Skip to content

Instantly share code, notes, and snippets.

@tcocca
Created March 2, 2010 19:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tcocca/319817 to your computer and use it in GitHub Desktop.
Save tcocca/319817 to your computer and use it in GitHub Desktop.
# adapted from: http://github.com/railsmachine/shadow_puppet/blob/master/lib/shadow_puppet/core_ext.rb
require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/core_ext/array'
require 'active_support/inflector'
require 'active_support/core_ext/class/inheritable_attributes'
require 'active_support/core_ext/duplicable'
class Hash #:nodoc:
def deep_merge(other_hash)
self.merge(other_hash) do |key, oldval, newval|
oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
newval = newval.to_hash if newval.respond_to?(:to_hash)
if oldval.is_a?(Hash) && newval.is_a?(Hash)
oldval.deep_merge(newval)
elsif oldval.is_a?(Array) && newval.is_a?(Array)
oldval += newval
else
newval
end
end
end
def deep_merge!(other_hash)
replace(deep_merge(other_hash))
end
def deep_symbolize_keys
self.inject({}) { |result, (key, value)|
value = value.deep_symbolize_keys if value.is_a?(Hash)
result[(key.to_sym rescue key) || key] = value
result
}
end
end
>> hash1 = {:name => "Tom", :with => {:no_fee => 1}, :without => {}, :conditions => {:town_id => 1}, :include => [:town, :state]}
=> {:include=>[:town, :state], :with=>{:no_fee=>1}, :without=>{}, :conditions=>{:town_id=>1}, :name=>"Tom"}
>> hash2 = {:name => "Thomas", :with => {}, :without => {:state_id => 1}, :conditions => {:state_id => 2}, :include => [:neighborhood]}
=> {:include=>[:neighborhood], :with=>{}, :without=>{:state_id=>1}, :conditions=>{:state_id=>2}, :name=>"Thomas"}
>> hash1.deep_merge!(hash2)
=> {:include=>[:town, :state, :neighborhood], :without=>{:state_id=>1}, :with=>{:no_fee=>1}, :conditions=>{:state_id=>2, :town_id=>1}, :name=>"Thomas"}
>> hash1 = {:name => "Tom", :with => {:no_fee => 1}, :without => {}, :conditions => {:town_id => 1}, :include => [:town, :state]}
=> {:include=>[:town, :state], :with=>{:no_fee=>1}, :without=>{}, :conditions=>{:town_id=>1}, :name=>"Tom"}
>> hash2 = {:name => "Thomas", :with => {}, :without => {:state_id => 1}, :conditions => {:state_id => 2}, :include => [:neighborhood]}
=> {:include=>[:neighborhood], :with=>{}, :without=>{:state_id=>1}, :conditions=>{:state_id=>2}, :name=>"Thomas"}
>> hash1.merge!(hash2) do |key,old_val,new_val|
if old_val.is_a?(Array)
old_val += new_val
elsif old_val.is_a?(String)
new_val
else
old_val.merge!(new_val)
end
end
=> {:include=>[:town, :state, :neighborhood], :with=>{:no_fee=>1}, :without=>{:state_id=>1}, :conditions=>{:state_id=>2, :town_id=>1}, :name=>"Thomas"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment