summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Marty <jmarty@iexposure.com>2016-12-13 14:43:47 -0600
committerDaniel Doubrovkine (dB.) @dblockdotorg <dblock@dblock.org>2016-12-13 15:43:47 -0500
commit199d816bc0865d4276a1b6db669ef9f3a2fedfc1 (patch)
tree4156626d394cf98c30590bb14d2eab013364d084
parentfb7dd06af5189ef483f0a466d12ab52f2838b86f (diff)
downloadhashie-199d816bc0865d4276a1b6db669ef9f3a2fedfc1.tar.gz
Fix #385 - deep merge by reference bug (#386)
-rw-r--r--CHANGELOG.md2
-rw-r--r--lib/hashie/extensions/deep_merge.rb2
-rw-r--r--spec/hashie/extensions/deep_merge_spec.rb9
3 files changed, 10 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce04bb7..dd15125 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ scheme are considered to be bugs.
## [Unreleased][unreleased]
+* [#386](https://github.com/intridea/hashie/pull/386): Fix for #385: Make `deep_merge` always `deep_dup` nested hashes before merging them in so that there are no shared references between the two hashes being merged. - [@mltsy](https://github.com/mltsy).
+
[3.4.7]: https://github.com/intridea/hashie/compare/v3.4.6...master
### Added
diff --git a/lib/hashie/extensions/deep_merge.rb b/lib/hashie/extensions/deep_merge.rb
index df0887d..5d8fe34 100644
--- a/lib/hashie/extensions/deep_merge.rb
+++ b/lib/hashie/extensions/deep_merge.rb
@@ -26,7 +26,7 @@ module Hashie
if hash.key?(k) && block_given?
block.call(k, hash[k], v)
else
- v
+ v.respond_to?(:deep_dup) ? v.deep_dup : v
end
end
end
diff --git a/spec/hashie/extensions/deep_merge_spec.rb b/spec/hashie/extensions/deep_merge_spec.rb
index 0815c15..aec2d7d 100644
--- a/spec/hashie/extensions/deep_merge_spec.rb
+++ b/spec/hashie/extensions/deep_merge_spec.rb
@@ -14,8 +14,8 @@ describe Hashie::Extensions::DeepMerge do
context 'without &block' do
let(:h1) { subject.new.merge(a: 'a', a1: 42, b: 'b', c: { c1: 'c1', c2: { a: 'b' }, c3: { d1: 'd1' } }) }
- let(:h2) { { a: 1, a1: 1, c: { c1: 2, c2: 'c2', c3: { d2: 'd2' } } } }
- let(:expected_hash) { { a: 1, a1: 1, b: 'b', c: { c1: 2, c2: 'c2', c3: { d1: 'd1', d2: 'd2' } } } }
+ let(:h2) { { a: 1, a1: 1, c: { c1: 2, c2: 'c2', c3: { d2: 'd2' } }, e: { e1: 1 } } }
+ let(:expected_hash) { { a: 1, a1: 1, b: 'b', c: { c1: 2, c2: 'c2', c3: { d1: 'd1', d2: 'd2' } }, e: { e1: 1 } } }
it 'deep merges two hashes' do
expect(h1.deep_merge(h2)).to eq expected_hash
@@ -25,6 +25,11 @@ describe Hashie::Extensions::DeepMerge do
h1.deep_merge!(h2)
expect(h1).to eq expected_hash
end
+
+ it 'merges new nested hash entries by value, not by reference' do
+ h1.deep_merge!(h2)
+ expect { h1[:e][:e1] = 'changed' }.not_to change { h2[:e][:e1] }
+ end
end
context 'with &block' do