monkey_forms 0.0.16 → 0.0.17

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.
Files changed (25) hide show
  1. data/lib/monkey_forms/vendor/deep_merge/.gitignore +2 -0
  2. data/lib/monkey_forms/vendor/deep_merge/CHANGELOG +34 -0
  3. data/lib/monkey_forms/vendor/deep_merge/README +88 -0
  4. data/lib/monkey_forms/vendor/deep_merge/Rakefile +20 -0
  5. data/lib/monkey_forms/vendor/deep_merge/VERSION +1 -0
  6. data/lib/monkey_forms/vendor/deep_merge/lib/deep_merge.rb +2 -0
  7. data/lib/monkey_forms/vendor/deep_merge/lib/deep_merge/core.rb +187 -0
  8. data/lib/monkey_forms/vendor/deep_merge/lib/deep_merge/deep_merge_hash.rb +28 -0
  9. data/lib/monkey_forms/vendor/deep_merge/lib/deep_merge/rails_compat.rb +27 -0
  10. data/lib/monkey_forms/vendor/deep_merge/test/test_deep_merge.rb +572 -0
  11. data/lib/monkey_forms/vendor/grouped_validations/.gitignore +3 -0
  12. data/lib/monkey_forms/vendor/grouped_validations/.rspec +2 -0
  13. data/lib/monkey_forms/vendor/grouped_validations/Gemfile +7 -0
  14. data/lib/monkey_forms/vendor/grouped_validations/MIT-LICENSE +20 -0
  15. data/lib/monkey_forms/vendor/grouped_validations/README.rdoc +146 -0
  16. data/lib/monkey_forms/vendor/grouped_validations/Rakefile +26 -0
  17. data/lib/monkey_forms/vendor/grouped_validations/grouped_validations.gemspec +23 -0
  18. data/lib/monkey_forms/vendor/grouped_validations/init.rb +1 -0
  19. data/lib/monkey_forms/vendor/grouped_validations/lib/grouped_validations.rb +93 -0
  20. data/lib/monkey_forms/vendor/grouped_validations/lib/grouped_validations/active_model.rb +34 -0
  21. data/lib/monkey_forms/vendor/grouped_validations/lib/grouped_validations/version.rb +3 -0
  22. data/lib/monkey_forms/vendor/grouped_validations/spec/grouped_validations_spec.rb +252 -0
  23. data/lib/monkey_forms/vendor/grouped_validations/spec/spec_helper.rb +32 -0
  24. data/lib/monkey_forms/version.rb +1 -1
  25. metadata +42 -19
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ *.gemspec
@@ -0,0 +1,34 @@
1
+ 2011-05-23 Joe Van Dyk <joe@fixieconsulting.com>
2
+
3
+ * Added Changelog
4
+
5
+ 2011-05-18 Joe Van Dyk <joe@fixieconsulting.com>
6
+
7
+ * Merging empty strings should work if String#blank? is defined.
8
+
9
+ * Use unix line endings
10
+
11
+ * Removing extra whitespace
12
+
13
+ 2010-01-11 Dan DeLeo <danielsdeleo@mac.com>
14
+
15
+ * fix boolean merging according to mdkent's patch explicitly test
16
+ for nils w/ #nil? instead of negating. Thanks mdkent!
17
+
18
+ 2009-12-25 Dan DeLeo <danielsdeleo@mac.com>
19
+
20
+ * miscellaneous cleanup
21
+
22
+ * make rails/active_support compat optional
23
+
24
+ * add jeweler rake task for gemability
25
+
26
+ 2009-12-24 Dan DeLeo <danielsdeleo@mac.com>
27
+
28
+ * VERSION: Version bump to 0.0.1
29
+
30
+ * VERSION: Version bump to 0.0.0
31
+
32
+ 2009-11-06 Jonathan Weiss <jw@innerewut.de>
33
+
34
+ * import
@@ -0,0 +1,88 @@
1
+ DeepMerge Overview
2
+ ==================
3
+
4
+ Deep Merge is a simple set of utility functions for Hash. It permits
5
+ you to merge elements inside a hash together recursively. The manner
6
+ by which it does this is somewhat arbitrary (since there is no defining
7
+ standard for this) but it should end up being pretty intuitive and do what
8
+ you expect.
9
+
10
+ You can learn a lot more about this by reading the test file. It's pretty
11
+ well documented and has many examples of various merges from very simple
12
+ to pretty complex.
13
+
14
+ The primary need that caused me to write this library is the merging of elements
15
+ coming from HTTP parameters and related stored parameters in session. This lets
16
+ a user build up a set of parameters over time, modifying individual items.
17
+
18
+ Deep Merge Core Documentation
19
+ =============================
20
+ deep_merge! method permits merging of arbitrary child elements. The two top level
21
+ elements must be hashes. These hashes can contain unlimited (to stack limit) levels
22
+ of child elements. These child elements to not have to be of the same types.
23
+ Where child elements are of the same type, deep_merge will attempt to merge them together.
24
+ Where child elements are not of the same type, deep_merge will skip or optionally overwrite
25
+ the destination element with the contents of the source element at that level.
26
+ So if you have two hashes like this:
27
+ source = {:x => [1,2,3], :y => 2}
28
+ dest = {:x => [4,5,'6'], :y => [7,8,9]}
29
+ dest.deep_merge!(source)
30
+ Results: {:x => [1,2,3,4,5,'6'], :y => 2}
31
+ By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
32
+ To avoid this, use "deep_merge" (no bang/exclamation mark)
33
+
34
+ Options:
35
+ Options are specified in the last parameter passed, which should be in hash format:
36
+ hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'})
37
+ :preserve_unmergeables DEFAULT: false
38
+ Set to true to skip any unmergeable elements from source
39
+ :knockout_prefix DEFAULT: nil
40
+ Set to string value to signify prefix which deletes elements from existing element
41
+ :sort_merged_arrays DEFAULT: false
42
+ Set to true to sort all arrays that are merged together
43
+ :unpack_arrays DEFAULT: nil
44
+ Set to string value to run "Array::join" then "String::split" against all arrays
45
+ :merge_debug DEFAULT: false
46
+ Set to true to get console output of merge process for debugging
47
+
48
+ Selected Options Details:
49
+ :knockout_prefix => The purpose of this is to provide a way to remove elements
50
+ from existing Hash by specifying them in a special way in incoming hash
51
+ source = {:x => ['--1', '2']}
52
+ dest = {:x => ['1', '3']}
53
+ dest.ko_deep_merge!(source)
54
+ Results: {:x => ['2','3']}
55
+ Additionally, if the knockout_prefix is passed alone as a string, it will cause
56
+ the entire element to be removed:
57
+ source = {:x => '--'}
58
+ dest = {:x => [1,2,3]}
59
+ dest.ko_deep_merge!(source)
60
+ Results: {:x => ""}
61
+ :unpack_arrays => The purpose of this is to permit compound elements to be passed
62
+ in as strings and to be converted into discrete array elements
63
+ irsource = {:x => ['1,2,3', '4']}
64
+ dest = {:x => ['5','6','7,8']}
65
+ dest.deep_merge!(source, {:unpack_arrays => ','})
66
+ Results: {:x => ['1','2','3','4','5','6','7','8'}
67
+ Why: If receiving data from an HTML form, this makes it easy for a checkbox
68
+ to pass multiple values from within a single HTML element
69
+
70
+ There are many tests for this library - and you can learn more about the features
71
+ and usages of deep_merge! by just browsing the test examples
72
+
73
+
74
+ Simple Example Code
75
+ ===================
76
+
77
+ require 'deep_merge'
78
+ x = {:x => [3,4,5]}
79
+ y = {:x => [1,2,3]}
80
+ y.deep_merge!(x)
81
+ # results: y = {:x => [1,2,3,4,5]}
82
+
83
+ Availablility
84
+ =============
85
+ SVN Repo here: http://trac.misuse.org/science/wiki/DeepMerge
86
+ Contact author: http://www.misuse.org/science
87
+
88
+ Copyright (c) 2008 Steve Midgley, released under the MIT license
@@ -0,0 +1,20 @@
1
+
2
+ begin
3
+ require 'rubygems'
4
+ rescue LoadError
5
+ #okay, then
6
+ end
7
+
8
+ begin
9
+ require 'jeweler'
10
+ Jeweler::Tasks.new do |gemspec|
11
+ gemspec.name = "deep_merge"
12
+ gemspec.summary = "Merge Deeply Nested Hashes"
13
+ gemspec.description = "The Peritor Fork of deep_merge, with Ruby 1.9 and ActiveSupport Compatibility"
14
+ gemspec.email = "kontakt@peritor.com"
15
+ gemspec.homepage = "http://github.com/peritor/deep_merge"
16
+ gemspec.authors = ["Steve Midgley"]
17
+ end
18
+ rescue LoadError
19
+ puts "Jeweler not available. Install it with: sudo gem install jeweler"
20
+ end
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,2 @@
1
+ require 'deep_merge/core'
2
+ require 'deep_merge/deep_merge_hash'
@@ -0,0 +1,187 @@
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_debug DEFAULT: false
34
+ # Set to true to get console output of merge process for debugging
35
+ #
36
+ # Selected Options Details:
37
+ # :knockout_prefix => The purpose of this is to provide a way to remove elements
38
+ # from existing Hash by specifying them in a special way in incoming hash
39
+ # source = {:x => ['--1', '2']}
40
+ # dest = {:x => ['1', '3']}
41
+ # dest.ko_deep_merge!(source)
42
+ # Results: {:x => ['2','3']}
43
+ # Additionally, if the knockout_prefix is passed alone as a string, it will cause
44
+ # the entire element to be removed:
45
+ # source = {:x => '--'}
46
+ # dest = {:x => [1,2,3]}
47
+ # dest.ko_deep_merge!(source)
48
+ # Results: {:x => ""}
49
+ # :unpack_arrays => The purpose of this is to permit compound elements to be passed
50
+ # in as strings and to be converted into discrete array elements
51
+ # irsource = {:x => ['1,2,3', '4']}
52
+ # dest = {:x => ['5','6','7,8']}
53
+ # dest.deep_merge!(source, {:unpack_arrays => ','})
54
+ # Results: {:x => ['1','2','3','4','5','6','7','8'}
55
+ # Why: If receiving data from an HTML form, this makes it easy for a checkbox
56
+ # to pass multiple values from within a single HTML element
57
+ #
58
+ # There are many tests for this library - and you can learn more about the features
59
+ # and usages of deep_merge! by just browsing the test examples
60
+ def self.deep_merge!(source, dest, options = {})
61
+ # turn on this line for stdout debugging text
62
+ merge_debug = options[:merge_debug] || false
63
+ overwrite_unmergeable = !options[:preserve_unmergeables]
64
+ knockout_prefix = options[:knockout_prefix] || nil
65
+ raise InvalidParameter, "knockout_prefix cannot be an empty string in deep_merge!" if knockout_prefix == ""
66
+ raise InvalidParameter, "overwrite_unmergeable must be true if knockout_prefix is specified in deep_merge!" if knockout_prefix && !overwrite_unmergeable
67
+ # if present: we will split and join arrays on this char before merging
68
+ array_split_char = options[:unpack_arrays] || false
69
+ # request that we sort together any arrays when they are merged
70
+ sort_merged_arrays = options[:sort_merged_arrays] || false
71
+ di = options[:debug_indent] || ''
72
+ # do nothing if source is nil
73
+ return dest if source.nil?
74
+ # if dest doesn't exist, then simply copy source to it
75
+ if !(dest) && overwrite_unmergeable
76
+ dest = source; return dest
77
+ end
78
+
79
+ puts "#{di}Source class: #{source.class.inspect} :: Dest class: #{dest.class.inspect}" if merge_debug
80
+ if source.kind_of?(Hash)
81
+ puts "#{di}Hashes: #{source.inspect} :: #{dest.inspect}" if merge_debug
82
+ source.each do |src_key, src_value|
83
+ if dest.kind_of?(Hash)
84
+ puts "#{di} looping: #{src_key.inspect} => #{src_value.inspect} :: #{dest.inspect}" if merge_debug
85
+ if dest[src_key]
86
+ puts "#{di} ==>merging: #{src_key.inspect} => #{src_value.inspect} :: #{dest[src_key].inspect}" if merge_debug
87
+ dest[src_key] = deep_merge!(src_value, dest[src_key], options.merge(:debug_indent => di + ' '))
88
+ else # dest[src_key] doesn't exist so we want to create and overwrite it (but we do this via deep_merge!)
89
+ puts "#{di} ==>merging over: #{src_key.inspect} => #{src_value.inspect}" if merge_debug
90
+ # note: we rescue here b/c some classes respond to "dup" but don't implement it (Numeric, TrueClass, FalseClass, NilClass among maybe others)
91
+ begin
92
+ src_dup = src_value.dup # we dup src_value if possible because we're going to merge into it (since dest is empty)
93
+ rescue TypeError
94
+ src_dup = src_value
95
+ end
96
+ dest[src_key] = deep_merge!(src_value, src_dup, options.merge(:debug_indent => di + ' '))
97
+ end
98
+ else # dest isn't a hash, so we overwrite it completely (if permitted)
99
+ if overwrite_unmergeable
100
+ puts "#{di} overwriting dest: #{src_key.inspect} => #{src_value.inspect} -over-> #{dest.inspect}" if merge_debug
101
+ dest = overwrite_unmergeables(source, dest, options)
102
+ end
103
+ end
104
+ end
105
+ elsif source.kind_of?(Array)
106
+ puts "#{di}Arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
107
+ # if we are instructed, join/split any source arrays before processing
108
+ if array_split_char
109
+ puts "#{di} split/join on source: #{source.inspect}" if merge_debug
110
+ source = source.join(array_split_char).split(array_split_char)
111
+ if dest.kind_of?(Array)
112
+ dest = dest.join(array_split_char).split(array_split_char)
113
+ end
114
+ end
115
+ # if there's a naked knockout_prefix in source, that means we are to truncate dest
116
+ if source.index(knockout_prefix)
117
+ dest = clear_or_nil(dest); source.delete(knockout_prefix)
118
+ end
119
+ if dest.kind_of?(Array)
120
+ if knockout_prefix
121
+ print "#{di} knocking out: " if merge_debug
122
+ # remove knockout prefix items from both source and dest
123
+ source.delete_if do |ko_item|
124
+ retval = false
125
+ item = ko_item.respond_to?(:gsub) ? ko_item.gsub(%r{^#{knockout_prefix}}, "") : ko_item
126
+ if item != ko_item
127
+ print "#{ko_item} - " if merge_debug
128
+ dest.delete(item)
129
+ dest.delete(ko_item)
130
+ retval = true
131
+ end
132
+ retval
133
+ end
134
+ puts if merge_debug
135
+ end
136
+ puts "#{di} merging arrays: #{source.inspect} :: #{dest.inspect}" if merge_debug
137
+ dest = dest | source
138
+ dest.sort! if sort_merged_arrays
139
+ elsif overwrite_unmergeable
140
+ puts "#{di} overwriting dest: #{source.inspect} -over-> #{dest.inspect}" if merge_debug
141
+ dest = overwrite_unmergeables(source, dest, options)
142
+ end
143
+ else # src_hash is not an array or hash, so we'll have to overwrite dest
144
+ puts "#{di}Others: #{source.inspect} :: #{dest.inspect}" if merge_debug
145
+ dest = overwrite_unmergeables(source, dest, options)
146
+ end
147
+ puts "#{di}Returning #{dest.inspect}" if merge_debug
148
+ dest
149
+ end # deep_merge!
150
+
151
+ # allows deep_merge! to uniformly handle overwriting of unmergeable entities
152
+ def self.overwrite_unmergeables(source, dest, options)
153
+ merge_debug = options[:merge_debug] || false
154
+ overwrite_unmergeable = !options[:preserve_unmergeables]
155
+ knockout_prefix = options[:knockout_prefix] || false
156
+ di = options[:debug_indent] || ''
157
+ if knockout_prefix && overwrite_unmergeable
158
+ if source.kind_of?(String) # remove knockout string from source before overwriting dest
159
+ src_tmp = source.gsub(%r{^#{knockout_prefix}},"")
160
+ elsif source.kind_of?(Array) # remove all knockout elements before overwriting dest
161
+ src_tmp = source.delete_if {|ko_item| ko_item.kind_of?(String) && ko_item.match(%r{^#{knockout_prefix}}) }
162
+ else
163
+ src_tmp = source
164
+ end
165
+ if src_tmp == source # if we didn't find a knockout_prefix then we just overwrite dest
166
+ puts "#{di}#{src_tmp.inspect} -over-> #{dest.inspect}" if merge_debug
167
+ dest = src_tmp
168
+ else # if we do find a knockout_prefix, then we just delete dest
169
+ puts "#{di}\"\" -over-> #{dest.inspect}" if merge_debug
170
+ dest = ""
171
+ end
172
+ elsif overwrite_unmergeable
173
+ dest = source
174
+ end
175
+ dest
176
+ end
177
+
178
+ def self.clear_or_nil(obj)
179
+ if obj.respond_to?(:clear)
180
+ obj.clear
181
+ else
182
+ obj = nil
183
+ end
184
+ obj
185
+ end
186
+
187
+ 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
@@ -0,0 +1,572 @@
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
+ # Merging empty strings
565
+ s1, s2 = "hello", ""
566
+ [s1, s2].each { |s| s.extend StringBlank }
567
+ hash_dst = {"item" => s1 }
568
+ hash_src = {"item" => s2 }
569
+ DeepMerge::deep_merge!(hash_src, hash_dst)
570
+ assert_equal({"item" => ""}, hash_dst)
571
+ end # test_deep_merge
572
+ end