nice_hash 1.15.2 → 1.15.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b3dfa4920ee6ffc492f91f20f01fdad4e22953a681bd5071d7f7f72ecbed4eb
4
- data.tar.gz: 357269895379ab1744886a6107493f339820e4a5cf4bd81ddd9ed4f7ecb94de9
3
+ metadata.gz: 5e1518b1eb83a00333a4051d91aa0b40fb9fe58e4b0b3ad229fcc78b0f86eb56
4
+ data.tar.gz: 69c215835f068a459dfc0e01605c45c42a5447e4e818eeabfac3f90a746c6012
5
5
  SHA512:
6
- metadata.gz: acbd759da3e565e4493cd6c6b082e31248124cd93dec40d9572a695d2055ec4c34850c82c19f2e548e8c71c31a0504d6ae4cf0e4b4457d789eb90b299a1d6eee
7
- data.tar.gz: 80f5adf41b3c01f6c32aff59ff8410c507e53f937aa794523485699afc8ca796934f72b9cc3ec22ec8797265b62d7c96413b4d9d058b58f136943e47367904ef
6
+ metadata.gz: f61c5845665e7dcddf367e2850afb0d83b95bef3d39c8931be7bce5f27ffc24d6352b5c13d9a600f0d128fc25b1ff8332a2796943abf7f6fe647c4ac9739830e
7
+ data.tar.gz: 6f5ae2c245b192ee7ee331bf6d1a990551dd5e57e93997d168e83a3acfa2d471649ca83e06efdc0a3e18f4f948b1a7e594a6bdd5a2de916745bc9339e2228994
data/.yardopts CHANGED
@@ -5,6 +5,6 @@
5
5
  -
6
6
  lib/**/*.rb
7
7
  lib/nice_hash.rb
