def self.field name, opts={}
@fields ||= []
raise ModelError, "field with name #{name} already defined" if @fields.any? { |k, v| k == name }
@fields << [name, opts]
if opts[:multi]
single_name = name.to_s.sub(/s$/, "")
define_method "add_#{single_name}" do |obj|
array = send(name)
raise ModelError, "already has a #{single_name} with name #{obj.name.inspect}" if obj.respond_to?(:name) && array.any? { |o| o.name == obj.name }
changed!
@serialized_values.delete name
array << obj
end
define_method "drop_#{single_name}" do |obj|
return unless @values[name].delete obj
@serialized_values.delete name
changed!
obj
end
end
define_method "#{name}=" do |o|
changed!
@serialized_values.delete name
@values[name] = o
end
define_method "__serialized_#{name}=" do |o|
changed!
@values.delete name
@serialized_values[name] = o
end
define_method "__serialized_#{name}" do
@serialized_values[name]
end
define_method name do
return @values[name] if @values.member?(name)
@values[name] = deserialized_form_of name, @serialized_values[name]
end
end