From d60cfd2aa011bef07f171acfecf8119168fb3b4b Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Wed, 26 May 2010 20:59:49 -0400 Subject: [PATCH] Rails 2.3.8: Hash#deep_merge fails for HashWithIndifferentAccess [#4702 state:resolved] --- .../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..4d4af53 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,21 @@ class HashWithIndifferentAccess < Hash Hash.new(default).merge(self) end + def deep_merge(other_hash) + other_hash.each_pair do |key, value| + key = convert_key(key) + oldval = self[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 + self.regular_writer(key, merged_value) + end + self + 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..e98327c 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_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) + + 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