8
- lib/nice/hash/add_to_ruby.rb
8
+ lib/nice/hash/*.rb
9
9
  *.md
10
10
  LICENSE
@@ -0,0 +1,49 @@
1
+ class NiceHash
2
+ ###########################################################################
3
+ # Change only one value at a time and return an Array of Hashes
4
+ # Let's guess we need to test a typical registration REST service and the service has many fields with many validations but we want to test it one field at a time.
5
+ # This method generates values following the patterns on patterns_hash and generates a new hash for every pattern/select field found on patterns_hash using the value supplied on values_hash
6
+ # input:
7
+ # patterns_hash:
8
+ # (Hash) Hash where we have defined the patterns to follow.
9
+ # (Array) In case of array supplied, the pair: [pattern_hash, select_hash_key]. select_hash_key will filter the hash by that key
10
+ # values_hash: (Hash) Hash of values to use to modify the values generated on patterns_hash
11
+ # output: (Array of Hashes)
12
+ # example:
13
+ # wrong_min_length_hash = my_hash.generate(:correct, errors: :min_length)
14
+ # array_of_hashes = NiceHash.change_one_by_one([my_hash, :correct], wrong_min_length_hash)
15
+ # array_of_hashes.each {|hash_with_one_wrong_field|
16
+ # #Here your code to send through http the JSON data stored in hash_with_one_wrong_field
17
+ # #if you want to know which field is the one that is wrong:
18
+ # res = my_hash.validate(:correct, hash_with_one_wrong_field)
19
+ # }
20
+ ###########################################################################
21
+ def NiceHash.change_one_by_one(patterns_hash, values_hash)
22
+ if patterns_hash.kind_of?(Array)
23
+ select_key = patterns_hash[1]
24
+ pattern_hash = patterns_hash[0]
25
+ else
26
+ pattern_hash = patterns_hash
27
+ select_key = []
28
+ end
29
+ array = Array.new
30
+ good_values = NiceHash.generate(pattern_hash, select_key)
31
+ select_keys = pattern_hash.pattern_fields(select_key) + pattern_hash.select_fields(select_key)
32
+ select_keys.each { |field|
33
+ new_hash = Marshal.load(Marshal.dump(good_values))
34
+ # to deal with the case same values... like in pwd1, pwd2, pwd3
35
+ if field[-1].kind_of?(Array)
36
+ last_to_set = field[-1]
37
+ else
38
+ last_to_set = [field[-1]]
39
+ end
40
+ last_to_set.each { |f|
41
+ keys = field[0..-2] << f
42
+ new_hash.bury(keys, values_hash.dig(*keys))
43
+ }
44
+ array << new_hash
45
+ }
46
+ return array
47
+ end
48
+
49
+ end
@@ -0,0 +1,69 @@
1
+ class NiceHash
2
+ ##################################################
3
+ # Analyzes the supplied replica and verifies that the structure follows the one supplied on structure
4
+ #
5
+ # @param structure [Array] [Hash] Contains the structure that should follow the replica. It can be a nested combination of arrays and hashes.
6
+ # @param replica [Array] [Hash] Contains the element to be verified on following the supplied structure. It can be a nested combination of arrays and hashes.
7
+ # @param compare_only_if_exist_key [Boolean] (Default false) If true, in case an element exist on structure but doesn't exist on replica won't be verified.
8
+ # @param patterns [Hash] add verification of data values following the patterns supplied on a one level hash
9
+ #
10
+ # @return [Boolean] true in case replica follows the structure supplied
11
+ #
12
+ # @example
13
+ # my_structure = [
14
+ # { name: 'xxx',
15
+ # zip: 'yyyy',
16
+ # customer: true,
17
+ # product_ids: [1]
18
+ # }
19
+ # ]
20
+ # my_replica = [ {name: 'Peter Ben', zip: '1121A', customer: false, product_ids: []},
21
+ # {name: 'John Woop', zip: '74014', customer: true, product_ids: [10,120,301]}]
22
+ # NiceHash.compare_structure(my_structure, my_replica)
23
+ # #>true
24
+ ##################################################
25
+ def NiceHash.compare_structure(structure, replica, compare_only_if_exist_key = false, patterns = {})
26
+ unless structure.class == replica.class or
27
+ ((structure.is_a?(TrueClass) or structure.is_a?(FalseClass)) and (replica.is_a?(TrueClass) or replica.is_a?(FalseClass)))
28
+ puts "NiceHash.compare_structure: different object type #{structure.class} is not #{replica.class}. expected: #{structure.inspect}. found: #{replica.inspect}."
29
+ return false
30
+ end
31
+ success = true
32
+ if structure.is_a?(Hash)
33
+ structure.each do |key, value|
34
+ if patterns.key?(key) and replica.key?(key)
35
+ unless (patterns[key].is_a?(Array) and replica[key].is_a?(Array) and replica[key].empty?) or
36
+ {key => patterns[key]}.validate({key => replica[key]}).empty?
37
+ puts "NiceHash.compare_structure: key :#{key} not following pattern #{patterns[key]}. value: #{replica[key]}"
38
+ success = false
39
+ end
40
+ end
41
+
42
+ if compare_only_if_exist_key and replica.key?(key)
43
+ unless compare_structure(value, replica[key], compare_only_if_exist_key, patterns)
44
+ puts "NiceHash.compare_structure: key :#{key} different."
45
+ success = false
46
+ end
47
+ elsif compare_only_if_exist_key == false
48
+ unless replica.key?(key)
49
+ puts "NiceHash.compare_structure: key :#{key} missing."
50
+ success = false
51
+ else
52
+ unless compare_structure(value, replica[key], compare_only_if_exist_key, patterns)
53
+ puts "NiceHash.compare_structure: key :#{key} different."
54
+ success = false
55
+ end
56
+ end
57
+ end
58
+ end
59
+ elsif structure.is_a?(Array)
60
+ # compare all elements of replica with the structure of the first element on structure
61
+ replica.each do |elem|
62
+ unless compare_structure(structure[0], elem, compare_only_if_exist_key, patterns)
63
+ success = false
64
+ end
65
+ end
66
+ end
67
+ return success
68
+ end
69
+ end
@@ -0,0 +1,37 @@
1
+ class NiceHash
2
+ ##################################################
3
+ # Deletes the supplied nested key
4
+ #
5
+ # @param hash [Hash] The hash we want
6
+ # @param nested_key [Hash] [String] String with the nested key: 'uno.dos.tres' or a hash { uno: {dos: :tres} }
7
+ #
8
+ # @return [Hash]
9
+ #
10
+ # @example
11
+ # my_hash = { user: {
12
+ # address: {
13
+ # city: 'Madrid',
14
+ # country: 'Spain'
15
+ # },
16
+ # name: 'Peter',
17
+ # age: 33
18
+ # },
19
+ # customer: true
20
+ # }
21
+ # NiceHash.delete_nested(my_hash, 'user.address.city')
22
+ # #>{:user=>{:address=>{:country=>"Spain"}, :name=>"Peter", :age=>33}, :customer=>true}
23
+ ##################################################
24
+ def self.delete_nested(hash, nested_key)
25
+ nested_key = transtring(nested_key)
26
+ keys = nested_key.split(".")
27
+ if keys.size == 1
28
+ hash.delete(nested_key.to_sym)
29
+ else
30
+ last_key = keys[-1]
31
+ eval("hash.#{keys[0..(keys.size - 2)].join(".")}.delete(:#{last_key})")
32
+ end
33
+ return hash
34
+ end
35
+
36
+
37
+ end
@@ -0,0 +1,209 @@
1
+ class NiceHash
2
+
3
+ ###########################################################################
4
+ # It will generate a new hash with the values generated from the string patterns and select fields specified.
5
+ # In case supplied select_hash_key and a subhash specified on a value it will be selected only the value of the key specified on select_hash_key
6
+ # If expected_errors specified the values will be generated with the specified errors.
7
+ # input:
8
+ # pattern_hash: (Hash) Hash we want to use to generate the values
9
+ # select_hash_key: (key value) (optional) The key we want to select on the subhashes
10
+ # expected_errors: (Array) (optional) (alias: errors) To generate the string patterns with the specified errors.
11
+ # The possible values you can specify is one or more of these ones:
12
+ # :length: wrong length, minimum or maximum
13
+ # :min_length: wrong minimum length
14
+ # :max_length: wrong maximum length
15
+ # :value: wrong resultant value
16
+ # :required_data: the output string won't include all necessary required data. It works only if required data supplied on the pattern.
17
+ # :excluded_data: the resultant string will include one or more characters that should be excluded. It works only if excluded data supplied on the pattern.
18
+ # :string_set_not_allowed: it will include one or more characters that are not supposed to be on the string.
19
+ # output: (Hash)
20
+ # The Hash with the select_hash_key selected and the values generated from the string patterns and select fields specified.
21
+ # examples:
22
+ # new_hash = NiceHash.generate(my_hash)
23
+ # #> {:name=>"Peter",
24
+ # :address=>{:wrong=>"\#$$$$$", :correct=>"KZPCzxsWGMLqonesu wbqH"},
25
+ # :city=>{:wrong=>"Germany", :correct=>"Barcelona"},
26
+ # :products=> [
27
+ # {:name=>"gIqkWygmVm", :price=>{:wrong=>"-20", :correct=>"34338330"}},
28
+ # {:name=>"CK68VLIcYf", :price=>{:wrong=>"-20", :correct=>"616066520"}}
29
+ # ]
30
+ # }
31
+ # new_hash = NiceHash.generate(my_hash, :correct)
32
+ # #> {:name=>"Peter",
33
+ # :address=>"juQeAVZjIuWBPsE",
34
+ # :city=>"Madrid",
35
+ # :products=> [
36
+ # {:name=>"G44Ilr0puV", :price=>"477813"},
37
+ # {:name=>"v6ojs79LOp", :price=>"74820"}
38
+ # ]
39
+ # }
40
+ # new_hash = NiceHash.generate(my_hash, :correct, expected_errors: [:min_length])
41
+ # #> {:name=>"Peter",
42
+ # :address=>"ZytjefJ",
43
+ # :city=>"Madri",
44
+ # :products=>[
45
+ # {:name=>"cIBrzeO", :price=>""},
46
+ # {:name=>"5", :price=>""}
47
+ # ]
48
+ # }
49
+ # Using it directly on Hash class, generate(select_hash_key=nil, expected_errors: []) (alias: gen):
50
+ # new_hash = my_hash.generate
51
+ # new_hash = my_hash.gen(:correct)
52
+ # new_hash = my_hash.generate(:correct, errors: [:min_length])
53
+ ###########################################################################
54
+ def NiceHash.generate(pattern_hash, select_hash_key = nil, expected_errors: [], **synonyms)
55
+ hashv = Hash.new()
56
+ same_values = Hash.new()
57
+ expected_errors = synonyms[:errors] if synonyms.keys.include?(:errors)
58
+ if expected_errors.kind_of?(Symbol)
59
+ expected_errors = [expected_errors]
60
+ end
61
+
62
+ if pattern_hash.kind_of?(Hash) and pattern_hash.size > 0
63
+ pattern_hash.each { |key, value|
64
+ if key.kind_of?(Array)
65
+ same_values[key[0]] = key.dup
66
+ same_values[key[0]].shift
67
+ key = key[0]
68
+ end
69
+ if value.kind_of?(Hash)
70
+ if value.keys.include?(select_hash_key)
71
+ value = value[select_hash_key]
72
+ else
73
+ value = NiceHash.generate(value, select_hash_key, expected_errors: expected_errors)
74
+ end
75
+ end
76
+ if value.kind_of?(String) or value.kind_of?(Symbol)
77
+ if ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^!?\d+-?\d*:.+/).size > 0
78
+ hashv[key] = StringPattern.generate(value, expected_errors: expected_errors)
79
+ elsif ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size > 0
80
+ if expected_errors.include?(:min_length) or (expected_errors.include?(:length) and rand.round == 0)
81
+ min = value.to_s.split("|").min { |a, b| a.size <=> b.size }
82
+ hashv[key] = min[0..-2] unless min == ""
83
+ end
84
+ if !hashv.keys.include?(key) and (expected_errors.include?(:max_length) or expected_errors.include?(:length))
85
+ max = value.to_s.split("|").max { |a, b| a.size <=> b.size }
86
+ hashv[key] = max + max[-1]
87
+ end
88
+ if expected_errors.include?(:value) or
89
+ expected_errors.include?(:string_set_not_allowed) or
90
+ expected_errors.include?(:required_data)
91
+ if hashv.keys.include?(key)
92
+ v = hashv[key]
93
+ else
94
+ v = value.to_s.split("|").sample
95
+ end
96
+ unless expected_errors.include?(:string_set_not_allowed)
97
+ v = StringPattern.generate(:"#{v.size}:[#{value.to_s.split("|").join.split(//).uniq.join}]")
98
+ hashv[key] = v unless value.to_s.split("|").include?(v)
99
+ end
100
+ unless hashv.keys.include?(key)
101
+ one_wrong_letter = StringPattern.generate(:"1:LN$[%#{value.to_s.split("|").join.split(//).uniq.join}%]")
102
+ v[rand(v.size)] = one_wrong_letter
103
+ hashv[key] = v unless value.to_s.split("|").include?(v)
104
+ end
105
+ end
106
+ unless hashv.keys.include?(key)
107
+ hashv[key] = value.to_s.split("|").sample
108
+ end
109
+ else
110
+ hashv[key] = value
111
+ end
112
+ elsif value.kind_of?(Array)
113
+ array_pattern = false
114
+ value.each { |v|
115
+ if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
116
+ hashv[key] = StringPattern.generate(value, expected_errors: expected_errors)
117
+ array_pattern = true
118
+ break
119
+ end
120
+ }
121
+ unless array_pattern
122
+ value_ret = Array.new
123
+ value.each { |v|
124
+ if v.is_a?(Hash)
125
+ ret = NiceHash.generate(v, select_hash_key, expected_errors: expected_errors)
126
+ else
127
+ ret = NiceHash.generate({ doit: v }, select_hash_key, expected_errors: expected_errors)
128
+ ret = ret[:doit] if ret.is_a?(Hash) and ret.key?(:doit)
129
+ end
130
+ ret = v if ret.kind_of?(Hash) and ret.size == 0
131
+ value_ret << ret
132
+ }
133
+ hashv[key] = value_ret
134
+ end
135
+ elsif value.kind_of?(Range)
136
+ if expected_errors.empty?
137
+ hashv[key] = rand(value)
138
+ else
139
+ hashv[key] = rand(value)
140
+ expected_errors.each do |er|
141
+ if er == :min_length
142
+ hashv[key] = rand((value.first - value.last)..value.first - 1)
143
+ elsif er == :max_length
144
+ hashv[key] = rand((value.last + 1)..(value.last * 2))
145
+ elsif er == :length
146
+ if rand.round == 1
147
+ hashv[key] = rand((value.first - value.last)..value.first - 1)
148
+ else
149
+ hashv[key] = rand((value.last + 1)..(value.last * 2))
150
+ end
151
+ elsif er == :value
152
+ hashv[key] = :"1-10:N/L/".gen
153
+ end
154
+ end
155
+ end
156
+ elsif value.kind_of?(Class) and value == DateTime
157
+ if expected_errors.empty?
158
+ hashv[key] = Time.now.stamp
159
+ else
160
+ hashv[key] = Time.now.stamp
161
+ expected_errors.each do |er|
162
+ if er == :min_length
163
+ hashv[key] = hashv[key].chop
164
+ elsif er == :max_length
165
+ hashv[key] = hashv[key] + "Z"
166
+ elsif er == :length
167
+ if rand.round == 1
168
+ hashv[key] = hashv[key].chop
169
+ else
170
+ hashv[key] = hashv[key] + "Z"
171
+ end
172
+ elsif er == :value
173
+ hashv[key][rand(hashv[key].size - 1)] = "1:L".gen
174
+ end
175
+ end
176
+ end
177
+ elsif value.kind_of?(Module) and value == Boolean
178
+ if expected_errors.empty?
179
+ hashv[key] = (rand.round == 0)
180
+ else
181
+ hashv[key] = (rand.round == 0)
182
+ expected_errors.each do |er|
183
+ if er == :value
184
+ hashv[key] = "1-10:L".gen
185
+ end
186
+ end
187
+ end
188
+ elsif value.kind_of?(Proc)
189
+ hashv[key] = value.call
190
+ elsif value.kind_of?(Regexp)
191
+ hashv[key] = value.generate(expected_errors: expected_errors)
192
+ else
193
+ hashv[key] = value
194
+ end
195
+
196
+ if same_values.include?(key)
197
+ same_values[key].each { |k|
198
+ hashv[k] = hashv[key]
199
+ }
200
+ end
201
+
202
+ @values = hashv
203
+ }
204
+ end
205
+
206
+ return hashv
207
+ end
208
+
209
+ end
@@ -0,0 +1,26 @@
1
+ class NiceHash
2
+ ##################################################
3
+ # Get all the keys of a hash
4
+ #
5
+ # @param hash [Hash] The hash
6
+ #
7
+ # @return [Array]
8
+ #
9
+ # @example
10
+ # my_hash = { uno: {dos: {tres: 3}} }
11
+ # NiceHash.get_all_keys(my_hash)
12
+ # #>[:uno, :dos, :tres]
13
+ ##################################################
14
+ def self.get_all_keys(h)
15
+ h.each_with_object([]) do |(k, v), keys|
16
+ keys << k
17
+ keys.concat(get_all_keys(v)) if v.is_a? Hash
18
+ if v.is_a?(Array)
19
+ v.each do |vv|
20
+ keys.concat(get_all_keys(vv)) if vv.is_a? Hash or vv.is_a? Array
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,152 @@
1
+ class NiceHash
2
+
3
+ ##################################################
4
+ # Get values from the Hash structure (array of Hashes allowed)
5
+ # In case the key supplied doesn't exist in the hash then it will be returned nil for that one
6
+ # input:
7
+ # hashv: a simple hash or a hash containing arrays. Example:
8
+ # example={"id"=>344,
9
+ # "customer"=>{
10
+ # "name"=>"Peter Smith",
11
+ # "phone"=>334334333
12
+ # },
13
+ # "tickets"=>[
14
+ # {"idt"=>345,"name"=>"myFavor1"},
15
+ # {"idt"=>3123},
16
+ # {"idt"=>3145,"name"=>"Special ticket"}
17
+ # ]
18
+ # }
19
+ # keys: one key (string) or an array of keys. key can be a nested key
20
+ # output:
21
+ # a Hash of Arrays with all values found.
22
+ # Example of output with example.get_values("id","name")
23
+ # {"id"=>344, "name"=>["Peter Smith", ["myFavor1", "Special ticket"]]}
24
+ # Example of output with example.get_values("idt")
25
+ # {"idt"=>[345,3123,3145]}
26
+ # Example of output with example.get_values(:'tickets.idt')
27
+ # {:"tickets.idt"=>[345,3123,3145]}
28
+ #
29
+ ####################################################
30
+ def NiceHash.get_values(hashv, keys)
31
+ #todo: check if we should return {"id"=>344, "name"=>["Peter Smith", "myFavor1", "Special ticket"]} instead of
32
+ # {"id"=>344, "name"=>["Peter Smith", ["myFavor1", "Special ticket"]]}
33
+ if keys.kind_of?(String) or keys.kind_of?(Symbol)
34
+ keys = [keys]
35
+ end
36
+ if (keys.grep(/\./)).empty?
37
+ nested = false
38
+ else
39
+ nested = true
40
+ end
41
+ result = Hash.new()
42
+ number_of_results = Hash.new()
43
+ keys.each { |key|
44
+ number_of_results[key] = 0
45
+ }
46
+ if hashv.kind_of?(Array)
47
+ hashv.each { |tmp|
48
+ if tmp.kind_of?(Array) or tmp.kind_of?(Hash)
49
+ n_result = get_values(tmp, keys)
50
+ if n_result != :error
51
+ n_result.each { |n_key, n_value|
52
+ if result.has_key?(n_key)
53
+ if !result[n_key].kind_of?(Array) or
54
+ (result[n_key].kind_of?(Array) and number_of_results[n_key] < result[n_key].size)
55
+ if result[n_key].kind_of?(Hash) or result[n_key].kind_of?(Array)
56
+ res_tx = result[n_key].dup()
57
+ else
58
+ res_tx = result[n_key]
59
+ end
60
+ result[n_key] = Array.new()
61
+ result[n_key].push(res_tx)
62
+ result[n_key].push(n_value)
63
+ else
64
+ result[n_key].push(n_value)
65
+ end
66
+ else
67
+ result[n_key] = n_value
68
+ end
69
+ number_of_results[n_key] += 1
70
+ }
71
+ end
72
+ end
73
+ }
74
+ elsif hashv.kind_of?(Hash)
75
+ hashv.each { |key, value|
76
+ #if keys.include?(key) then
77
+ #added to be able to access the keys with symbols to strings and opposite
78
+ if keys.include?(key) or keys.include?(key.to_s) or keys.include?(key.to_sym)
79
+ #todo: check on next ruby versions since it will be not necessary to do it
80
+ #added to be able to access the keys with symbols to strings and opposite
81
+ key = key.to_s() if keys.include?(key.to_s)
82
+ key = key.to_sym() if keys.include?(key.to_sym)
83
+
84
+ if result.has_key?(key)
85
+ if !result[key].kind_of?(Array) or
86
+ (result[key].kind_of?(Array) and number_of_results[key] < result[key].size)
87
+ if result[key].kind_of?(Hash) or result[key].kind_of?(Array)
88
+ res_tx = result[key].dup()
89
+ else
90
+ res_tx = result[key]
91
+ end
92
+ result[key] = Array.new()
93
+ result[key].push(res_tx)
94
+ result[key].push(value)
95
+ else
96
+ result[key].push(value)
97
+ end
98
+ else
99
+ result[key] = value
100
+ end
101
+ number_of_results[key] += 1
102
+ end
103
+ if value.kind_of?(Array) or value.kind_of?(Hash)
104
+ if nested
105
+ keys_nested = []
106
+ keys.grep(/^#{key}\./).each do |k|
107
+ keys_nested << k.to_s.gsub(/^#{key}\./,'').to_sym
108
+ end
109
+ n_result_tmp = get_values(value, keys_nested)
110
+ n_result = {}
111
+ n_result_tmp.each do |k,v|
112
+ n_result["#{key}.#{k}".to_sym] = v
113
+ end
114
+ else
115
+ n_result = get_values(value, keys)
116
+ end
117
+ if n_result != :error
118
+ n_result.each { |n_key, n_value|
119
+ if result.has_key?(n_key)
120
+ if !result[n_key].kind_of?(Array) or
121
+ (result[n_key].kind_of?(Array) and number_of_results[n_key] < result[n_key].size)
122
+ if result[n_key].kind_of?(Hash) or result[n_key].kind_of?(Array)
123
+ res_tx = result[n_key].dup()
124
+ else
125
+ res_tx = result[n_key]
126
+ end
127
+ result[n_key] = Array.new()
128
+ result[n_key].push(res_tx)
129
+ result[n_key].push(n_value)
130
+ else
131
+ result[n_key].push(n_value)
132
+ end
133
+ else
134
+ result[n_key] = n_value
135
+ end
136
+ number_of_results[n_key] += 1
137
+ }
138
+ end
139
+ end
140
+ }
141
+ else
142
+ return :error
143
+ end
144
+ if result.kind_of?(Hash) and caller[0]["get_values"].nil? #no error or anything weird
145
+ (keys - result.keys).each { |k| #in case some keys don't exist in the hash
146
+ result[k] = nil
147
+ }
148
+ end
149
+ return result
150
+ end
151
+
152
+ end