Module: Gorillib::Resolution
- Extended by:
- Concern
- Includes:
- FancyBuilder
- Included in:
- Ironfan::Dsl
- Defined in:
- lib/gorillib/resolution.rb
Overview
The attribute :underlay provides an object (preferably another
Gorillib::Model or the like) that will resolve stacked
defaults. If fields are declared with a :resolver, it will
apply that call in preference the default rules (self.field
-> underlay.field -> self.field.default )
To provide resolve cleanly without read-write loops destroying
the separation of concerns, the resolve mechanism has been
broken from the regular read-write accessors.
Instance Attribute Summary collapse
-
#underlay ⇒ Object
Returns the value of attribute underlay.
Instance Method Summary collapse
-
#deep_resolve(field_name) ⇒ Object
This is one of two methods used to resolve Gorillib collections.
-
#merge_resolve(field_name) ⇒ Object
This is one of two methods used to resolve Gorillib collections.
-
#merge_values(target, value = nil) ⇒ Object
This method makes the assumption that target and value are both instances of either Gorillib::Model or Gorillib::Collection.
- #read_resolved_attribute(field_name) ⇒ Object
- #read_set_attribute(field_name) ⇒ Object
- #read_set_or_underlay_attribute(field_name) ⇒ Object
- #read_underlay_attribute(field_name) ⇒ Object
-
#resolve ⇒ Object
Return a fully-resolved copy of this object.
- #resolve! ⇒ Object
- #resolve_value(value) ⇒ Object
Instance Attribute Details
#underlay ⇒ Object
Returns the value of attribute underlay.
59 60 61 |
# File 'lib/gorillib/resolution.rb', line 59 def underlay @underlay end |
Instance Method Details
#deep_resolve(field_name) ⇒ Object
This is one of two methods used to resolve Gorillib collections. (The other is merge_resolve.) It simply resolves the field and returns the result. In case the field is a gorillib collection, it resolves each item in the collection.
89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/gorillib/resolution.rb', line 89 def deep_resolve(field_name) temp = read_set_or_underlay_attribute(field_name) return if temp.nil? if temp.is_a? Gorillib::Collection result = temp.class.new temp.each_pair {|k,v| result[k] = resolve_value(v) } else result = resolve_value(result) end result end |
#merge_resolve(field_name) ⇒ Object
This is one of two methods used to resolve Gorillib collections. (The other is deep_resolve.) It returns the result of merging the value of a field with the value of that field on the parent (underlay) of this object.
113 114 115 116 117 118 119 |
# File 'lib/gorillib/resolution.rb', line 113 def merge_resolve(field_name) field = self.class.fields[field_name] or return result = field.type.new merge_values(result,read_underlay_attribute(field_name)) merge_values(result,read_set_attribute(field_name)) result end |
#merge_values(target, value = nil) ⇒ Object
This method makes the assumption that target and value are both instances of either Gorillib::Model or Gorillib::Collection. They should be the same type.
This method is called for its side-effects on the ‘target’ parameter.
In case they are both models, target.receive!(value) is called.
In case they are both collections, target.receive!(v) is called, for each k,v in value.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/gorillib/resolution.rb', line 135 def merge_values(target, value=nil) value ||= {} if target.is_a? Gorillib::Collection value.each_pair do |k,v| existing = target[k] if existing && existing.respond_to?(:receive!) target[k].receive! v elsif existing && existing.respond_to?(:merge!) target[k].merge! v else target[k] = v end end else target.receive! value end end |
#read_resolved_attribute(field_name) ⇒ Object
153 154 155 156 |
# File 'lib/gorillib/resolution.rb', line 153 def read_resolved_attribute(field_name) field = self.class.fields[field_name] or return self.send(field.resolver, field_name) end |
#read_set_attribute(field_name) ⇒ Object
158 159 160 161 |
# File 'lib/gorillib/resolution.rb', line 158 def read_set_attribute(field_name) attr_name = "@#{field_name}" instance_variable_get(attr_name) if instance_variable_defined?(attr_name) end |
#read_set_or_underlay_attribute(field_name) ⇒ Object
168 169 170 171 172 |
# File 'lib/gorillib/resolution.rb', line 168 def read_set_or_underlay_attribute(field_name) result = read_set_attribute(field_name) return result unless result.nil? read_underlay_attribute(field_name) end |
#read_underlay_attribute(field_name) ⇒ Object
163 164 165 166 |
# File 'lib/gorillib/resolution.rb', line 163 def read_underlay_attribute(field_name) return if underlay.nil? Gorillib.deep_copy(underlay.read_resolved_attribute(field_name)) end |
#resolve ⇒ Object
Return a fully-resolved copy of this object. All objects
referenced will be clean deep_copies, and will lack the
:underlay accessor. This is by design, to prevent self-
referential loops (parent->collection->child->owner)
when deep_coping.
66 67 68 69 70 71 72 73 |
# File 'lib/gorillib/resolution.rb', line 66 def resolve result = self.class.new self.class.fields.each do |field_name, field| value = read_resolved_attribute(field_name) result.write_attribute(field_name, value) unless value.nil? end result end |
#resolve! ⇒ Object
75 76 77 78 79 80 81 |
# File 'lib/gorillib/resolution.rb', line 75 def resolve! resolved = resolve self.class.fields.each do |field_name, field| write_attribute(field_name, resolved.send(field_name.to_sym)) end self end |
#resolve_value(value) ⇒ Object
101 102 103 104 105 |
# File 'lib/gorillib/resolution.rb', line 101 def resolve_value(value) return if value.nil? return value.resolve if value.respond_to? :resolve deep_copy(value) end |