lib/frenchy/model.rb in frenchy-0.3.0 vs lib/frenchy/model.rb in frenchy-0.4.0
- old
+ new
@@ -5,11 +5,10 @@
base.class_eval do
self.fields = {}
self.defaults = {}
end
-
end
# Create a new instance of this model with the given attributes
def initialize(attrs={})
attrs.stringify_keys!
@@ -52,11 +51,10 @@
def set(name, value)
instance_variable_set("@#{name}", value)
end
module ClassMethods
-
# Class accessors
def fields; @fields; end
def defaults; @defaults; end
def fields=(value); @fields = value; end
def defaults=(value); @defaults = value; end
@@ -68,10 +66,25 @@
define_method(:to_param) do
send(name).to_s
end
end
+ # Macro to create a subtype
+ def type(name, &block)
+ klass = Class.new(self) do
+ include Frenchy::Model
+ end
+ const_set(name.to_s.camelize, klass)
+ klass.class_eval(&block)
+ end
+
+ # Macro to create a subtype and associated field
+ def embed(name, options={}, &block)
+ type(name, &block)
+ field(name, options.merge({type: name}))
+ end
+
# Macro to add a field
def field(name, options={})
name = name.to_s
options.stringify_keys!
@@ -118,10 +131,14 @@
# Convert value to a Time or DateTime. Numbers are treated as unix timestamps,
# other values are parsed with DateTime.parse.
define_method("#{name}=") do |v|
if v.is_a?(Fixnum)
set(name, Time.at(v).to_datetime)
+ elsif v.is_a?(DateTime)
+ set(name, v)
+ elsif v.is_a?(Time)
+ set(name, v.to_datetime)
else
set(name, DateTime.parse(v))
end
end
@@ -144,10 +161,10 @@
end
else
# Unknown types have their type constantized and initialized with the value. This
# allows us to support things like other Frenchy::Model classes, ActiveRecord models, etc.
- klass = (options["class_name"] || type.camelize).constantize
+ klass = const_get(options["class_name"] || type.camelize)
# Fields with many values have a default of [] (unless previously set above)
if options["many"]
options["default"] ||= []
end