Module: SimpleMapper::Attribute::Collection
- Included in:
- Pattern
- Defined in:
- lib/simple_mapper/attribute/collection.rb
Overview
Include in a SimpleMapper::Attribute to give it collection behaviors:
* have an attribute be a collection (i.e. a hash or array) of values
rather than a single value
* map N keys from a source value to the attribute, based on the +:member_key?+ test
* map keys/values from the collection object back to a "source" structure
Instance Method Summary collapse
-
#apply_type(value) ⇒ Object
If the receiver has a valid type specified, returns a new collection based on value, with the key/value pairs from value but each value encoded by the type converter.
- #changed?(object) ⇒ Boolean
- #freeze_for(object) ⇒ Object
-
#from_simple_key(key) ⇒ Object
Given a key from the source structure (the “simple structure”), returns a transformed key as it will be entered in the attribute’s collection value.
- #member_key?(key) ⇒ Boolean
-
#new_collection ⇒ Object
Returns a new collection object to be used as the basis for building the attribute’s value collection; by default, returns instances of SimpleMapper::Collection::Hash.
- #source_value(object) ⇒ Object
-
#to_simple(object, container, options = {}) ⇒ Object
Converts the object’s attribute value into its simple representation, putting the keys/values into container.
-
#to_simple_key(key) ⇒ Object
The reverse of
:to_simple_key
, given a key from the attribute collection, returns the transformed version of that key as it should appear in the “simple” representation of the object. -
#transformed_source_value(object) ⇒ Object
Given an object that has the attribute represented by the receiver, returns the source value for the attribute after applying defaults and types.
Instance Method Details
#apply_type(value) ⇒ Object
If the receiver has a valid type specified, returns a new collection based on value, with the key/value pairs from value but each value encoded by the type converter.
37 38 39 40 41 42 43 |
# File 'lib/simple_mapper/attribute/collection.rb', line 37 def apply_type(value) converter = self.converter value.inject(new_collection) do |hash, keyval| hash[keyval[0]] = converter.decode(keyval[1]) hash end end |
#changed?(object) ⇒ Boolean
83 84 85 86 87 88 |
# File 'lib/simple_mapper/attribute/collection.rb', line 83 def changed?(object) val = value(object) return true if val.changed_members.size > 0 return true if mapper and val.find {|keyval| keyval[1].changed?} false end |
#freeze_for(object) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/simple_mapper/attribute/collection.rb', line 69 def freeze_for(object) val = value(object) if val if mapper if val.respond_to?(:values) val.values.each {|member| member.freeze} else val.each {|member| member.freeze} end end val.freeze end end |
#from_simple_key(key) ⇒ Object
Given a key from the source structure (the “simple structure”), returns a transformed key as it will be entered in the attribute’s collection value. By default, this simply passes through key, but it can be overridden to allow for more sophisticated source/object mappings.
58 59 60 |
# File 'lib/simple_mapper/attribute/collection.rb', line 58 def from_simple_key(key) key end |
#member_key?(key) ⇒ Boolean
23 24 25 |
# File 'lib/simple_mapper/attribute/collection.rb', line 23 def member_key?(key) false end |
#new_collection ⇒ Object
Returns a new collection object to be used as the basis for building the attribute’s value collection; by default, returns instances of SimpleMapper::Collection::Hash. Override this to alter the kinds of collections your attributes work with.
48 49 50 51 52 |
# File 'lib/simple_mapper/attribute/collection.rb', line 48 def new_collection h = SimpleMapper::Collection::Hash.new h.attribute = self h end |
#source_value(object) ⇒ Object
27 28 29 30 31 32 |
# File 'lib/simple_mapper/attribute/collection.rb', line 27 def source_value(object) object.simple_mapper_source.inject(new_collection) do |hash, keyval| hash[from_simple_key(keyval[0])] = keyval[1] if member_key?(keyval[0]) hash end end |
#to_simple(object, container, options = {}) ⇒ Object
Converts the object’s attribute value into its simple representation, putting the keys/values into container. This is conceptually consistent with SimpleMapper::Attributes#to_simple, but adds a few collection-oriented concerns:
* the attribute's value is assumed to be a collection with N key/value pairs
to be mapped into _container_
* the keys are transformed via +:to_simple_key+ on their way into _container_.
This will work with any kind of container that can be assigned to via []=
, and any value for the attribute that supports :inject
in the same manner as a Hash (yields the accumulated value and a key/value pair to the block).
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/simple_mapper/attribute/collection.rb', line 101 def to_simple(object, container, = {}) val = value(object) mapper = self.mapper strings = [:string_keys] || false changed_members = change_tracking_for(val) if [:changed] if mapper change_proc = Proc.new do |key, val| changed_members[key] or (! val.nil? and val.changed?) end else change_proc = Proc.new {|k, v| changed_members[k]} end else change_proc = nil end changes = [:changed] || false container = val.inject(container) do |hash, keyvalue| key = to_simple_key(keyvalue[0]) hash[strings ? key.to_s : key] = mapper ? keyvalue[1].to_simple() : encode(keyvalue[1]) if ! change_proc or change_proc.call(*keyvalue) hash end if (change_proc or [:all]) and ! [:defined] changed_members.keys.find_all {|x| ! val.is_member?(x)}.each do |key| container[to_simple_key(key)] = nil end end container end |
#to_simple_key(key) ⇒ Object
The reverse of :to_simple_key
, given a key from the attribute collection, returns the transformed version of that key as it should appear in the “simple” representation of the object.
65 66 67 |
# File 'lib/simple_mapper/attribute/collection.rb', line 65 def to_simple_key(key) key end |
#transformed_source_value(object) ⇒ Object
Given an object that has the attribute represented by the receiver, returns the source value for the attribute after applying defaults and types. The type check is applied to either the raw source value (if one exists) or the default value (if no source exists and a default was specified for the attribute).
Type checking is not enforced here; it is expected that :source_value
, :default_value
, and :apply_type
will all return objects of the expected collection type (or consistent interface).
15 16 17 18 19 20 21 |
# File 'lib/simple_mapper/attribute/collection.rb', line 15 def transformed_source_value(object) val = source_value(object) val = default_value(object) if val.nil? val = apply_type(val) if type val.change_tracking = true if val.respond_to?(:change_tracking) val end |