deep_merge 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,210 @@
1
+ module DeepMerge
2
+
3
+ class InvalidParameter < StandardError; end
4
+
5
+ DEFAULT_FIELD_KNOCKOUT_PREFIX = '--'
6
+
7
+ # Deep Merge core documentation.
8
+ # deep_merge! method permits merging of arbitrary child elements. The two top level
9
+ # elements must be hashes. These hashes can contain unlimited (to stack limit) levels
10
+ # of child elements. These child elements to not have to be of the same types.
11
+ # Where child elements are of the same type, deep_merge will attempt to merge them together.
12
+ # Where child elements are not of the same type, deep_merge will skip or optionally overwrite
13
+ # the destination element with the contents of the source element at that level.
14
+ # So if you have two hashes like this:
15
+ # source = {:x => [1,2,3], :y => 2}
16
+ # dest = {:x => [4,5,'6'], :y => [7,8,9]}
17
+ # dest.deep_merge!(source)
18
+ # Results: {:x => [1,2,3,4,5,'6'], :y => 2}
19
+ # By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
20
+ # To avoid this, use "deep_merge" (no bang/exclamation mark)
21
+ #
22
+ # Options:
23
+ # Options are specified in the last parameter passed, which should be in hash format:
24
+ # hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'})
25
+ # :preserve_unmergeables DEFAULT: false
26
+ # Set to true to skip any unmergeable elements from source
27
+ # :knockout_prefix DEFAULT: nil
28
+ # Set to string value to signify prefix which deletes elements from existing element
29
+ # :sort_merged_arrays DEFAULT: false
30
+ # Set to true to sort all arrays that are merged together
31
+ # :unpack_arrays DEFAULT: nil
32
+ # Set to string value to run "Array::join" then "String::split" against all arrays
33
+ # :merge_hash_arrays DEFAULT: false
34
+ # Set to true to merge hashes within arrays
35
+ # :merge_debug DEFAULT: false
36
+ # Set to true to get console output of merge process for debugging
37
+ #
38
+ # Selected Options Details:
39
+ # :knockout_prefix => The purpose of this is to provide a way to remove elements
40
+ # from existing Hash by specifying them in a special way in incoming hash
41
+ # source = {:x => ['--1', '2']}
42
+ # dest = {:x => ['1', '3']}
43
+ # dest.ko_deep_merge!(source)
44
+ # Results: {:x => ['2','3']}
45
+ # Additionally, if the knockout_prefix is passed alone as a string, it will cause
46
+ # the entire element to be removed:
47
+ # source = {:x => '--'}
48
+ # dest = {:x => [1,2,3]}
49
+ # dest.ko_deep_merge!(source)
50
+ # Results: {:x => ""}
51
+ # :unpack_arrays => The purpose of this is to permit compound elements to be passed
52
+ # in as strings and to be converted into discrete array elements
53
+ # irsource = {:x => ['1,2,3', '4']}
54
+ # dest = {:x => ['5','6','7,8']}
55
+ # dest.deep_merge!(source, {:unpack_arrays => ','})
56
+ # Results: {:x => ['1','2','3','4','5','6','7','8'}
57
+ # Why: If receiving data from an HTML form, this makes it easy for a checkbox
58
+ # to pass multiple values from within a single HTML element
59
+ #
60
+ # :merge_hash_arrays => merge hashes within arrays
61
+ # source = {:x => [{:y => 1}]}
62
+ # dest = {:x => [{:z => 2}]}
63
+ # dest.deep_merge!(source, {:merge_hash_arrays => true})
64
+ # Results: {:x => [{:y => 1, :z => 2}]}
65
+ #
66
+ # There are many tests for this library - and you can learn more about the features
67
+ # and usages of deep_merge! by just browsing the test examples
68
+ def self.deep_merge!(source, dest, options = {})
69
+ # turn on this line for stdout debugging text
70
+ merge_debug = options[:merge_debug] || false
71
+ overwrite_unmergeable = !options[:preserve_unmergeables]
72
+ knockout_prefix = options[:knockout_prefix] || nil
73
+ raise InvalidParameter, "knockout_prefix cannot be an empty string in deep_merge!" if knockout_prefix == ""
74
+ raise InvalidParameter, "overwrite_unmergeable must be true if knockout_prefix is specified in deep_merge!" if knockout_prefix && !overwrite_unmergeable
75
+ # if present: we will split and join arrays on this char before merging
76
+ array_split_char = options[:unpack_arrays] || false
77
+ # request that we sort together any arrays when they are merged
78
+ sort_merged_arrays = options[:sort_merged_arrays] || false
79
+ # request that arrays of hashes are merged together
80
+ merge_hash_arrays = options[:merge_hash_arrays] || false
81
+ di = options[:debug_indent] || ''
82
+ # do nothing if source is nil
83
+ return dest if source.nil?
84
+ # if dest doesn't exist, then simply copy source to it
85
+ if !(dest) && overwrite_unmergeable
86
+ dest = source; return dest
87
+ end
88
+
89
+ puts "#{di}Source class: #{source.class.inspect} :: Dest class: #{dest.class.inspect}" if merge_debug
90
+ if source.kind_of?(Hash)
91
+ puts "#{di}Hashes: #{source.inspect} :: #{dest.inspect}" if merge_debug
92
+ source.each do |src_key, src_value|
93
+ if dest.kind_of?(Hash)
94
+ puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug
95
+ if dest[src_key]
96
+ puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug
97
+ dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(:debug_indent => di + ' '))
98
+ else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!)
99
+ puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug
100
+ # note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
101
+ begin
102
+ src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty)
103
+ rescue TypeError
104
+ src_dup = src_value
105
+ end
106
+ dest[src_key] = deep_merge!(src_value, src_dup, options.merge(:debug_indent => di + ' '))
107
+ end
108
+ else # dest isn't a hash, so we overwrite it completely (if permitted)
109
+ if overwrite_unmergeable
110
+ puts "#{di} overwriting dest: #{src_key.inspect} => #{src_value.inspect} -over-> #{dest.inspect}" if merge_debug
111
+ dest = overwrite_unmergeables(source, dest, options)
112
+ end
113
+ end
114
+ end
115
+ elsif source.kind_of?(Array)
116
+ puts "#{di}Arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
117
+ # if we are instructed, join/split any source arrays before processing
118
+ if array_split_char
119
+ puts "#{di} split/join on source: #{source.inspect}" if merge_debug
120
+ source = source.join(array_split_char).split(array_split_char)
121
+ if dest.kind_of?(Array)
122
+ dest = dest.join(array_split_char).split(array_split_char)
123
+ end
124
+ end
125
+ # if there's a naked knockout_prefix in source, that means we are to truncate dest
126
+ if source.index(knockout_prefix)
127
+ dest = clear_or_nil(dest); source.delete(knockout_prefix)
128
+ end
129
+ if dest.kind_of?(Array)
130
+ if knockout_prefix
131
+ print "#{di} knocking out: " if merge_debug
132
+ # remove knockout prefix items from both source and dest
133
+ source.delete_if do |ko_item|
134
+ retval = false
135
+ item = ko_item.respond_to?(:gsub) ? ko_item.gsub(%r{^#{knockout_prefix}}, "") : ko_item
136
+ if item != ko_item
137
+ print "#{ko_item} - " if merge_debug
138
+ dest.delete(item)
139
+ dest.delete(ko_item)
140
+ retval = true
141
+ end
142
+ retval
143
+ end
144
+ puts if merge_debug
145
+ end
146
+ puts "#{di} merging arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
147
+ source_all_hashes = source.all? { |i| i.kind_of?(Hash) }
148
+ dest_all_hashes = dest.all? { |i| i.kind_of?(Hash) }
149
+ if merge_hash_arrays && source_all_hashes && dest_all_hashes
150
+ # merge hashes in lists
151
+ list = []
152
+ dest.each_index do |i|
153
+ list[i] = deep_merge!(source[i] || {}, dest[i],
154
+ options.merge(:debug_indent => di + ' '))
155
+ end
156
+ list += source[dest.count..-1] if source.count > dest.count
157
+ dest = list
158
+ else
159
+ dest = dest | source
160
+ end
161
+ dest.sort! if sort_merged_arrays
162
+ elsif overwrite_unmergeable
163
+ puts "#{di} overwriting dest: #{source.inspect} -over-> #{dest.inspect}" if merge_debug
164
+ dest = overwrite_unmergeables(source, dest, options)
165
+ end
166
+ else # src_hash is not an array or hash, so we'll have to overwrite dest
167
+ puts "#{di}Others: #{source.inspect} :: #{dest.inspect}" if merge_debug
168
+ dest = overwrite_unmergeables(source, dest, options)
169
+ end
170
+ puts "#{di}Returning #{dest.inspect}" if merge_debug
171
+ dest
172
+ end # deep_merge!
173
+
174
+ # allows deep_merge! to uniformly handle overwriting of unmergeable entities
175
+ def self.overwrite_unmergeables(source, dest, options)
176
+ merge_debug = options[:merge_debug] || false
177
+ overwrite_unmergeable = !options[:preserve_unmergeables]
178
+ knockout_prefix = options[:knockout_prefix] || false
179
+ di = options[:debug_indent] || ''
180
+ if knockout_prefix && overwrite_unmergeable
181
+ if source.kind_of?(String) # remove knockout string from source before overwriting dest
182
+ src_tmp = source.gsub(%r{^#{knockout_prefix}},"")
183
+ elsif source.kind_of?(Array) # remove all knockout elements before overwriting dest
184
+ src_tmp = source.delete_if {|ko_item| ko_item.kind_of?(String) && ko_item.match(%r{^#{knockout_prefix}}) }
185
+ else
186
+ src_tmp = source
187
+ end
188
+ if src_tmp == source # if we didn't find a knockout_prefix then we just overwrite dest
189
+ puts "#{di}#{src_tmp.inspect} -over-> #{dest.inspect}" if merge_debug
190
+ dest = src_tmp
191
+ else # if we do find a knockout_prefix, then we just delete dest
192
+ puts "#{di}\"\" -over-> #{dest.inspect}" if merge_debug
193
+ dest = ""
194
+ end
195
+ elsif overwrite_unmergeable
196
+ dest = source
197
+ end
198
+ dest
199
+ end
200
+
201
+ def self.clear_or_nil(obj)
202
+ if obj.respond_to?(:clear)
203
+ obj.clear
204
+ else
205
+ obj = nil
206
+ end
207
+ obj
208
+ end
209
+
210
+ end # module DeepMerge
@@ -0,0 +1,28 @@
1
+ require 'deep_merge/core'
2
+
3
+ module DeepMerge
4
+ module DeepMergeHash
5
+ # ko_hash_merge! will merge and knockout elements prefixed with DEFAULT_FIELD_KNOCKOUT_PREFIX
6
+ def ko_deep_merge!(source, options = {})
7
+ default_opts = {:knockout_prefix => "--", :preserve_unmergeables => false}
8
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
9
+ end
10
+
11
+ # deep_merge! will merge and overwrite any unmergeables in destination hash
12
+ def deep_merge!(source, options = {})
13
+ default_opts = {:preserve_unmergeables => false}
14
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
15
+ end
16
+
17
+ # deep_merge will merge and skip any unmergeables in destination hash
18
+ def deep_merge(source, options = {})
19
+ default_opts = {:preserve_unmergeables => true}
20
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
21
+ end
22
+
23
+ end # DeepMergeHashExt
24
+ end
25
+
26
+ class Hash
27
+ include DeepMerge::DeepMergeHash
28
+ end
@@ -0,0 +1,27 @@
1
+ require 'deep_merge/core'
2
+
3
+ module DeepMerge
4
+ module RailsCompat
5
+ # ko_hash_merge! will merge and knockout elements prefixed with DEFAULT_FIELD_KNOCKOUT_PREFIX
6
+ def ko_deeper_merge!(source, options = {})
7
+ default_opts = {:knockout_prefix => "--", :preserve_unmergeables => false}
8
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
9
+ end
10
+
11
+ # deep_merge! will merge and overwrite any unmergeables in destination hash
12
+ def deeper_merge!(source, options = {})
13
+ default_opts = {:preserve_unmergeables => false}
14
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
15
+ end
16
+
17
+ # deep_merge will merge and skip any unmergeables in destination hash
18
+ def deeper_merge(source, options = {})
19
+ default_opts = {:preserve_unmergeables => true}
20
+ DeepMerge::deep_merge!(source, self, default_opts.merge(options))
21
+ end
22
+ end
23
+ end
24
+
25
+ class Hash
26
+ include ::DeepMerge::RailsCompat
27
+ end
@@ -1,553 +1,596 @@
1
- require 'test/unit'
2
- require '../lib/deep_merge.rb'
3
-
4
- class TestDeepMerge < Test::Unit::TestCase
5
-
6
- def setup
7
- end
8
-
9
- # show that Hash object has deep merge capabilities in form of three methods:
10
- # ko_deep_merge! # uses '--' knockout and overwrites unmergeable
11
- # deep_merge! # overwrites unmergeable
12
- # deep_merge # skips unmergeable
13
- def test_hash_deep_merge
14
- x = {}
15
- assert x.respond_to?('deep_merge!'.to_sym)
16
- hash_src = {'id' => [3,4,5]}
17
- hash_dest = {'id' => [1,2,3]}
18
- assert hash_dest.ko_deep_merge!(hash_src)
19
- assert_equal({'id' => [1,2,3,4,5]}, hash_dest)
20
-
21
- hash_src = {'id' => [3,4,5]}
22
- hash_dest = {'id' => [1,2,3]}
23
- assert hash_dest.deep_merge!(hash_src)
24
- assert_equal({'id' => [1,2,3,4,5]}, hash_dest)
25
-
26
- hash_src = {'id' => 'xxx'}
27
- hash_dest = {'id' => [1,2,3]}
28
- assert hash_dest.deep_merge(hash_src)
29
- assert_equal({'id' => [1,2,3]}, hash_dest)
30
- end
31
-
32
- FIELD_KNOCKOUT_PREFIX = DeepMerge::DEFAULT_FIELD_KNOCKOUT_PREFIX
33
-
34
- # tests DeepMerge::deep_merge! function
35
- def test_deep_merge
36
- # merge tests (moving from basic to more complex)
37
-
38
- # test merging an hash w/array into blank hash
39
- hash_src = {'id' => '2'}
40
- hash_dst = {}
41
- DeepMerge::deep_merge!(hash_src.dup, hash_dst, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
42
- assert_equal hash_src, hash_dst
43
-
44
- # test merging an hash w/array into blank hash
45
- hash_src = {'region' => {'id' => ['227', '2']}}
46
- hash_dst = {}
47
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
48
- assert_equal hash_src, hash_dst
49
-
50
- # merge from empty hash
51
- hash_src = {}
52
- hash_dst = {"property" => ["2","4"]}
53
- DeepMerge::deep_merge!(hash_src, hash_dst)
54
- assert_equal({"property" => ["2","4"]}, hash_dst)
55
-
56
- # merge to empty hash
57
- hash_src = {"property" => ["2","4"]}
58
- hash_dst = {}
59
- DeepMerge::deep_merge!(hash_src, hash_dst)
60
- assert_equal({"property" => ["2","4"]}, hash_dst)
61
-
62
- # simple string overwrite
63
- hash_src = {"name" => "value"}
64
- hash_dst = {"name" => "value1"}
65
- DeepMerge::deep_merge!(hash_src, hash_dst)
66
- assert_equal({"name" => "value"}, hash_dst)
67
-
68
- # simple string overwrite of empty hash
69
- hash_src = {"name" => "value"}
70
- hash_dst = {}
71
- DeepMerge::deep_merge!(hash_src, hash_dst)
72
- assert_equal(hash_src, hash_dst)
73
-
74
- # hashes holding array
75
- hash_src = {"property" => ["1","3"]}
76
- hash_dst = {"property" => ["2","4"]}
77
- DeepMerge::deep_merge!(hash_src, hash_dst)
78
- assert_equal(["2","4","1","3"], hash_dst['property'])
79
-
80
- # hashes holding array (sorted)
81
- hash_src = {"property" => ["1","3"]}
82
- hash_dst = {"property" => ["2","4"]}
83
- DeepMerge::deep_merge!(hash_src, hash_dst, {:sort_merged_arrays => true})
84
- assert_equal(["1","2","3","4"].sort, hash_dst['property'])
85
-
86
- # hashes holding hashes holding arrays (array with duplicate elements is merged with dest then src
87
- hash_src = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["1", "4+"]}}
88
- hash_dst = {"property" => {"bedroom_count" => ["3", "2"], "bathroom_count" => ["2"]}}
89
- DeepMerge::deep_merge!(hash_src, hash_dst)
90
- assert_equal({"property" => {"bedroom_count" => ["3","2","1"], "bathroom_count" => ["2", "1", "4+"]}}, hash_dst)
91
-
92
- # hash holding hash holding array v string (string is overwritten by array)
93
- hash_src = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["1", "4+"]}}
94
- hash_dst = {"property" => {"bedroom_count" => "3", "bathroom_count" => ["2"]}}
95
- DeepMerge::deep_merge!(hash_src, hash_dst)
96
- assert_equal({"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2","1","4+"]}}, hash_dst)
97
-
98
- # hash holding hash holding array v string (string is NOT overwritten by array)
99
- hash_src = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["1", "4+"]}}
100
- hash_dst = {"property" => {"bedroom_count" => "3", "bathroom_count" => ["2"]}}
101
- DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
102
- assert_equal({"property" => {"bedroom_count" => "3", "bathroom_count" => ["2","1","4+"]}}, hash_dst)
103
-
104
- # hash holding hash holding string v array (array is overwritten by string)
105
- hash_src = {"property" => {"bedroom_count" => "3", "bathroom_count" => ["1", "4+"]}}
106
- hash_dst = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2"]}}
107
- DeepMerge::deep_merge!(hash_src, hash_dst)
108
- assert_equal({"property" => {"bedroom_count" => "3", "bathroom_count" => ["2","1","4+"]}}, hash_dst)
109
-
110
- # hash holding hash holding string v array (array does NOT overwrite string)
111
- hash_src = {"property" => {"bedroom_count" => "3", "bathroom_count" => ["1", "4+"]}}
112
- hash_dst = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2"]}}
113
- DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
114
- assert_equal({"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2","1","4+"]}}, hash_dst)
115
-
116
- # hash holding hash holding hash v array (array is overwritten by hash)
117
- hash_src = {"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["1", "4+"]}}
118
- hash_dst = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2"]}}
119
- DeepMerge::deep_merge!(hash_src, hash_dst)
120
- assert_equal({"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["2","1","4+"]}}, hash_dst)
121
-
122
- # hash holding hash holding hash v array (array is NOT overwritten by hash)
123
- hash_src = {"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["1", "4+"]}}
124
- hash_dst = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2"]}}
125
- DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
126
- assert_equal({"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2","1","4+"]}}, hash_dst)
127
-
128
- # 3 hash layers holding integers (integers are overwritten by source)
129
- hash_src = {"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["1", "4+"]}}
130
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => 2, "queen_bed" => 4}, "bathroom_count" => ["2"]}}
131
- DeepMerge::deep_merge!(hash_src, hash_dst)
132
- assert_equal({"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["2","1","4+"]}}, hash_dst)
133
-
134
- # 3 hash layers holding arrays of int (arrays are merged)
135
- hash_src = {"property" => {"bedroom_count" => {"king_bed" => [3], "queen_bed" => [1]}, "bathroom_count" => ["1", "4+"]}}
136
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
137
- DeepMerge::deep_merge!(hash_src, hash_dst)
138
- assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2,3], "queen_bed" => [4,1]}, "bathroom_count" => ["2","1","4+"]}}, hash_dst)
139
-
140
- # 1 hash overwriting 3 hash layers holding arrays of int
141
- hash_src = {"property" => "1"}
142
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
143
- DeepMerge::deep_merge!(hash_src, hash_dst)
144
- assert_equal({"property" => "1"}, hash_dst)
145
-
146
- # 1 hash NOT overwriting 3 hash layers holding arrays of int
147
- hash_src = {"property" => "1"}
148
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
149
- DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
150
- assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}, hash_dst)
151
-
152
- # 3 hash layers holding arrays of int (arrays are merged) but second hash's array is overwritten
153
- hash_src = {"property" => {"bedroom_count" => {"king_bed" => [3], "queen_bed" => [1]}, "bathroom_count" => "1"}}
154
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
155
- DeepMerge::deep_merge!(hash_src, hash_dst)
156
- assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2,3], "queen_bed" => [4,1]}, "bathroom_count" => "1"}}, hash_dst)
157
-
158
- # 3 hash layers holding arrays of int (arrays are merged) but second hash's array is NOT overwritten
159
- hash_src = {"property" => {"bedroom_count" => {"king_bed" => [3], "queen_bed" => [1]}, "bathroom_count" => "1"}}
160
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
161
- DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
162
- assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2,3], "queen_bed" => [4,1]}, "bathroom_count" => ["2"]}}, hash_dst)
163
-
164
- # 3 hash layers holding arrays of int, but one holds int. This one overwrites, but the rest merge
165
- hash_src = {"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => [1]}, "bathroom_count" => ["1"]}}
166
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
167
- DeepMerge::deep_merge!(hash_src, hash_dst)
168
- assert_equal({"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => [4,1]}, "bathroom_count" => ["2","1"]}}, hash_dst)
169
-
170
- # 3 hash layers holding arrays of int, but source is incomplete.
171
- hash_src = {"property" => {"bedroom_count" => {"king_bed" => [3]}, "bathroom_count" => ["1"]}}
172
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
173
- DeepMerge::deep_merge!(hash_src, hash_dst)
174
- assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2,3], "queen_bed" => [4]}, "bathroom_count" => ["2","1"]}}, hash_dst)
175
-
176
- # 3 hash layers holding arrays of int, but source is shorter and has new 2nd level ints.
177
- hash_src = {"property" => {"bedroom_count" => {2=>3, "king_bed" => [3]}, "bathroom_count" => ["1"]}}
178
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
179
- DeepMerge::deep_merge!(hash_src, hash_dst)
180
- assert_equal({"property" => {"bedroom_count" => {2=>3, "king_bed" => [2,3], "queen_bed" => [4]}, "bathroom_count" => ["2","1"]}}, hash_dst)
181
-
182
- # 3 hash layers holding arrays of int, but source is empty
183
- hash_src = {}
184
- hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
185
- DeepMerge::deep_merge!(hash_src, hash_dst)
186
- assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}, hash_dst)
187
-
188
- # 3 hash layers holding arrays of int, but dest is empty
189
- hash_src = {"property" => {"bedroom_count" => {2=>3, "king_bed" => [3]}, "bathroom_count" => ["1"]}}
190
- hash_dst = {}
191
- DeepMerge::deep_merge!(hash_src, hash_dst)
192
- assert_equal({"property" => {"bedroom_count" => {2=>3, "king_bed" => [3]}, "bathroom_count" => ["1"]}}, hash_dst)
193
-
194
- # test parameter management for knockout_prefix and overwrite unmergable
195
- assert_raise(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => ""})}
196
- assert_raise(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true, :knockout_prefix => ""})}
197
- assert_raise(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true, :knockout_prefix => "--"})}
198
- assert_nothing_raised(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => "--"})}
199
- assert_nothing_raised(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst)}
200
- assert_nothing_raised(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})}
201
-
202
- # hash holding arrays of arrays
203
- hash_src = {["1", "2", "3"] => ["1", "2"]}
204
- hash_dst = {["4", "5"] => ["3"]}
205
- DeepMerge::deep_merge!(hash_src, hash_dst)
206
- assert_equal({["1","2","3"] => ["1", "2"], ["4", "5"] => ["3"]}, hash_dst)
207
-
208
- # test merging of hash with blank hash, and make sure that source array split still functions
209
- hash_src = {'property' => {'bedroom_count' => ["1","2,3"]}}
210
- hash_dst = {}
211
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
212
- assert_equal({'property' => {'bedroom_count' => ["1","2","3"]}}, hash_dst)
213
-
214
- # test merging of hash with blank hash, and make sure that source array split does not function when turned off
215
- hash_src = {'property' => {'bedroom_count' => ["1","2,3"]}}
216
- hash_dst = {}
217
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
218
- assert_equal({'property' => {'bedroom_count' => ["1","2,3"]}}, hash_dst)
219
-
220
- # test merging into a blank hash with overwrite_unmergeables turned on
221
- hash_src = {"action"=>"browse", "controller"=>"results"}
222
- hash_dst = {}
223
- DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
224
- assert_equal hash_src, hash_dst
225
-
226
- # KNOCKOUT_PREFIX testing
227
- # the next few tests are looking for correct behavior from specific real-world params/session merges
228
- # using the custom modifiers built for param/session merges
229
-
230
- [nil, ","].each do |ko_split|
231
- # typical params/session style hash with knockout_merge elements
232
- hash_params = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "2", "3"]}}
233
- hash_session = {"property"=>{"bedroom_count"=>["1", "2", "3"]}}
234
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
235
- assert_equal({"property"=>{"bedroom_count"=>["2", "3"]}}, hash_session)
236
-
237
- # typical params/session style hash with knockout_merge elements
238
- hash_params = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "2", "3"]}}
239
- hash_session = {"property"=>{"bedroom_count"=>["3"]}}
240
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
241
- assert_equal({"property"=>{"bedroom_count"=>["3","2"]}}, hash_session)
242
-
243
- # typical params/session style hash with knockout_merge elements
244
- hash_params = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "2", "3"]}}
245
- hash_session = {"property"=>{"bedroom_count"=>["4"]}}
246
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
247
- assert_equal({"property"=>{"bedroom_count"=>["4","2","3"]}}, hash_session)
248
-
249
- # typical params/session style hash with knockout_merge elements
250
- hash_params = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "2", "3"]}}
251
- hash_session = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "4"]}}
252
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
253
- assert_equal({"property"=>{"bedroom_count"=>["4","2","3"]}}, hash_session)
254
-
255
- # typical params/session style hash with knockout_merge elements
256
- hash_params = {"amenity"=>{"id"=>[FIELD_KNOCKOUT_PREFIX+"1", FIELD_KNOCKOUT_PREFIX+"2", "3", "4"]}}
257
- hash_session = {"amenity"=>{"id"=>["1", "2"]}}
258
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
259
- assert_equal({"amenity"=>{"id"=>["3","4"]}}, hash_session)
260
- end
261
-
262
- # special params/session style hash with knockout_merge elements in form src: ["1","2"] dest:["--1,--2", "3,4"]
263
- hash_params = {"amenity"=>{"id"=>[FIELD_KNOCKOUT_PREFIX+"1,"+FIELD_KNOCKOUT_PREFIX+"2", "3,4"]}}
264
- hash_session = {"amenity"=>{"id"=>["1", "2"]}}
265
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
266
- assert_equal({"amenity"=>{"id"=>["3","4"]}}, hash_session)
267
-
268
- # same as previous but without ko_split value, this merge should fail
269
- hash_params = {"amenity"=>{"id"=>[FIELD_KNOCKOUT_PREFIX+"1,"+FIELD_KNOCKOUT_PREFIX+"2", "3,4"]}}
270
- hash_session = {"amenity"=>{"id"=>["1", "2"]}}
271
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
272
- assert_equal({"amenity"=>{"id"=>["1","2","3,4"]}}, hash_session)
273
-
274
- # special params/session style hash with knockout_merge elements in form src: ["1","2"] dest:["--1,--2", "3,4"]
275
- hash_params = {"amenity"=>{"id"=>[FIELD_KNOCKOUT_PREFIX+"1,2", "3,4", "--5", "6"]}}
276
- hash_session = {"amenity"=>{"id"=>["1", "2"]}}
277
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
278
- assert_equal({"amenity"=>{"id"=>["2","3","4","6"]}}, hash_session)
279
-
280
- # special params/session style hash with knockout_merge elements in form src: ["--1,--2", "3,4", "--5", "6"] dest:["1,2", "3,4"]
281
- hash_params = {"amenity"=>{"id"=>["#{FIELD_KNOCKOUT_PREFIX}1,#{FIELD_KNOCKOUT_PREFIX}2", "3,4", "#{FIELD_KNOCKOUT_PREFIX}5", "6"]}}
282
- hash_session = {"amenity"=>{"id"=>["1", "2", "3", "4"]}}
283
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
284
- assert_equal({"amenity"=>{"id"=>["3","4","6"]}}, hash_session)
285
-
286
-
287
- hash_src = {"url_regions"=>[], "region"=>{"ids"=>["227,233"]}, "action"=>"browse", "task"=>"browse", "controller"=>"results"}
288
- hash_dst = {"region"=>{"ids"=>["227"]}}
289
- DeepMerge::deep_merge!(hash_src.dup, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
290
- assert_equal({"url_regions"=>[], "region"=>{"ids"=>["227","233"]}, "action"=>"browse", "task"=>"browse", "controller"=>"results"}, hash_dst)
291
-
292
- hash_src = {"region"=>{"ids"=>["--","227"], "id"=>"230"}}
293
- hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
294
- DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
295
- assert_equal({"region"=>{"ids"=>["227"], "id"=>"230"}}, hash_dst)
296
-
297
- hash_src = {"region"=>{"ids"=>["--","227", "232", "233"], "id"=>"232"}}
298
- hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
299
- DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
300
- assert_equal({"region"=>{"ids"=>["227", "232", "233"], "id"=>"232"}}, hash_dst)
301
-
302
- hash_src = {"region"=>{"ids"=>["--,227,232,233"], "id"=>"232"}}
303
- hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
304
- DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
305
- assert_equal({"region"=>{"ids"=>["227", "232", "233"], "id"=>"232"}}, hash_dst)
306
-
307
- hash_src = {"region"=>{"ids"=>["--,227,232","233"], "id"=>"232"}}
308
- hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
309
- DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
310
- assert_equal({"region"=>{"ids"=>["227", "232", "233"], "id"=>"232"}}, hash_dst)
311
-
312
- hash_src = {"region"=>{"ids"=>["--,227"], "id"=>"230"}}
313
- hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
314
- DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
315
- assert_equal({"region"=>{"ids"=>["227"], "id"=>"230"}}, hash_dst)
316
-
317
- hash_src = {"region"=>{"ids"=>["--,227"], "id"=>"230"}}
318
- hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}, "action"=>"browse", "task"=>"browse", "controller"=>"results", "property_order_by"=>"property_type.descr"}
319
- DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
320
- assert_equal({"region"=>{"ids"=>["227"], "id"=>"230"}, "action"=>"browse", "task"=>"browse",
321
- "controller"=>"results", "property_order_by"=>"property_type.descr"}, hash_dst)
322
-
323
- hash_src = {"query_uuid"=>"6386333d-389b-ab5c-8943-6f3a2aa914d7", "region"=>{"ids"=>["--,227"], "id"=>"230"}}
324
- hash_dst = {"query_uuid"=>"6386333d-389b-ab5c-8943-6f3a2aa914d7", "url_regions"=>[], "region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}, "action"=>"browse", "task"=>"browse", "controller"=>"results", "property_order_by"=>"property_type.descr"}
325
- DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
326
- assert_equal({"query_uuid" => "6386333d-389b-ab5c-8943-6f3a2aa914d7", "url_regions"=>[],
327
- "region"=>{"ids"=>["227"], "id"=>"230"}, "action"=>"browse", "task"=>"browse",
328
- "controller"=>"results", "property_order_by"=>"property_type.descr"}, hash_dst)
329
-
330
- # knock out entire dest hash if "--" is passed for source
331
- hash_params = {'amenity' => "--"}
332
- hash_session = {"amenity" => "1"}
333
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
334
- assert_equal({'amenity' => ""}, hash_session)
335
-
336
- # knock out entire dest hash if "--" is passed for source
337
- hash_params = {'amenity' => ["--"]}
338
- hash_session = {"amenity" => "1"}
339
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
340
- assert_equal({'amenity' => []}, hash_session)
341
-
342
- # knock out entire dest hash if "--" is passed for source
343
- hash_params = {'amenity' => "--"}
344
- hash_session = {"amenity" => ["1"]}
345
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
346
- assert_equal({'amenity' => ""}, hash_session)
347
-
348
- # knock out entire dest hash if "--" is passed for source
349
- hash_params = {'amenity' => ["--"]}
350
- hash_session = {"amenity" => ["1"]}
351
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
352
- assert_equal({'amenity' => []}, hash_session)
353
-
354
- # knock out entire dest hash if "--" is passed for source
355
- hash_params = {'amenity' => ["--"]}
356
- hash_session = {"amenity" => "1"}
357
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
358
- assert_equal({'amenity' => []}, hash_session)
359
-
360
- # knock out entire dest hash if "--" is passed for source
361
- hash_params = {'amenity' => ["--", "2"]}
362
- hash_session = {'amenity' => ["1", "3", "7+"]}
363
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
364
- assert_equal({'amenity' => ["2"]}, hash_session)
365
-
366
- # knock out entire dest hash if "--" is passed for source
367
- hash_params = {'amenity' => ["--", "2"]}
368
- hash_session = {'amenity' => "5"}
369
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
370
- assert_equal({'amenity' => ['2']}, hash_session)
371
-
372
- # knock out entire dest hash if "--" is passed for source
373
- hash_params = {'amenity' => "--"}
374
- hash_session = {"amenity"=>{"id"=>["1", "2", "3", "4"]}}
375
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
376
- assert_equal({'amenity' => ""}, hash_session)
377
-
378
- # knock out entire dest hash if "--" is passed for source
379
- hash_params = {'amenity' => ["--"]}
380
- hash_session = {"amenity"=>{"id"=>["1", "2", "3", "4"]}}
381
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
382
- assert_equal({'amenity' => []}, hash_session)
383
-
384
- # knock out dest array if "--" is passed for source
385
- hash_params = {"region" => {'ids' => FIELD_KNOCKOUT_PREFIX}}
386
- hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"]}}
387
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
388
- assert_equal({'region' => {'ids' => ""}}, hash_session)
389
-
390
- # knock out dest array but leave other elements of hash intact
391
- hash_params = {"region" => {'ids' => FIELD_KNOCKOUT_PREFIX}}
392
- hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
393
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
394
- assert_equal({'region' => {'ids' => "", 'id'=>'11'}}, hash_session)
395
-
396
- # knock out entire tree of dest hash
397
- hash_params = {"region" => FIELD_KNOCKOUT_PREFIX}
398
- hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
399
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
400
- assert_equal({'region' => ""}, hash_session)
401
-
402
- # knock out entire tree of dest hash - retaining array format
403
- hash_params = {"region" => {'ids' => [FIELD_KNOCKOUT_PREFIX]}}
404
- hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
405
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
406
- assert_equal({'region' => {'ids' => [], 'id'=>'11'}}, hash_session)
407
-
408
- # knock out entire tree of dest hash & replace with new content
409
- hash_params = {"region" => {'ids' => ["2", FIELD_KNOCKOUT_PREFIX, "6"]}}
410
- hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
411
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
412
- assert_equal({'region' => {'ids' => ["2", "6"], 'id'=>'11'}}, hash_session)
413
-
414
- # knock out entire tree of dest hash & replace with new content
415
- hash_params = {"region" => {'ids' => ["7", FIELD_KNOCKOUT_PREFIX, "6"]}}
416
- hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
417
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
418
- assert_equal({'region' => {'ids' => ["7", "6"], 'id'=>'11'}}, hash_session)
419
-
420
- # edge test: make sure that when we turn off knockout_prefix that all values are processed correctly
421
- hash_params = {"region" => {'ids' => ["7", "--", "2", "6,8"]}}
422
- hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
423
- DeepMerge::deep_merge!(hash_params, hash_session, {:unpack_arrays => ","})
424
- assert_equal({'region' => {'ids' => ["1", "2", "3", "4", "7", "--", "6", "8"], 'id'=>'11'}}, hash_session)
425
-
426
- # edge test 2: make sure that when we turn off source array split that all values are processed correctly
427
- hash_params = {"region" => {'ids' => ["7", "3", "--", "6,8"]}}
428
- hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
429
- DeepMerge::deep_merge!(hash_params, hash_session)
430
- assert_equal({'region' => {'ids' => ["1", "2", "3", "4", "7", "--", "6,8"], 'id'=>'11'}}, hash_session)
431
-
432
- # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
433
- hash_params = {"amenity"=>"--1"}
434
- hash_session = {"amenity"=>"1"}
435
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
436
- assert_equal({"amenity"=>""}, hash_session)
437
-
438
- # Example: src = {'key' => "--1"}, dst = {'key' => "2"} -> merges to {'key' => ""}
439
- hash_params = {"amenity"=>"--1"}
440
- hash_session = {"amenity"=>"2"}
441
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
442
- assert_equal({"amenity"=>""}, hash_session)
443
-
444
- # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
445
- hash_params = {"amenity"=>["--1"]}
446
- hash_session = {"amenity"=>"1"}
447
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
448
- assert_equal({"amenity"=>[]}, hash_session)
449
-
450
- # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
451
- hash_params = {"amenity"=>["--1"]}
452
- hash_session = {"amenity"=>["1"]}
453
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
454
- assert_equal({"amenity"=>[]}, hash_session)
455
-
456
- # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
457
- hash_params = {"amenity"=>"--1"}
458
- hash_session = {}
459
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
460
- assert_equal({"amenity"=>""}, hash_session)
461
-
462
-
463
- # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
464
- hash_params = {"amenity"=>"--1"}
465
- hash_session = {"amenity"=>["1"]}
466
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
467
- assert_equal({"amenity"=>""}, hash_session)
468
-
469
- #are unmerged hashes passed unmodified w/out :unpack_arrays?
470
- hash_params = {"amenity"=>{"id"=>["26,27"]}}
471
- hash_session = {}
472
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
473
- assert_equal({"amenity"=>{"id"=>["26,27"]}}, hash_session)
474
-
475
- #hash should be merged
476
- hash_params = {"amenity"=>{"id"=>["26,27"]}}
477
- hash_session = {}
478
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
479
- assert_equal({"amenity"=>{"id"=>["26","27"]}}, hash_session)
480
-
481
- # second merge of same values should result in no change in output
482
- hash_params = {"amenity"=>{"id"=>["26,27"]}}
483
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
484
- assert_equal({"amenity"=>{"id"=>["26","27"]}}, hash_session)
485
-
486
- #hashes with knockout values are suppressed
487
- hash_params = {"amenity"=>{"id"=>["#{FIELD_KNOCKOUT_PREFIX}26,#{FIELD_KNOCKOUT_PREFIX}27,28"]}}
488
- hash_session = {}
489
- DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
490
- assert_equal({"amenity"=>{"id"=>["28"]}}, hash_session)
491
-
492
- hash_src= {'region' =>{'ids'=>['--']}, 'query_uuid' => 'zzz'}
493
- hash_dst= {'region' =>{'ids'=>['227','2','3','3']}, 'query_uuid' => 'zzz'}
494
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
495
- assert_equal({'region' =>{'ids'=>[]}, 'query_uuid' => 'zzz'}, hash_dst)
496
-
497
- hash_src= {'region' =>{'ids'=>['--']}, 'query_uuid' => 'zzz'}
498
- hash_dst= {'region' =>{'ids'=>['227','2','3','3'], 'id' => '3'}, 'query_uuid' => 'zzz'}
499
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
500
- assert_equal({'region' =>{'ids'=>[], 'id'=>'3'}, 'query_uuid' => 'zzz'}, hash_dst)
501
-
502
- hash_src= {'region' =>{'ids'=>['--']}, 'query_uuid' => 'zzz'}
503
- hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
504
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
505
- assert_equal({'region' =>{'muni_city_id' => '2244', 'ids'=>[], 'id'=>'3'}, 'query_uuid' => 'zzz'}, hash_dst)
506
-
507
- hash_src= {'region' =>{'ids'=>['--'], 'id' => '5'}, 'query_uuid' => 'zzz'}
508
- hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
509
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
510
- assert_equal({'region' =>{'muni_city_id' => '2244', 'ids'=>[], 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
511
-
512
- hash_src= {'region' =>{'ids'=>['--', '227'], 'id' => '5'}, 'query_uuid' => 'zzz'}
513
- hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
514
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
515
- assert_equal({'region' =>{'muni_city_id' => '2244', 'ids'=>['227'], 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
516
-
517
- hash_src= {'region' =>{'muni_city_id' => '--', 'ids'=>'--', 'id'=>'5'}, 'query_uuid' => 'zzz'}
518
- hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
519
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
520
- assert_equal({'region' =>{'muni_city_id' => '', 'ids'=>'', 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
521
-
522
- hash_src= {'region' =>{'muni_city_id' => '--', 'ids'=>['--'], 'id'=>'5'}, 'query_uuid' => 'zzz'}
523
- hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
524
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
525
- assert_equal({'region' =>{'muni_city_id' => '', 'ids'=>[], 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
526
-
527
- hash_src= {'region' =>{'muni_city_id' => '--', 'ids'=>['--','227'], 'id'=>'5'}, 'query_uuid' => 'zzz'}
528
- hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
529
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
530
- assert_equal({'region' =>{'muni_city_id' => '', 'ids'=>['227'], 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
531
-
532
- hash_src = {"muni_city_id"=>"--", "id"=>""}
533
- hash_dst = {"muni_city_id"=>"", "id"=>""}
534
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
535
- assert_equal({"muni_city_id"=>"", "id"=>""}, hash_dst)
536
-
537
- hash_src = {"region"=>{"muni_city_id"=>"--", "id"=>""}}
538
- hash_dst = {"region"=>{"muni_city_id"=>"", "id"=>""}}
539
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
540
- assert_equal({"region"=>{"muni_city_id"=>"", "id"=>""}}, hash_dst)
541
-
542
- hash_src = {"query_uuid"=>"a0dc3c84-ec7f-6756-bdb0-fff9157438ab", "url_regions"=>[], "region"=>{"muni_city_id"=>"--", "id"=>""}, "property"=>{"property_type_id"=>"", "search_rate_min"=>"", "search_rate_max"=>""}, "task"=>"search", "run_query"=>"Search"}
543
- hash_dst = {"query_uuid"=>"a0dc3c84-ec7f-6756-bdb0-fff9157438ab", "url_regions"=>[], "region"=>{"muni_city_id"=>"", "id"=>""}, "property"=>{"property_type_id"=>"", "search_rate_min"=>"", "search_rate_max"=>""}, "task"=>"search", "run_query"=>"Search"}
544
- DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
545
- assert_equal({"query_uuid"=>"a0dc3c84-ec7f-6756-bdb0-fff9157438ab", "url_regions"=>[], "region"=>{"muni_city_id"=>"", "id"=>""}, "property"=>{"property_type_id"=>"", "search_rate_min"=>"", "search_rate_max"=>""}, "task"=>"search", "run_query"=>"Search"}, hash_dst)
546
-
547
- # hash of array of hashes
548
- hash_src = {"item" => [{"1" => "3"}, {"2" => "4"}]}
549
- hash_dst = {"item" => [{"3" => "5"}]}
550
- DeepMerge::deep_merge!(hash_src, hash_dst)
551
- assert_equal({"item" => [{"3" => "5"}, {"1" => "3"}, {"2" => "4"}]}, hash_dst)
552
- end # test_deep_merge
553
- end
1
+ require 'test/unit'
2
+
3
+ $:.unshift(File.dirname(__FILE__) + '/../lib/')
4
+ require 'deep_merge'
5
+
6
+ # Assume strings have a blank? method
7
+ # as they do when ActiveSupport is included.
8
+ module StringBlank
9
+ def blank?
10
+ size == 0
11
+ end
12
+ end
13
+
14
+ class TestDeepMerge < Test::Unit::TestCase
15
+
16
+ def setup
17
+ end
18
+
19
+ # show that Hash object has deep merge capabilities in form of three methods:
20
+ # ko_deep_merge! # uses '--' knockout and overwrites unmergeable
21
+ # deep_merge! # overwrites unmergeable
22
+ # deep_merge # skips unmergeable
23
+ def test_hash_deep_merge
24
+ x = {}
25
+ assert x.respond_to?('deep_merge!'.to_sym)
26
+ hash_src = {'id' => [3,4,5]}
27
+ hash_dest = {'id' => [1,2,3]}
28
+ assert hash_dest.ko_deep_merge!(hash_src)
29
+ assert_equal({'id' => [1,2,3,4,5]}, hash_dest)
30
+
31
+ hash_src = {'id' => [3,4,5]}
32
+ hash_dest = {'id' => [1,2,3]}
33
+ assert hash_dest.deep_merge!(hash_src)
34
+ assert_equal({'id' => [1,2,3,4,5]}, hash_dest)
35
+
36
+ hash_src = {'id' => 'xxx'}
37
+ hash_dest = {'id' => [1,2,3]}
38
+ assert hash_dest.deep_merge(hash_src)
39
+ assert_equal({'id' => [1,2,3]}, hash_dest)
40
+ end
41
+
42
+ FIELD_KNOCKOUT_PREFIX = DeepMerge::DEFAULT_FIELD_KNOCKOUT_PREFIX
43
+
44
+ # tests DeepMerge::deep_merge! function
45
+ def test_deep_merge
46
+ # merge tests (moving from basic to more complex)
47
+
48
+ # test merging an hash w/array into blank hash
49
+ hash_src = {'id' => '2'}
50
+ hash_dst = {}
51
+ DeepMerge::deep_merge!(hash_src.dup, hash_dst, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
52
+ assert_equal hash_src, hash_dst
53
+
54
+ # test merging an hash w/array into blank hash
55
+ hash_src = {'region' => {'id' => ['227', '2']}}
56
+ hash_dst = {}
57
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
58
+ assert_equal hash_src, hash_dst
59
+
60
+ # merge from empty hash
61
+ hash_src = {}
62
+ hash_dst = {"property" => ["2","4"]}
63
+ DeepMerge::deep_merge!(hash_src, hash_dst)
64
+ assert_equal({"property" => ["2","4"]}, hash_dst)
65
+
66
+ # merge to empty hash
67
+ hash_src = {"property" => ["2","4"]}
68
+ hash_dst = {}
69
+ DeepMerge::deep_merge!(hash_src, hash_dst)
70
+ assert_equal({"property" => ["2","4"]}, hash_dst)
71
+
72
+ # simple string overwrite
73
+ hash_src = {"name" => "value"}
74
+ hash_dst = {"name" => "value1"}
75
+ DeepMerge::deep_merge!(hash_src, hash_dst)
76
+ assert_equal({"name" => "value"}, hash_dst)
77
+
78
+ # simple string overwrite of empty hash
79
+ hash_src = {"name" => "value"}
80
+ hash_dst = {}
81
+ DeepMerge::deep_merge!(hash_src, hash_dst)
82
+ assert_equal(hash_src, hash_dst)
83
+
84
+ # hashes holding array
85
+ hash_src = {"property" => ["1","3"]}
86
+ hash_dst = {"property" => ["2","4"]}
87
+ DeepMerge::deep_merge!(hash_src, hash_dst)
88
+ assert_equal(["2","4","1","3"], hash_dst['property'])
89
+
90
+ # hashes holding array (sorted)
91
+ hash_src = {"property" => ["1","3"]}
92
+ hash_dst = {"property" => ["2","4"]}
93
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:sort_merged_arrays => true})
94
+ assert_equal(["1","2","3","4"].sort, hash_dst['property'])
95
+
96
+ # hashes holding hashes holding arrays (array with duplicate elements is merged with dest then src
97
+ hash_src = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["1", "4+"]}}
98
+ hash_dst = {"property" => {"bedroom_count" => ["3", "2"], "bathroom_count" => ["2"]}}
99
+ DeepMerge::deep_merge!(hash_src, hash_dst)
100
+ assert_equal({"property" => {"bedroom_count" => ["3","2","1"], "bathroom_count" => ["2", "1", "4+"]}}, hash_dst)
101
+
102
+ # hash holding hash holding array v string (string is overwritten by array)
103
+ hash_src = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["1", "4+"]}}
104
+ hash_dst = {"property" => {"bedroom_count" => "3", "bathroom_count" => ["2"]}}
105
+ DeepMerge::deep_merge!(hash_src, hash_dst)
106
+ assert_equal({"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2","1","4+"]}}, hash_dst)
107
+
108
+ # hash holding hash holding array v string (string is NOT overwritten by array)
109
+ hash_src = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["1", "4+"]}}
110
+ hash_dst = {"property" => {"bedroom_count" => "3", "bathroom_count" => ["2"]}}
111
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
112
+ assert_equal({"property" => {"bedroom_count" => "3", "bathroom_count" => ["2","1","4+"]}}, hash_dst)
113
+
114
+ # hash holding hash holding string v array (array is overwritten by string)
115
+ hash_src = {"property" => {"bedroom_count" => "3", "bathroom_count" => ["1", "4+"]}}
116
+ hash_dst = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2"]}}
117
+ DeepMerge::deep_merge!(hash_src, hash_dst)
118
+ assert_equal({"property" => {"bedroom_count" => "3", "bathroom_count" => ["2","1","4+"]}}, hash_dst)
119
+
120
+ # hash holding hash holding string v array (array does NOT overwrite string)
121
+ hash_src = {"property" => {"bedroom_count" => "3", "bathroom_count" => ["1", "4+"]}}
122
+ hash_dst = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2"]}}
123
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
124
+ assert_equal({"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2","1","4+"]}}, hash_dst)
125
+
126
+ # hash holding hash holding hash v array (array is overwritten by hash)
127
+ hash_src = {"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["1", "4+"]}}
128
+ hash_dst = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2"]}}
129
+ DeepMerge::deep_merge!(hash_src, hash_dst)
130
+ assert_equal({"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["2","1","4+"]}}, hash_dst)
131
+
132
+ # hash holding hash holding hash v array (array is NOT overwritten by hash)
133
+ hash_src = {"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["1", "4+"]}}
134
+ hash_dst = {"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2"]}}
135
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
136
+ assert_equal({"property" => {"bedroom_count" => ["1", "2"], "bathroom_count" => ["2","1","4+"]}}, hash_dst)
137
+
138
+ # 3 hash layers holding integers (integers are overwritten by source)
139
+ hash_src = {"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["1", "4+"]}}
140
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => 2, "queen_bed" => 4}, "bathroom_count" => ["2"]}}
141
+ DeepMerge::deep_merge!(hash_src, hash_dst)
142
+ assert_equal({"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => 1}, "bathroom_count" => ["2","1","4+"]}}, hash_dst)
143
+
144
+ # 3 hash layers holding arrays of int (arrays are merged)
145
+ hash_src = {"property" => {"bedroom_count" => {"king_bed" => [3], "queen_bed" => [1]}, "bathroom_count" => ["1", "4+"]}}
146
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
147
+ DeepMerge::deep_merge!(hash_src, hash_dst)
148
+ assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2,3], "queen_bed" => [4,1]}, "bathroom_count" => ["2","1","4+"]}}, hash_dst)
149
+
150
+ # 1 hash overwriting 3 hash layers holding arrays of int
151
+ hash_src = {"property" => "1"}
152
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
153
+ DeepMerge::deep_merge!(hash_src, hash_dst)
154
+ assert_equal({"property" => "1"}, hash_dst)
155
+
156
+ # 1 hash NOT overwriting 3 hash layers holding arrays of int
157
+ hash_src = {"property" => "1"}
158
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
159
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
160
+ assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}, hash_dst)
161
+
162
+ # 3 hash layers holding arrays of int (arrays are merged) but second hash's array is overwritten
163
+ hash_src = {"property" => {"bedroom_count" => {"king_bed" => [3], "queen_bed" => [1]}, "bathroom_count" => "1"}}
164
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
165
+ DeepMerge::deep_merge!(hash_src, hash_dst)
166
+ assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2,3], "queen_bed" => [4,1]}, "bathroom_count" => "1"}}, hash_dst)
167
+
168
+ # 3 hash layers holding arrays of int (arrays are merged) but second hash's array is NOT overwritten
169
+ hash_src = {"property" => {"bedroom_count" => {"king_bed" => [3], "queen_bed" => [1]}, "bathroom_count" => "1"}}
170
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
171
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})
172
+ assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2,3], "queen_bed" => [4,1]}, "bathroom_count" => ["2"]}}, hash_dst)
173
+
174
+ # 3 hash layers holding arrays of int, but one holds int. This one overwrites, but the rest merge
175
+ hash_src = {"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => [1]}, "bathroom_count" => ["1"]}}
176
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
177
+ DeepMerge::deep_merge!(hash_src, hash_dst)
178
+ assert_equal({"property" => {"bedroom_count" => {"king_bed" => 3, "queen_bed" => [4,1]}, "bathroom_count" => ["2","1"]}}, hash_dst)
179
+
180
+ # 3 hash layers holding arrays of int, but source is incomplete.
181
+ hash_src = {"property" => {"bedroom_count" => {"king_bed" => [3]}, "bathroom_count" => ["1"]}}
182
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
183
+ DeepMerge::deep_merge!(hash_src, hash_dst)
184
+ assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2,3], "queen_bed" => [4]}, "bathroom_count" => ["2","1"]}}, hash_dst)
185
+
186
+ # 3 hash layers holding arrays of int, but source is shorter and has new 2nd level ints.
187
+ hash_src = {"property" => {"bedroom_count" => {2=>3, "king_bed" => [3]}, "bathroom_count" => ["1"]}}
188
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
189
+ DeepMerge::deep_merge!(hash_src, hash_dst)
190
+ assert_equal({"property" => {"bedroom_count" => {2=>3, "king_bed" => [2,3], "queen_bed" => [4]}, "bathroom_count" => ["2","1"]}}, hash_dst)
191
+
192
+ # 3 hash layers holding arrays of int, but source is empty
193
+ hash_src = {}
194
+ hash_dst = {"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}
195
+ DeepMerge::deep_merge!(hash_src, hash_dst)
196
+ assert_equal({"property" => {"bedroom_count" => {"king_bed" => [2], "queen_bed" => [4]}, "bathroom_count" => ["2"]}}, hash_dst)
197
+
198
+ # 3 hash layers holding arrays of int, but dest is empty
199
+ hash_src = {"property" => {"bedroom_count" => {2=>3, "king_bed" => [3]}, "bathroom_count" => ["1"]}}
200
+ hash_dst = {}
201
+ DeepMerge::deep_merge!(hash_src, hash_dst)
202
+ assert_equal({"property" => {"bedroom_count" => {2=>3, "king_bed" => [3]}, "bathroom_count" => ["1"]}}, hash_dst)
203
+
204
+ # test parameter management for knockout_prefix and overwrite unmergable
205
+ assert_raise(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => ""})}
206
+ assert_raise(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true, :knockout_prefix => ""})}
207
+ assert_raise(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true, :knockout_prefix => "--"})}
208
+ assert_nothing_raised(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => "--"})}
209
+ assert_nothing_raised(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst)}
210
+ assert_nothing_raised(DeepMerge::InvalidParameter) {DeepMerge::deep_merge!(hash_src, hash_dst, {:preserve_unmergeables => true})}
211
+
212
+ # hash holding arrays of arrays
213
+ hash_src = {["1", "2", "3"] => ["1", "2"]}
214
+ hash_dst = {["4", "5"] => ["3"]}
215
+ DeepMerge::deep_merge!(hash_src, hash_dst)
216
+ assert_equal({["1","2","3"] => ["1", "2"], ["4", "5"] => ["3"]}, hash_dst)
217
+
218
+ # test merging of hash with blank hash, and make sure that source array split still functions
219
+ hash_src = {'property' => {'bedroom_count' => ["1","2,3"]}}
220
+ hash_dst = {}
221
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
222
+ assert_equal({'property' => {'bedroom_count' => ["1","2","3"]}}, hash_dst)
223
+
224
+ # test merging of hash with blank hash, and make sure that source array split does not function when turned off
225
+ hash_src = {'property' => {'bedroom_count' => ["1","2,3"]}}
226
+ hash_dst = {}
227
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
228
+ assert_equal({'property' => {'bedroom_count' => ["1","2,3"]}}, hash_dst)
229
+
230
+ # test merging into a blank hash with overwrite_unmergeables turned on
231
+ hash_src = {"action"=>"browse", "controller"=>"results"}
232
+ hash_dst = {}
233
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
234
+ assert_equal hash_src, hash_dst
235
+
236
+ # KNOCKOUT_PREFIX testing
237
+ # the next few tests are looking for correct behavior from specific real-world params/session merges
238
+ # using the custom modifiers built for param/session merges
239
+
240
+ [nil, ","].each do |ko_split|
241
+ # typical params/session style hash with knockout_merge elements
242
+ hash_params = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "2", "3"]}}
243
+ hash_session = {"property"=>{"bedroom_count"=>["1", "2", "3"]}}
244
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
245
+ assert_equal({"property"=>{"bedroom_count"=>["2", "3"]}}, hash_session)
246
+
247
+ # typical params/session style hash with knockout_merge elements
248
+ hash_params = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "2", "3"]}}
249
+ hash_session = {"property"=>{"bedroom_count"=>["3"]}}
250
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
251
+ assert_equal({"property"=>{"bedroom_count"=>["3","2"]}}, hash_session)
252
+
253
+ # typical params/session style hash with knockout_merge elements
254
+ hash_params = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "2", "3"]}}
255
+ hash_session = {"property"=>{"bedroom_count"=>["4"]}}
256
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
257
+ assert_equal({"property"=>{"bedroom_count"=>["4","2","3"]}}, hash_session)
258
+
259
+ # typical params/session style hash with knockout_merge elements
260
+ hash_params = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "2", "3"]}}
261
+ hash_session = {"property"=>{"bedroom_count"=>[FIELD_KNOCKOUT_PREFIX+"1", "4"]}}
262
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
263
+ assert_equal({"property"=>{"bedroom_count"=>["4","2","3"]}}, hash_session)
264
+
265
+ # typical params/session style hash with knockout_merge elements
266
+ hash_params = {"amenity"=>{"id"=>[FIELD_KNOCKOUT_PREFIX+"1", FIELD_KNOCKOUT_PREFIX+"2", "3", "4"]}}
267
+ hash_session = {"amenity"=>{"id"=>["1", "2"]}}
268
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ko_split})
269
+ assert_equal({"amenity"=>{"id"=>["3","4"]}}, hash_session)
270
+ end
271
+
272
+ # special params/session style hash with knockout_merge elements in form src: ["1","2"] dest:["--1,--2", "3,4"]
273
+ hash_params = {"amenity"=>{"id"=>[FIELD_KNOCKOUT_PREFIX+"1,"+FIELD_KNOCKOUT_PREFIX+"2", "3,4"]}}
274
+ hash_session = {"amenity"=>{"id"=>["1", "2"]}}
275
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
276
+ assert_equal({"amenity"=>{"id"=>["3","4"]}}, hash_session)
277
+
278
+ # same as previous but without ko_split value, this merge should fail
279
+ hash_params = {"amenity"=>{"id"=>[FIELD_KNOCKOUT_PREFIX+"1,"+FIELD_KNOCKOUT_PREFIX+"2", "3,4"]}}
280
+ hash_session = {"amenity"=>{"id"=>["1", "2"]}}
281
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
282
+ assert_equal({"amenity"=>{"id"=>["1","2","3,4"]}}, hash_session)
283
+
284
+ # special params/session style hash with knockout_merge elements in form src: ["1","2"] dest:["--1,--2", "3,4"]
285
+ hash_params = {"amenity"=>{"id"=>[FIELD_KNOCKOUT_PREFIX+"1,2", "3,4", "--5", "6"]}}
286
+ hash_session = {"amenity"=>{"id"=>["1", "2"]}}
287
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
288
+ assert_equal({"amenity"=>{"id"=>["2","3","4","6"]}}, hash_session)
289
+
290
+ # special params/session style hash with knockout_merge elements in form src: ["--1,--2", "3,4", "--5", "6"] dest:["1,2", "3,4"]
291
+ hash_params = {"amenity"=>{"id"=>["#{FIELD_KNOCKOUT_PREFIX}1,#{FIELD_KNOCKOUT_PREFIX}2", "3,4", "#{FIELD_KNOCKOUT_PREFIX}5", "6"]}}
292
+ hash_session = {"amenity"=>{"id"=>["1", "2", "3", "4"]}}
293
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
294
+ assert_equal({"amenity"=>{"id"=>["3","4","6"]}}, hash_session)
295
+
296
+
297
+ hash_src = {"url_regions"=>[], "region"=>{"ids"=>["227,233"]}, "action"=>"browse", "task"=>"browse", "controller"=>"results"}
298
+ hash_dst = {"region"=>{"ids"=>["227"]}}
299
+ DeepMerge::deep_merge!(hash_src.dup, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
300
+ assert_equal({"url_regions"=>[], "region"=>{"ids"=>["227","233"]}, "action"=>"browse", "task"=>"browse", "controller"=>"results"}, hash_dst)
301
+
302
+ hash_src = {"region"=>{"ids"=>["--","227"], "id"=>"230"}}
303
+ hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
304
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
305
+ assert_equal({"region"=>{"ids"=>["227"], "id"=>"230"}}, hash_dst)
306
+
307
+ hash_src = {"region"=>{"ids"=>["--","227", "232", "233"], "id"=>"232"}}
308
+ hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
309
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
310
+ assert_equal({"region"=>{"ids"=>["227", "232", "233"], "id"=>"232"}}, hash_dst)
311
+
312
+ hash_src = {"region"=>{"ids"=>["--,227,232,233"], "id"=>"232"}}
313
+ hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
314
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
315
+ assert_equal({"region"=>{"ids"=>["227", "232", "233"], "id"=>"232"}}, hash_dst)
316
+
317
+ hash_src = {"region"=>{"ids"=>["--,227,232","233"], "id"=>"232"}}
318
+ hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
319
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
320
+ assert_equal({"region"=>{"ids"=>["227", "232", "233"], "id"=>"232"}}, hash_dst)
321
+
322
+ hash_src = {"region"=>{"ids"=>["--,227"], "id"=>"230"}}
323
+ hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}}
324
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
325
+ assert_equal({"region"=>{"ids"=>["227"], "id"=>"230"}}, hash_dst)
326
+
327
+ hash_src = {"region"=>{"ids"=>["--,227"], "id"=>"230"}}
328
+ hash_dst = {"region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}, "action"=>"browse", "task"=>"browse", "controller"=>"results", "property_order_by"=>"property_type.descr"}
329
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
330
+ assert_equal({"region"=>{"ids"=>["227"], "id"=>"230"}, "action"=>"browse", "task"=>"browse",
331
+ "controller"=>"results", "property_order_by"=>"property_type.descr"}, hash_dst)
332
+
333
+ hash_src = {"query_uuid"=>"6386333d-389b-ab5c-8943-6f3a2aa914d7", "region"=>{"ids"=>["--,227"], "id"=>"230"}}
334
+ hash_dst = {"query_uuid"=>"6386333d-389b-ab5c-8943-6f3a2aa914d7", "url_regions"=>[], "region"=>{"ids"=>["227", "233", "324", "230", "230"], "id"=>"230"}, "action"=>"browse", "task"=>"browse", "controller"=>"results", "property_order_by"=>"property_type.descr"}
335
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:overwrite_unmergeables => true, :knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
336
+ assert_equal({"query_uuid" => "6386333d-389b-ab5c-8943-6f3a2aa914d7", "url_regions"=>[],
337
+ "region"=>{"ids"=>["227"], "id"=>"230"}, "action"=>"browse", "task"=>"browse",
338
+ "controller"=>"results", "property_order_by"=>"property_type.descr"}, hash_dst)
339
+
340
+ # knock out entire dest hash if "--" is passed for source
341
+ hash_params = {'amenity' => "--"}
342
+ hash_session = {"amenity" => "1"}
343
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
344
+ assert_equal({'amenity' => ""}, hash_session)
345
+
346
+ # knock out entire dest hash if "--" is passed for source
347
+ hash_params = {'amenity' => ["--"]}
348
+ hash_session = {"amenity" => "1"}
349
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
350
+ assert_equal({'amenity' => []}, hash_session)
351
+
352
+ # knock out entire dest hash if "--" is passed for source
353
+ hash_params = {'amenity' => "--"}
354
+ hash_session = {"amenity" => ["1"]}
355
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
356
+ assert_equal({'amenity' => ""}, hash_session)
357
+
358
+ # knock out entire dest hash if "--" is passed for source
359
+ hash_params = {'amenity' => ["--"]}
360
+ hash_session = {"amenity" => ["1"]}
361
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
362
+ assert_equal({'amenity' => []}, hash_session)
363
+
364
+ # knock out entire dest hash if "--" is passed for source
365
+ hash_params = {'amenity' => ["--"]}
366
+ hash_session = {"amenity" => "1"}
367
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
368
+ assert_equal({'amenity' => []}, hash_session)
369
+
370
+ # knock out entire dest hash if "--" is passed for source
371
+ hash_params = {'amenity' => ["--", "2"]}
372
+ hash_session = {'amenity' => ["1", "3", "7+"]}
373
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
374
+ assert_equal({'amenity' => ["2"]}, hash_session)
375
+
376
+ # knock out entire dest hash if "--" is passed for source
377
+ hash_params = {'amenity' => ["--", "2"]}
378
+ hash_session = {'amenity' => "5"}
379
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
380
+ assert_equal({'amenity' => ['2']}, hash_session)
381
+
382
+ # knock out entire dest hash if "--" is passed for source
383
+ hash_params = {'amenity' => "--"}
384
+ hash_session = {"amenity"=>{"id"=>["1", "2", "3", "4"]}}
385
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
386
+ assert_equal({'amenity' => ""}, hash_session)
387
+
388
+ # knock out entire dest hash if "--" is passed for source
389
+ hash_params = {'amenity' => ["--"]}
390
+ hash_session = {"amenity"=>{"id"=>["1", "2", "3", "4"]}}
391
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => "--", :unpack_arrays => ","})
392
+ assert_equal({'amenity' => []}, hash_session)
393
+
394
+ # knock out dest array if "--" is passed for source
395
+ hash_params = {"region" => {'ids' => FIELD_KNOCKOUT_PREFIX}}
396
+ hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"]}}
397
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
398
+ assert_equal({'region' => {'ids' => ""}}, hash_session)
399
+
400
+ # knock out dest array but leave other elements of hash intact
401
+ hash_params = {"region" => {'ids' => FIELD_KNOCKOUT_PREFIX}}
402
+ hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
403
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
404
+ assert_equal({'region' => {'ids' => "", 'id'=>'11'}}, hash_session)
405
+
406
+ # knock out entire tree of dest hash
407
+ hash_params = {"region" => FIELD_KNOCKOUT_PREFIX}
408
+ hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
409
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
410
+ assert_equal({'region' => ""}, hash_session)
411
+
412
+ # knock out entire tree of dest hash - retaining array format
413
+ hash_params = {"region" => {'ids' => [FIELD_KNOCKOUT_PREFIX]}}
414
+ hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
415
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
416
+ assert_equal({'region' => {'ids' => [], 'id'=>'11'}}, hash_session)
417
+
418
+ # knock out entire tree of dest hash & replace with new content
419
+ hash_params = {"region" => {'ids' => ["2", FIELD_KNOCKOUT_PREFIX, "6"]}}
420
+ hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
421
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
422
+ assert_equal({'region' => {'ids' => ["2", "6"], 'id'=>'11'}}, hash_session)
423
+
424
+ # knock out entire tree of dest hash & replace with new content
425
+ hash_params = {"region" => {'ids' => ["7", FIELD_KNOCKOUT_PREFIX, "6"]}}
426
+ hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
427
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
428
+ assert_equal({'region' => {'ids' => ["7", "6"], 'id'=>'11'}}, hash_session)
429
+
430
+ # edge test: make sure that when we turn off knockout_prefix that all values are processed correctly
431
+ hash_params = {"region" => {'ids' => ["7", "--", "2", "6,8"]}}
432
+ hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
433
+ DeepMerge::deep_merge!(hash_params, hash_session, {:unpack_arrays => ","})
434
+ assert_equal({'region' => {'ids' => ["1", "2", "3", "4", "7", "--", "6", "8"], 'id'=>'11'}}, hash_session)
435
+
436
+ # edge test 2: make sure that when we turn off source array split that all values are processed correctly
437
+ hash_params = {"region" => {'ids' => ["7", "3", "--", "6,8"]}}
438
+ hash_session = {"region"=>{"ids"=>["1", "2", "3", "4"], 'id'=>'11'}}
439
+ DeepMerge::deep_merge!(hash_params, hash_session)
440
+ assert_equal({'region' => {'ids' => ["1", "2", "3", "4", "7", "--", "6,8"], 'id'=>'11'}}, hash_session)
441
+
442
+ # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
443
+ hash_params = {"amenity"=>"--1"}
444
+ hash_session = {"amenity"=>"1"}
445
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
446
+ assert_equal({"amenity"=>""}, hash_session)
447
+
448
+ # Example: src = {'key' => "--1"}, dst = {'key' => "2"} -> merges to {'key' => ""}
449
+ hash_params = {"amenity"=>"--1"}
450
+ hash_session = {"amenity"=>"2"}
451
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
452
+ assert_equal({"amenity"=>""}, hash_session)
453
+
454
+ # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
455
+ hash_params = {"amenity"=>["--1"]}
456
+ hash_session = {"amenity"=>"1"}
457
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
458
+ assert_equal({"amenity"=>[]}, hash_session)
459
+
460
+ # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
461
+ hash_params = {"amenity"=>["--1"]}
462
+ hash_session = {"amenity"=>["1"]}
463
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
464
+ assert_equal({"amenity"=>[]}, hash_session)
465
+
466
+ # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
467
+ hash_params = {"amenity"=>"--1"}
468
+ hash_session = {}
469
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
470
+ assert_equal({"amenity"=>""}, hash_session)
471
+
472
+
473
+ # Example: src = {'key' => "--1"}, dst = {'key' => "1"} -> merges to {'key' => ""}
474
+ hash_params = {"amenity"=>"--1"}
475
+ hash_session = {"amenity"=>["1"]}
476
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
477
+ assert_equal({"amenity"=>""}, hash_session)
478
+
479
+ #are unmerged hashes passed unmodified w/out :unpack_arrays?
480
+ hash_params = {"amenity"=>{"id"=>["26,27"]}}
481
+ hash_session = {}
482
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX})
483
+ assert_equal({"amenity"=>{"id"=>["26,27"]}}, hash_session)
484
+
485
+ #hash should be merged
486
+ hash_params = {"amenity"=>{"id"=>["26,27"]}}
487
+ hash_session = {}
488
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
489
+ assert_equal({"amenity"=>{"id"=>["26","27"]}}, hash_session)
490
+
491
+ # second merge of same values should result in no change in output
492
+ hash_params = {"amenity"=>{"id"=>["26,27"]}}
493
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
494
+ assert_equal({"amenity"=>{"id"=>["26","27"]}}, hash_session)
495
+
496
+ #hashes with knockout values are suppressed
497
+ hash_params = {"amenity"=>{"id"=>["#{FIELD_KNOCKOUT_PREFIX}26,#{FIELD_KNOCKOUT_PREFIX}27,28"]}}
498
+ hash_session = {}
499
+ DeepMerge::deep_merge!(hash_params, hash_session, {:knockout_prefix => FIELD_KNOCKOUT_PREFIX, :unpack_arrays => ","})
500
+ assert_equal({"amenity"=>{"id"=>["28"]}}, hash_session)
501
+
502
+ hash_src= {'region' =>{'ids'=>['--']}, 'query_uuid' => 'zzz'}
503
+ hash_dst= {'region' =>{'ids'=>['227','2','3','3']}, 'query_uuid' => 'zzz'}
504
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
505
+ assert_equal({'region' =>{'ids'=>[]}, 'query_uuid' => 'zzz'}, hash_dst)
506
+
507
+ hash_src= {'region' =>{'ids'=>['--']}, 'query_uuid' => 'zzz'}
508
+ hash_dst= {'region' =>{'ids'=>['227','2','3','3'], 'id' => '3'}, 'query_uuid' => 'zzz'}
509
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
510
+ assert_equal({'region' =>{'ids'=>[], 'id'=>'3'}, 'query_uuid' => 'zzz'}, hash_dst)
511
+
512
+ hash_src= {'region' =>{'ids'=>['--']}, 'query_uuid' => 'zzz'}
513
+ hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
514
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
515
+ assert_equal({'region' =>{'muni_city_id' => '2244', 'ids'=>[], 'id'=>'3'}, 'query_uuid' => 'zzz'}, hash_dst)
516
+
517
+ hash_src= {'region' =>{'ids'=>['--'], 'id' => '5'}, 'query_uuid' => 'zzz'}
518
+ hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
519
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
520
+ assert_equal({'region' =>{'muni_city_id' => '2244', 'ids'=>[], 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
521
+
522
+ hash_src= {'region' =>{'ids'=>['--', '227'], 'id' => '5'}, 'query_uuid' => 'zzz'}
523
+ hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
524
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
525
+ assert_equal({'region' =>{'muni_city_id' => '2244', 'ids'=>['227'], 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
526
+
527
+ hash_src= {'region' =>{'muni_city_id' => '--', 'ids'=>'--', 'id'=>'5'}, 'query_uuid' => 'zzz'}
528
+ hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
529
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
530
+ assert_equal({'region' =>{'muni_city_id' => '', 'ids'=>'', 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
531
+
532
+ hash_src= {'region' =>{'muni_city_id' => '--', 'ids'=>['--'], 'id'=>'5'}, 'query_uuid' => 'zzz'}
533
+ hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
534
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
535
+ assert_equal({'region' =>{'muni_city_id' => '', 'ids'=>[], 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
536
+
537
+ hash_src= {'region' =>{'muni_city_id' => '--', 'ids'=>['--','227'], 'id'=>'5'}, 'query_uuid' => 'zzz'}
538
+ hash_dst= {'region' =>{'muni_city_id' => '2244', 'ids'=>['227','2','3','3'], 'id'=>'3'}, 'query_uuid' => 'zzz'}
539
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
540
+ assert_equal({'region' =>{'muni_city_id' => '', 'ids'=>['227'], 'id'=>'5'}, 'query_uuid' => 'zzz'}, hash_dst)
541
+
542
+ hash_src = {"muni_city_id"=>"--", "id"=>""}
543
+ hash_dst = {"muni_city_id"=>"", "id"=>""}
544
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
545
+ assert_equal({"muni_city_id"=>"", "id"=>""}, hash_dst)
546
+
547
+ hash_src = {"region"=>{"muni_city_id"=>"--", "id"=>""}}
548
+ hash_dst = {"region"=>{"muni_city_id"=>"", "id"=>""}}
549
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
550
+ assert_equal({"region"=>{"muni_city_id"=>"", "id"=>""}}, hash_dst)
551
+
552
+ hash_src = {"query_uuid"=>"a0dc3c84-ec7f-6756-bdb0-fff9157438ab", "url_regions"=>[], "region"=>{"muni_city_id"=>"--", "id"=>""}, "property"=>{"property_type_id"=>"", "search_rate_min"=>"", "search_rate_max"=>""}, "task"=>"search", "run_query"=>"Search"}
553
+ hash_dst = {"query_uuid"=>"a0dc3c84-ec7f-6756-bdb0-fff9157438ab", "url_regions"=>[], "region"=>{"muni_city_id"=>"", "id"=>""}, "property"=>{"property_type_id"=>"", "search_rate_min"=>"", "search_rate_max"=>""}, "task"=>"search", "run_query"=>"Search"}
554
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:knockout_prefix => '--', :unpack_arrays => ","})
555
+ assert_equal({"query_uuid"=>"a0dc3c84-ec7f-6756-bdb0-fff9157438ab", "url_regions"=>[], "region"=>{"muni_city_id"=>"", "id"=>""}, "property"=>{"property_type_id"=>"", "search_rate_min"=>"", "search_rate_max"=>""}, "task"=>"search", "run_query"=>"Search"}, hash_dst)
556
+
557
+ # hash of array of hashes
558
+ hash_src = {"item" => [{"1" => "3"}, {"2" => "4"}]}
559
+ hash_dst = {"item" => [{"3" => "5"}]}
560
+ DeepMerge::deep_merge!(hash_src, hash_dst)
561
+ assert_equal({"item" => [{"3" => "5"}, {"1" => "3"}, {"2" => "4"}]}, hash_dst)
562
+
563
+ ######################################
564
+ # tests for "merge_hash_arrays" option
565
+
566
+ hash_src = {"item" => [{"1" => "3"}]}
567
+ hash_dst = {"item" => [{"3" => "5"}]}
568
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:merge_hash_arrays => true})
569
+ assert_equal({"item" => [{"3" => "5", "1" => "3"}]}, hash_dst)
570
+
571
+ hash_src = {"item" => [{"1" => "3"}, {"2" => "4"}]}
572
+ hash_dst = {"item" => [{"3" => "5"}]}
573
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:merge_hash_arrays => true})
574
+ assert_equal({"item" => [{"3" => "5", "1" => "3"}, {"2" => "4"}]}, hash_dst)
575
+
576
+ hash_src = {"item" => [{"1" => "3"}]}
577
+ hash_dst = {"item" => [{"3" => "5"}, {"2" => "4"}]}
578
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:merge_hash_arrays => true})
579
+ assert_equal({"item" => [{"3" => "5", "1" => "3"}, {"2" => "4"}]}, hash_dst)
580
+
581
+ # if arrays contain non-hash objects, the :merge_hash_arrays option has
582
+ # no effect.
583
+ hash_src = {"item" => [{"1" => "3"}, "str"]} # contains "str", non-hash
584
+ hash_dst = {"item" => [{"3" => "5"}]}
585
+ DeepMerge::deep_merge!(hash_src, hash_dst, {:merge_hash_arrays => true})
586
+ assert_equal({"item" => [{"3" => "5"}, {"1" => "3"}, "str"]}, hash_dst)
587
+
588
+ # Merging empty strings
589
+ s1, s2 = "hello", ""
590
+ [s1, s2].each { |s| s.extend StringBlank }
591
+ hash_dst = {"item" => s1 }
592
+ hash_src = {"item" => s2 }
593
+ DeepMerge::deep_merge!(hash_src, hash_dst)
594
+ assert_equal({"item" => ""}, hash_dst)
595
+ end # test_deep_merge
596
+ end