lib/jinx/resource/mergeable.rb in jinx-2.1.2 vs lib/jinx/resource/mergeable.rb in jinx-2.1.3
- old
+ new
@@ -21,37 +21,37 @@
# If other is not a Hash, then the other object's attributes values are merged into
# this object. The default attributes is this mergeable's class
# {Propertied#mergeable_attributes}.
#
# The merge is performed by calling {#merge_attribute} on each attribute with the matches
- # and merger block given to this method.
+ # and filter block given to this method.
#
# @param [Mergeable, {Symbol => Object}] other the source domain object or value hash to merge from
# @param [<Symbol>, nil] attributes the attributes to merge (default {Propertied#nondomain_attributes})
# @param [{Resource => Resource}, nil] the optional merge source => target reference matches
- # @yield [attribute, oldval, newval] the optional merger block
- # @yieldparam [Symbol] attribute the merge target attribute
- # @yieldparam oldval the current merge attribute value
- # @yieldparam newval the new merge attribute value
+ # @yield [value] the optional filter block
+ # @yieldparam value the source merge attribute value
# @return [Mergeable] self
# @raise [ArgumentError] if none of the following are true:
# * other is a Hash
# * attributes is non-nil
# * the other class responds to +mergeable_attributes+
- def merge_attributes(other, attributes=nil, matches=nil, &merger)
+ def merge_attributes(other, attributes=nil, matches=nil, &filter)
return self if other.nil? or other.equal?(self)
attributes = [attributes] if Symbol === attributes
attributes ||= self.class.mergeable_attributes
# if the source object is not a hash, then convert it to an attribute => value hash
vh = Hashable === other ? other : other.value_hash(attributes)
# merge the value hash
- vh.each { |pa, value| merge_attribute(pa, value, matches, &merger) }
+ vh.each { |pa, value| merge_attribute(pa, value, matches, &filter) }
self
end
- alias :merge :merge_attributes
+ def merge(*args, &filter)
+ merge_attributes(*args, &filter)
+ end
alias :merge! :merge
# Merges the value newval into the attribute as follows:
# * If the value is nil, empty or equal to the current attribute value, then no merge
@@ -75,22 +75,29 @@
# @yieldparam (see #merge_attributes)
# @return the merged attribute value
def merge_attribute(attribute, newval, matches=nil)
# the previous value
oldval = send(attribute)
- # If nothing to merge or a block can take over, then bail.
- if newval.nil? or mergeable__equal?(oldval, newval) then
- return oldval
- elsif block_given? then
- return yield(attribute, oldval, value)
+ # Filter the newval into the srcval.
+ srcval = if newval and block_given? then
+ if newval.collection? then
+ newval.select { |v| yield(v) }
+ elsif yield(newval) then
+ newval
+ end
+ else
+ newval
end
+ # If there is no point in merging, then bail.
+ return oldval if srcval.nil_or_empty? or mergeable__equal?(oldval, newval)
+
# Discriminate between a domain and non-domain attribute.
prop = self.class.property(attribute)
if prop.domain? then
- merge_domain_property_value(prop, oldval, newval, matches)
+ merge_domain_property_value(prop, oldval, srcval, matches)
else
- merge_nondomain_property_value(prop, oldval, newval)
+ merge_nondomain_property_value(prop, oldval, srcval)
end
end
private