# :stopdoc: # This module extends the native Ruby Hash class to support deep merging # and comparing the difference between hashes. # This functionality mimics that found in ActiveSupport # @see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/deep_merge.rb # module Archetype::Functions::Hash # # recursively merge two hashes with deep merging # # *Parameters*: # - +other_hash+ {Hash} the other hash to merge with # *Returns*: # - {Hash} a new hash containing the contents of other_hash and the contents of hsh, deep merged # def rmerge(other_hash, &block) dup.rmerge!(other_hash, &block) end # # adds the contents of other_hash to hsh, deep merged # # *Parameters*: # - +other_hash+ {Hash} the other hash to merge with # *Returns*: # - {Hash} the original hash with the addition of the contents of other_hash # def rmerge!(other_hash, &block) other_hash.each_pair do |k,v| tv = self[k] if tv.is_a?(Hash) && v.is_a?(Hash) self[k] = tv.rmerge(v, &block) else self[k] = block && tv ? block.call(k, tv, v) : v end end return self end # # get the difference of another hash # # *Parameters*: # - +other_hash+ {Hash} the other hash to compare against # *Returns*: # - {Hash} a representation of the difference between the two hashes # def diff(other_hash) (self.keys + other_hash.keys).uniq.inject(Archetype::Hash.new) do |tmp, key| item_1, item_2 = self[key], other_hash[key] # special comparison for gradients are_gradients = (item_1.class == item_2.class) && (item_1.is_a?(Compass::Core::SassExtensions::Functions::GradientSupport::LinearGradient) or item_1.is_a?(Compass::Core::SassExtensions::Functions::GradientSupport::RadialGradient)) eq_gradients = are_gradients ? (item_1.to_s == item_2.to_s) : true unless item_1 == item_2 and eq_gradients if item_1.kind_of?(Hash) and item_2.kind_of?(Hash) tmp[key] = item_1.diff(item_2) else tmp[key] = item_2 || Archetype::Functions::CSS.default(key) # if the key is `filter-gradient` and it was removed, we need to change the key to `ie-filter` tmp['ie-filter'] = Archetype::Functions::CSS.default('ie-filter') if key == 'filter-gradient' and tmp[key].nil? # if it came back as `nil` we couldn't understand it or it has no default, so axe it tmp.delete(key) if tmp[key].nil? end end tmp end end unless self.respond_to?(:to_h) def to_h return self end end end