Module: Ecoportal::API::Common::Content::DoubleModel::Attributable::Nesting::CascadedCallback::InstanceMethods
- Defined in:
- lib/ecoportal/api/common/content/double_model/attributable/nesting/cascaded_callback.rb
Overview
Note:
this happens at instance level (not tracked at class level)
We offer helpers to implement cascaded callbacks to nested objects
i.e. #as_update or #dirty?
Instance Method Summary collapse
-
#cascaded_callback(value = nil, method:, args: [], kargs: {}, path: [], recurs: true) {|result, value, key_path, object| ... } ⇒ Variant
Method to go through all the embedded properties recursively.
-
#cascaded_reduce(init = nil, recurs: false, trace: nil, &block) ⇒ Object
Trace = Struct.new(:subject, :nested_attrs, :obj_key_path).
Instance Method Details
#cascaded_callback(value = nil, method:, args: [], kargs: {}, path: [], recurs: true) {|result, value, key_path, object| ... } ⇒ Variant
Note:
Be aware that
- It does NOT natively discard
root?objects. You will need to explicitly do this in the block callback. - If
methodcalls in turn tocascaded_callback, to prevent double-recursion you MUST userecurs: false. The problem with this approach is thatkey_pathfrom the original object that calledcascaded_callbackis lost. For which you should probably rather usecascaded_reduce. - It already does a first call on
self.method, might it respond to. And it will notyieldin this first call.
Note:
the cascaded_callback will end were:
- The current object does NOT respond to
method. - The current object does NOT have nested properties. So where
the object does not have any
_cascaded_attributes.
Method to go through all the embedded properties recursively.
95 96 97 98 99 100 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/ecoportal/api/common/content/double_model/attributable/nesting/cascaded_callback.rb', line 95 def cascaded_callback( value = nil, method:, args: [], kargs: {}, path: [], recurs: true, &block ) method = method.to_sym return value unless respond_to?(method, true) value = if path.empty? # Don't yield on the first call send(method, *args, **kargs) else yield( value, send(method, *args, **kargs), path, self ) end return value unless respond_to?(:_cascaded_attributes) _cascaded_attributes.reduce(value) do |val, (attribute, obj_k)| next val unless (obj = send(attribute)) next val unless obj.respond_to(method, true) obj_path = path.dup.push(obj_k) # next val if obj_path.empty? unless obj.respond_to?(:cascaded_callback) next yield( val, obj.send(method, *args, **kargs), obj_path, obj ) end next val unless recurs obj.cascaded_callback( val, method: method, args: args, kargs: kargs, path: obj_path, recurs: recurs, &block ) end end |
#cascaded_reduce(init = nil, recurs: false, trace: nil, &block) ⇒ Object
Trace = Struct.new(:subject, :nested_attrs, :obj_key_path)
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/ecoportal/api/common/content/double_model/attributable/nesting/cascaded_callback.rb', line 153 def cascaded_reduce(init = nil, recurs: false, trace: nil, &block) trace ||= {} trace = _cascaded_attributes_trace(recurs: recurs) if trace.empty? return init if trace.empty? params = i[subject key key_path attributes] subject, key, key_path, attributes = trace.values_at(*params) value = yield(init, subject, key, key_path, trace) return value if attributes.nil? || attributes.empty? attributes.reduce(value) do |mem, (_attr, subtrace)| cascaded_reduce(mem, recurs: recurs, trace: subtrace, &block) end end |