deep_merge 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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