Skip to content

Commit e0e2c7e

Browse files
committed
Merge nil values or keep the original via an option
For some people, it's unexpected that explicitly merging in a nil will not overwrite an existing value. `DeepMerge::deep_merge({:a => nil}, {:a => 1})` Currently, we retain the 1 value. My expectation is we'd get a nil value. Since changing this is a change in behavior, and possibly not desirable, I'm exposing an option to opt-in to this new behavior. Note, this is related to danielsdeleo#20 and can be confusing to see the difference. This commit handles merging a nil value into an existing destination via an option. PR danielsdeleo#20 handles NOT merging a value into an already nil destination.
1 parent 989b2df commit e0e2c7e

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ Push src elements to existing arrays, instead of overwriting them.
9999
dest.deep_merge!(source, {:extend_existing_arrays => true})
100100
Results: {"property" => ["1", "2", "3", "4"]}
101101

102+
**:merge_nil_values**
103+
104+
The purpose of this option is to allow nil hash values to be merged. The prior behavior was to discard nil hash values and remains the default if not specified.
105+
106+
source = {"item" => nil}
107+
dest = {"item" => "existing"}
108+
dest.deep_merge!(source, {:merge_nil_values => true})
109+
Results: {"item" => nil}
110+
102111
There are many tests for this library - and you can learn more about the features and usages of deep_merge! by just browsing the test examples.
103112

104113
Using deep_merge in Rails

lib/deep_merge/core.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,12 @@ def self.deep_merge!(source, dest, options = {})
9494
extend_existing_arrays = options[:extend_existing_arrays] || false
9595
# request that arrays keep duplicate elements
9696
keep_array_duplicates = options[:keep_array_duplicates] || false
97+
# request that nil values are merged or skipped (Skipped/false by default)
98+
merge_nil_values = options[:merge_nil_values] || false
9799

98100
di = options[:debug_indent] || ''
99101
# do nothing if source is nil
100-
return dest if source.nil?
102+
return dest if !merge_nil_values && source.nil?
101103
# if dest doesn't exist, then simply copy source to it
102104
if !(dest) && overwrite_unmergeable
103105
dest = source; return dest

test/test_deep_merge.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,16 @@ def test_deep_merge
630630
DeepMerge::deep_merge!(hash_src, hash_dst, {:keep_array_duplicates => true})
631631
assert_equal({"item" => ["1", "2", "2", "3"]}, hash_dst)
632632

633+
# Don't merge nil values by default
634+
hash_src = {"item" => nil}
635+
hash_dst = {"item" => "existing"}
636+
DeepMerge::deep_merge!(hash_src, hash_dst)
637+
assert_equal({"item" => "existing"}, hash_dst)
633638

634-
639+
# Merge nil values via an explicit: :merge_nil_values => true
640+
hash_src = {"item" => nil}
641+
hash_dst = {"item" => "existing"}
642+
DeepMerge::deep_merge!(hash_src, hash_dst, {:merge_nil_values => true})
643+
assert_equal({"item" => nil}, hash_dst)
635644
end # test_deep_merge
636645
end

0 commit comments

Comments
 (0)