From d0868ba96443904cbcee3eb91302c1957647d604 Mon Sep 17 00:00:00 2001 From: Andrew Moreland Date: Sat, 8 Aug 2009 20:49:57 -0700 Subject: [PATCH] This commit allows hashes with indifferent access to be deep_merged. --- .../core_ext/hash/indifferent_access.rb | 15 +++++++++++++++ activesupport/test/core_ext/hash_ext_test.rb | 12 ++++++++++++ 2 files changed, 27 insertions(+), 0 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb index 34ba8a0..84e2683 100644 --- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb +++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb @@ -97,6 +97,21 @@ class HashWithIndifferentAccess < Hash super other_hash.with_indifferent_access end + # Performs a deep_merge on a HashWithIndifferentAccess, returning a new HashWithIndifferentAccess with +self+ and +other_hash+ merged recursively. + def deep_merge(other_hash) + target = dup + other_hash.each_pair do |k,v| + target[k].is_a?(Hash) && v.is_a?(Hash) ? target[k] = target[k].deep_merge(v) : target[k] = v + end + target + end + + # Returns a new HashWithIndifferentAccess with +self+ and +other_hash+ merged recursively. + # Modifies the receiver in place. + def deep_merge!(other_hash) + replace(deep_merge(other_hash)) + end + # Removes a specified key from the hash. def delete(key) super(convert_key(key)) diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index c58c0ac..a0fd40c 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -263,6 +263,18 @@ class HashExtTest < Test::Unit::TestCase assert_equal expected, hash_1 end + def test_deep_merge_on_indifferent + hash_1 = HashWithIndifferentAccess.new({ :a => "a", :b => "b", :c => { :c1 => "c1", :c2 => "c2", :c3 => { :d1 => "d1" } } }) + hash_2 = HashWithIndifferentAccess.new({ :a => 1, :c => { :c1 => 2, :c3 => { :d2 => "d2" } } }) + hash_3 = { :a => 1, :c => { :c1 => 2, :c3 => { :d2 => "d2" } } } + expected = { "a" => 1, "b" => "b", "c" => { "c1" => 2, "c2" => "c2", "c3" => { "d1" => "d1", "d2" => "d2" } } } + assert_equal expected, hash_1.deep_merge(hash_2) + assert_equal expected, hash_1.deep_merge(hash_3) + hash_1.deep_merge!(hash_2) + assert_equal expected, hash_1 + + end + def test_reverse_merge defaults = { :a => "x", :b => "y", :c => 10 }.freeze options = { :a => 1, :b => 2 } -- 1.6.3.3