From 9919fac6b5f55b919c72629deecb7418cfabff3b Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Thu, 27 May 2010 09:26:15 -0400 Subject: [PATCH] Rails 2.3.8: Hash#deep_merge fails for HashWithIndifferentAccess [#4702 state:resolved] --- .../core_ext/hash/indifferent_access.rb | 16 ++++++++++++++++ activesupport/test/core_ext/hash_ext_test.rb | 17 +++++++++++++++++ 2 files changed, 33 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..24c520a 100644 --- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb +++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb @@ -111,6 +111,22 @@ class HashWithIndifferentAccess < Hash Hash.new(default).merge(self) end + def deep_merge(other_hash) + dup = self.dup + other_hash.each_pair do |key, value| + key = convert_key(key) + oldval = dup[key] + newval = convert_value(value) + + oldval = oldval.to_hash if oldval.respond_to?(:to_hash) + newval = newval.to_hash if newval.respond_to?(:to_hash) + + merged_value = oldval.kind_of?(Hash) && newval.kind_of?(Hash) ? oldval.deep_merge(newval) : newval + dup.regular_writer(key, merged_value) + end + dup + end + protected def convert_key(key) key.kind_of?(Symbol) ? key.to_s : key diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 44308c3..ca080e6 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -263,6 +263,23 @@ class HashExtTest < Test::Unit::TestCase assert_equal expected, hash_1 end + def test_deep_merge_on_indifferent_access + 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) + + assert_equal( { :a => "a", :b => "b", :c => { :c1 => "c1", :c2 => "c2", :c3 => { :d1 => "d1" } } }.with_indifferent_access, + hash_1, + 'Original hash should not have been changed') + + 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.5.2