lib/spontaneous/collections/field_set.rb in spontaneous-0.2.0.alpha2 vs lib/spontaneous/collections/field_set.rb in spontaneous-0.2.0.alpha3
- old
+ new
@@ -6,48 +6,74 @@
attr_reader :owner
def initialize(owner, initial_values)
super()
@owner = owner
- initialize_from_prototypes(initial_values)
+ @field_data = initial_values
+ initialize_from_prototypes
end
- def initialize_from_prototypes(initial_values)
- values = (initial_values || []).map do |value|
- value = S::FieldTypes.deserialize_field(value)
- [Spontaneous.schema.uids[value[:id]], value]
- end
- values = Hash[values]
- owner.field_prototypes.each do |field_prototype|
- field = field_prototype.to_field(values[field_prototype.schema_id])
- add_field(field)
- end
- end
def serialize_db
self.map { |field| field.serialize_db }
end
def export(user)
- owner.class.field_names.map do |name|
- self[name].export(user)
- end
+ owner.class.field_names.
+ select { |name| owner.field_writable?(user, name) }.
+ map { |name| self[name].export(user) }
end
def saved
self.each { |field| field.mark_unmodified }
end
+ # Lazily load fields by name
+ def named(name)
+ super || load_field(owner.field_prototypes[name.to_sym])
+ end
+
protected
- def add_field(field)
- field.owner = owner
- getter_name = field.name
- setter_name = "#{field.name}="
- self[field.name.to_sym] = field
+ def initialize_from_prototypes
+ owner.field_prototypes.each do |field_prototype|
+ add_field(field_prototype)
+ end
+ end
+
+ def field_values
+ @field_values ||= parse_field_data(@field_data)
+ end
+
+ def parse_field_data(initial_values)
+ values = (initial_values || []).map do |value|
+ value = S::FieldTypes.deserialize_field(value)
+ [Spontaneous.schema.uids[value[:id]], value]
+ end
+ Hash[values]
+ end
+
+ # overwritten because otherwise the iterators in PrototypeSet don't
+ # know which keys we are supposed to have
+ def local_order
+ owner.field_prototypes.keys
+ end
+
+ def add_field(field_prototype)
+ name = field_prototype.name
+ getter_name = name
+ setter_name = "#{name}="
singleton_class.class_eval do
- define_method(getter_name) { |*args| field.tap { |f| f.template_params = args } }
- define_method(setter_name) { |value| field.value = value }
+ define_method(getter_name) { |*args| named(name).tap { |f| f.template_params = args } }
+ define_method(setter_name) { |value| named(name).value = value }
+ end
+ end
+
+ def load_field(field_prototype)
+ return nil if field_prototype.nil?
+ field_prototype.to_field(owner, field_values[field_prototype.schema_id]).tap do |field|
+ field.owner = owner
+ self[field_prototype.name] = field
end
end
end
end