Skip to content

Instantly share code, notes, and snippets.

@masqita
Created November 4, 2011 15:13
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save masqita/1339540 to your computer and use it in GitHub Desktop.
Save masqita/1339540 to your computer and use it in GitHub Desktop.
TypeCaster module
class Boolean
def self.from_json(value)
if value.is_a?(TrueClass) || value.is_a?(FalseClass)
return value
elsif value.is_a?(String)
return value == ("true" || "1")
elsif value.is_a?(Integer)
return value == 1
else
nil
end
end
end
def String.from_json(value); value.to_s; end
def Integer.from_json(value); value.to_i; end
def Float.from_json(value); value.to_f; end
def BigDecimal.from_json(value); BigDecimal.new(value.to_s); end
def Date.from_json(value); value.is_a?(Date) ? value : Date.parse(value); end
def Time.from_json(value); value.is_a?(Time) ? value : Time.parse(value); end
module TypeCaster
# Also see: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/concern.rb
extend ActiveSupport::Concern
module ClassMethods
def field(name, fieldtype = String, options = {})
attr_accessor name.to_sym
(@fields ||= HashWithIndifferentAccess.new).merge!({name => options.merge(:type => fieldtype)})
end
def inherited(subclass)
subclass.instance_variable_set("@fields", instance_variable_get("@fields").clone)
end
end
module InstanceMethods
def initialize(attrib = {})
attrib = HashWithIndifferentAccess.new(attrib)
attrib.stringify_keys!
fields.each do |name, options|
send("#{name}=", typecast(name,attrib[name.to_s]))
end
end
def typecast(name, value)
return fields[name.to_sym][:default] unless value
fieldtype = fields[name.to_sym][:type] || String
return fieldtype.from_json(value) unless value.is_a?(Array) || value.is_a?(Hash)
begin
klass = name.classify.constantize
if value.is_a?(Array)
coll = Array.new
value.each do |v|
coll << klass.new(v)
end
coll
else
klass.new(value)
end
rescue
value
end
end
def attributes
@attributes ||= Hash[fields.keys.collect{|a| [a, self.send(a)]}]
end
def fields
self.class.instance_variable_get("@fields")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment