nice_hash 1.3.0 → 1.4.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.
Files changed (7) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +4 -4
  3. data/LICENSE +21 -21
  4. data/README.md +547 -545
  5. data/lib/nice/hash/add_to_ruby.rb +204 -189
  6. data/lib/nice_hash.rb +710 -710
  7. metadata +2 -2
@@ -1,189 +1,204 @@
1
- class String
2
- ###########################################################################
3
- # In case the string is a json it will return the keys specified. the keys need to be provided as symbols
4
- # input:
5
- # keys:
6
- # 1 value with key or an array of keys
7
- # In case the key supplied doesn't exist in the hash then it will be returned nil for that one
8
- # output:
9
- # if keys given: a hash of (keys, values) or the value, if the key is found more than once in the json string, then it will be return a hash op arrays
10
- # if no keys given, an empty hash
11
- ###########################################################################
12
- def json(*keys)
13
- require 'json'
14
- feed_symbols = JSON.parse(self, symbolize_names: true)
15
- result = {}
16
- if !keys.empty?
17
- result_tmp = if keys[0].is_a?(Symbol)
18
- NiceHash.get_values(feed_symbols, keys)
19
- else
20
- {}
21
- end
22
-
23
- if result_tmp.size == 1
24
- result = if result_tmp.values.is_a?(Array) && (result_tmp.values.size == 1)
25
- result_tmp.values[0]
26
- else
27
- result_tmp.values
28
- end
29
- else
30
- result_tmp.each do |key, value|
31
- result[key] = if (value.is_a?(Array) || value.is_a?(Hash)) && (value.size == 1)
32
- value[0]
33
- else
34
- value
35
- end
36
- end
37
- end
38
-
39
- else
40
- result = feed_symbols
41
- end
42
- result
43
- end
44
- end
45
-
46
- class Array
47
- ###########################################################################
48
- # Stores a value on the location indicated
49
- # input:
50
- # where: (Array)
51
- # value
52
- # examples:
53
- # my_array.bury([3, 0], "doom") # array of array
54
- # my_array.bury([2, 1, :original],"the value to set") #array of array of hash
55
- ###########################################################################
56
- def bury(where, value)
57
- me = self
58
- where[0..-2].each do |key|
59
- me = me[key]
60
- end
61
- me[where[-1]] = value
62
- end
63
-
64
- ###########################################################################
65
- # In case of an array of json strings will return the keys specified. The keys need to be provided as symbols
66
- # input:
67
- # keys:
68
- # 1 value with key or an array of keys
69
- # In case the key supplied doesn't exist in the hash then it will be return nil for that one
70
- # output:
71
- # if keys given: a hash of (keys, values) or the value, if the key is found more than once in the json string, then it will be return a hash of arrays
72
- # if no keys given, an empty hash
73
- ###########################################################################
74
- def json(*keys)
75
- json_string = "[#{join(',')}]"
76
- json_string.json(*keys)
77
- end
78
- end
79
-
80
- class Hash
81
- ###########################################################################
82
- # Returns the value of the key specified in case doesn't exist a Hash method with the same name
83
- # The keys can be accessed also adding underscore to avoid problems with existent methods
84
- # Also set values in case = supplied
85
- # examples:
86
- # my_hash.address.correct
87
- # my_hash._address._correct
88
- # my_hash.city
89
- # my_hash._city
90
- # my_hash.city="Paris"
91
- # my_hash.products[1].price.wrong="AAAAA"
92
- ###########################################################################
93
- def method_missing(m, *arguments, &block)
94
- m = m[1..-1].to_sym if m[0] == '_'
95
- if key?(m)
96
- self[m]
97
- elsif m.to_s[-1] == '='
98
- self[m.to_s.chop.to_sym] = arguments[0]
99
- else
100
- super
101
- end
102
- end
103
-
104
- ###########################################################################
105
- # Stores a value on the location indicated
106
- # input:
107
- # where: (Array)
108
- # value
109
- # examples:
110
- # my_hash.bury([:bip, :doom], "doom") # hash of hash
111
- # my_hash.bury([:original, 1, :doom],"the value to set") #hash of array of hash
112
- ###########################################################################
113
- def bury(where, value)
114
- me = self
115
- where[0..-2].each do |key|
116
- me = me[key]
117
- end
118
- key = where[-1]
119
- key = [key] unless where[-1].is_a?(Array) # for the case same value for different keys, for example pwd1, pwd2, pwd3
120
- key.each do |k|
121
- me[k] = value
122
- end
123
- end
124
-
125
- ###########################################################################
126
- # It will filter the hash by the key specified on select_hash_key.
127
- # In case a subhash specified on a value it will be selected only the value of the key specified on select_hash_key
128
- # More info: NiceHash.select_key
129
- ###########################################################################
130
- def select_key(select_hash_key)
131
- NiceHash.select_key(self, select_hash_key)
132
- end
133
-
134
- ###########################################################################
135
- # It will generate a new hash with the values generated from the string patterns and select fields specified.
136
- # 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
137
- # If expected_errors specified the values will be generated with the specified errors.
138
- # More info: NiceHash.generate
139
- # alias: gen
140
- ###########################################################################
141
- def generate(select_hash_key = nil, expected_errors: [], **synonyms)
142
- NiceHash.generate(self, select_hash_key, expected_errors: expected_errors, **synonyms)
143
- end
144
-
145
- ###########################################################################
146
- # Validates a given values_hash_to_validate with string patterns and select fields
147
- # More info: NiceHash.validate
148
- # alias: val
149
- ###########################################################################
150
- def validate(select_hash_key = nil, values_hash_to_validate)
151
- NiceHash.validate([self, select_hash_key], values_hash_to_validate, only_patterns: false)
152
- end
153
-
154
- ###########################################################################
155
- # Validates a given values_hash_to_validate with string patterns
156
- # More info: NiceHash.validate
157
- ###########################################################################
158
- def validate_patterns(select_hash_key = nil, values_hash_to_validate)
159
- NiceHash.validate([self, select_hash_key], values_hash_to_validate, only_patterns: true)
160
- end
161
-
162
- ###########################################################################
163
- # It will return an array of the keys where we are using string patterns.
164
- # More info: NiceHash.pattern_fields
165
- ###########################################################################
166
- def pattern_fields(*select_hash_key)
167
- NiceHash.pattern_fields(self, *select_hash_key)
168
- end
169
-
170
- ###########################################################################
171
- # It will return an array of the keys where we are using select values of the kind: "value1|value2|value3".
172
- # More info: NiceHash.select_fields
173
- ###########################################################################
174
- def select_fields(*select_hash_key)
175
- NiceHash.select_fields(self, *select_hash_key)
176
- end
177
-
178
- ###########################################################################
179
- # Get values of the keys supplied from the Hash structure.
180
- # More info: NiceHash.get_values
181
- ###########################################################################
182
- def get_values(*keys)
183
- NiceHash.get_values(self, keys)
184
- end
185
-
186
- alias gen generate
187
- alias val validate
188
- alias patterns pattern_fields
189
- end
1
+ class String
2
+
3
+ ###########################################################################
4
+ # When comparing an string and an integer, float or nil, it will be automatically converted to string:
5
+ # "300" == 300 #will return true
6
+ # 200.1=="200.1" #will return true
7
+ # ""==nil #will return true
8
+ ###########################################################################
9
+ def ==(par)
10
+ if par.kind_of?(Integer) or par.nil? or par.kind_of?(Float) then
11
+ super(par.to_s())
12
+ else
13
+ super(par)
14
+ end
15
+ end
16
+
17
+ ###########################################################################
18
+ # In case the string is a json it will return the keys specified. the keys need to be provided as symbols
19
+ # input:
20
+ # keys:
21
+ # 1 value with key or an array of keys
22
+ # In case the key supplied doesn't exist in the hash then it will be returned nil for that one
23
+ # output:
24
+ # if keys given: a hash of (keys, values) or the value, if the key is found more than once in the json string, then it will be return a hash op arrays
25
+ # if no keys given, an empty hash
26
+ ###########################################################################
27
+ def json(*keys)
28
+ require 'json'
29
+ feed_symbols = JSON.parse(self, symbolize_names: true)
30
+ result = {}
31
+ if !keys.empty?
32
+ result_tmp = if keys[0].is_a?(Symbol)
33
+ NiceHash.get_values(feed_symbols, keys)
34
+ else
35
+ {}
36
+ end
37
+
38
+ if result_tmp.size == 1
39
+ result = if result_tmp.values.is_a?(Array) && (result_tmp.values.size == 1)
40
+ result_tmp.values[0]
41
+ else
42
+ result_tmp.values
43
+ end
44
+ else
45
+ result_tmp.each do |key, value|
46
+ result[key] = if (value.is_a?(Array) || value.is_a?(Hash)) && (value.size == 1)
47
+ value[0]
48
+ else
49
+ value
50
+ end
51
+ end
52
+ end
53
+
54
+ else
55
+ result = feed_symbols
56
+ end
57
+ result
58
+ end
59
+ end
60
+
61
+ class Array
62
+ ###########################################################################
63
+ # Stores a value on the location indicated
64
+ # input:
65
+ # where: (Array)
66
+ # value
67
+ # examples:
68
+ # my_array.bury([3, 0], "doom") # array of array
69
+ # my_array.bury([2, 1, :original],"the value to set") #array of array of hash
70
+ ###########################################################################
71
+ def bury(where, value)
72
+ me = self
73
+ where[0..-2].each do |key|
74
+ me = me[key]
75
+ end
76
+ me[where[-1]] = value
77
+ end
78
+
79
+ ###########################################################################
80
+ # In case of an array of json strings will return the keys specified. The keys need to be provided as symbols
81
+ # input:
82
+ # keys:
83
+ # 1 value with key or an array of keys
84
+ # In case the key supplied doesn't exist in the hash then it will be return nil for that one
85
+ # output:
86
+ # if keys given: a hash of (keys, values) or the value, if the key is found more than once in the json string, then it will be return a hash of arrays
87
+ # if no keys given, an empty hash
88
+ ###########################################################################
89
+ def json(*keys)
90
+ json_string = "[#{join(',')}]"
91
+ json_string.json(*keys)
92
+ end
93
+ end
94
+
95
+ class Hash
96
+ ###########################################################################
97
+ # Returns the value of the key specified in case doesn't exist a Hash method with the same name
98
+ # The keys can be accessed also adding underscore to avoid problems with existent methods
99
+ # Also set values in case = supplied
100
+ # examples:
101
+ # my_hash.address.correct
102
+ # my_hash._address._correct
103
+ # my_hash.city
104
+ # my_hash._city
105
+ # my_hash.city="Paris"
106
+ # my_hash.products[1].price.wrong="AAAAA"
107
+ ###########################################################################
108
+ def method_missing(m, *arguments, &block)
109
+ m = m[1..-1].to_sym if m[0] == '_'
110
+ if key?(m)
111
+ self[m]
112
+ elsif m.to_s[-1] == '='
113
+ self[m.to_s.chop.to_sym] = arguments[0]
114
+ else
115
+ super
116
+ end
117
+ end
118
+
119
+ ###########################################################################
120
+ # Stores a value on the location indicated
121
+ # input:
122
+ # where: (Array)
123
+ # value
124
+ # examples:
125
+ # my_hash.bury([:bip, :doom], "doom") # hash of hash
126
+ # my_hash.bury([:original, 1, :doom],"the value to set") #hash of array of hash
127
+ ###########################################################################
128
+ def bury(where, value)
129
+ me = self
130
+ where[0..-2].each do |key|
131
+ me = me[key]
132
+ end
133
+ key = where[-1]
134
+ key = [key] unless where[-1].is_a?(Array) # for the case same value for different keys, for example pwd1, pwd2, pwd3
135
+ key.each do |k|
136
+ me[k] = value
137
+ end
138
+ end
139
+
140
+ ###########################################################################
141
+ # It will filter the hash by the key specified on select_hash_key.
142
+ # In case a subhash specified on a value it will be selected only the value of the key specified on select_hash_key
143
+ # More info: NiceHash.select_key
144
+ ###########################################################################
145
+ def select_key(select_hash_key)
146
+ NiceHash.select_key(self, select_hash_key)
147
+ end
148
+
149
+ ###########################################################################
150
+ # It will generate a new hash with the values generated from the string patterns and select fields specified.
151
+ # 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
152
+ # If expected_errors specified the values will be generated with the specified errors.
153
+ # More info: NiceHash.generate
154
+ # alias: gen
155
+ ###########################################################################
156
+ def generate(select_hash_key = nil, expected_errors: [], **synonyms)
157
+ NiceHash.generate(self, select_hash_key, expected_errors: expected_errors, **synonyms)
158
+ end
159
+
160
+ ###########################################################################
161
+ # Validates a given values_hash_to_validate with string patterns and select fields
162
+ # More info: NiceHash.validate
163
+ # alias: val
164
+ ###########################################################################
165
+ def validate(select_hash_key = nil, values_hash_to_validate)
166
+ NiceHash.validate([self, select_hash_key], values_hash_to_validate, only_patterns: false)
167
+ end
168
+
169
+ ###########################################################################
170
+ # Validates a given values_hash_to_validate with string patterns
171
+ # More info: NiceHash.validate
172
+ ###########################################################################
173
+ def validate_patterns(select_hash_key = nil, values_hash_to_validate)
174
+ NiceHash.validate([self, select_hash_key], values_hash_to_validate, only_patterns: true)
175
+ end
176
+
177
+ ###########################################################################
178
+ # It will return an array of the keys where we are using string patterns.
179
+ # More info: NiceHash.pattern_fields
180
+ ###########################################################################
181
+ def pattern_fields(*select_hash_key)
182
+ NiceHash.pattern_fields(self, *select_hash_key)
183
+ end
184
+
185
+ ###########################################################################
186
+ # It will return an array of the keys where we are using select values of the kind: "value1|value2|value3".
187
+ # More info: NiceHash.select_fields
188
+ ###########################################################################
189
+ def select_fields(*select_hash_key)
190
+ NiceHash.select_fields(self, *select_hash_key)
191
+ end
192
+
193
+ ###########################################################################
194
+ # Get values of the keys supplied from the Hash structure.
195
+ # More info: NiceHash.get_values
196
+ ###########################################################################
197
+ def get_values(*keys)
198
+ NiceHash.get_values(self, keys)
199
+ end
200
+
201
+ alias gen generate
202
+ alias val validate
203
+ alias patterns pattern_fields
204
+ end
data/lib/nice_hash.rb CHANGED
@@ -1,710 +1,710 @@
1
- SP_ADD_TO_RUBY = true if !defined?(SP_ADD_TO_RUBY)
2
- require_relative 'nice/hash/add_to_ruby' if SP_ADD_TO_RUBY
3
-
4
- require 'string_pattern'
5
-
6
- ###########################################################################
7
- # NiceHash creates hashes following certain patterns so your testing will be much easier.
8
- # You can easily generates all the hashes you want following the criteria you specify.
9
- # Many other features coming to Hash class like the methods 'bury' or select_key, access the keys like methods: my_hash.my_key.other_key.
10
- # You will be able to generate thousands of different hashes just declaring one and test easily APIs based on JSON for example.
11
- # To generate the strings following a pattern take a look at the documentation for string_pattern gem: https://github.com/MarioRuiz/string_pattern
12
- # This is the Hash we will be using on the examples declared on the methods source code documentation:
13
- # my_hash={
14
- # name: 'Peter',
15
- # address: {wrong: '#$$$$$', correct: :'10-30:L_'},
16
- # city: {wrong: 'Germany', correct: :'Madrid|Barcelona|London|Akureyri'},
17
- # products: [
18
- # {
19
- # name: :'10:Ln',
20
- # price: {wrong: '-20', correct: :'1-10:N'}
21
- # },
22
- # {
23
- # name: :'10:Ln',
24
- # price: {wrong: '-20', correct: :'1-10:N'}
25
- # },
26
- # ]
27
- # }
28
- ###########################################################################
29
- class NiceHash
30
-
31
- ###########################################################################
32
- # It will filter the hash by the key specified on select_hash_key.
33
- # In case a subhash specified on a value it will be selected only the value of the key specified on select_hash_key
34
- #
35
- # input:
36
- # pattern_hash: (Hash) Hash we want to select specific keys
37
- # select_hash_key: (key value) The key we want to select on the subhashes
38
- # output: (Hash)
39
- # The same hash but in case a subhash specified on a value it will be selected only the value of the key specified on select_hash_key
40
- # example:
41
- # new_hash = NiceHash.select_key(my_hash, :wrong)
42
- # #> {:name=>"Peter", :address=>"\#$$$$$", :city=>"Germany", :products=> [{:name=>:"10:Ln", :price=>"-20"}, {:name=>:"10:Ln", :price=>"-20"}]}
43
- # Using it directly on Hash class, select_key(select_hash_key):
44
- # new_hash = my_hash.select_key(:wrong)
45
- ###########################################################################
46
- def NiceHash.select_key(pattern_hash, select_hash_key)
47
- hash=Hash.new()
48
-
49
- if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
50
- pattern_hash.each {|key, value|
51
-
52
- if value.kind_of?(Hash)
53
- if value.keys.include?(select_hash_key)
54
- value=value[select_hash_key]
55
- else
56
- value=NiceHash.select_key(value, select_hash_key)
57
- end
58
- end
59
- if value.kind_of?(Array)
60
- array_pattern=false
61
- value.each {|v|
62
- if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
63
- hash[key]=value
64
- array_pattern=true
65
- break
66
- end
67
- }
68
- unless array_pattern
69
- value_ret=Array.new
70
- value.each {|v|
71
- ret=NiceHash.select_key(v, select_hash_key)
72
- value_ret<<ret
73
- }
74
- hash[key]=value_ret
75
- end
76
- else
77
- hash[key]=value
78
- end
79
- }
80
- else
81
- return pattern_hash
82
- end
83
- return hash
84
- end
85
-
86
- ###########################################################################
87
- # It will return an array of the keys where we are using string patterns.
88
- #
89
- # input:
90
- # pattern_hash: (Hash) Hash we want to get the pattern_fields
91
- # select_hash_key: (key value) (optional) The key we want to select on the subhashes
92
- # output: (Array)
93
- # Array of the kind: [ [key], [key, subkey, subkey] ]
94
- # Each value of the array can be used as parameter for the methods: dig, bury
95
- # examples:
96
- # NiceHash.pattern_fields(my_hash)
97
- # #> [
98
- # [:address, :correct],
99
- # [:products, 0, :name],
100
- # [:products, 0, :price, :correct],
101
- # [:products, 1, :name],
102
- # [:products, 1, :price, :correct]
103
- # ]
104
- # NiceHash.pattern_fields(my_hash, :correct)
105
- # #> [
106
- # [:address],
107
- # [:products, 0, :name],
108
- # [:products, 0, :price],
109
- # [:products, 1, :name],
110
- # [:products, 1, :price]
111
- # ]
112
- # Using it directly on Hash class, pattern_fields(*select_hash_key) (alias: patterns):
113
- # my_hash.pattern_fields
114
- # my_hash.pattern_fields(:correct)
115
- # my_hash.patterns(:correct)
116
- ###########################################################################
117
- def NiceHash.pattern_fields(pattern_hash, *select_hash_key)
118
- pattern_fields = Array.new
119
-
120
- if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
121
- pattern_hash.each {|key, value|
122
- key=[key]
123
- if value.kind_of?(Hash)
124
- if select_hash_key.size==1 and value.keys.include?(select_hash_key[0])
125
- value=value[select_hash_key[0]]
126
- else
127
- res=NiceHash.pattern_fields(value, *select_hash_key)
128
- if res.size>0
129
- res.each {|r|
130
- pattern_fields<<(r.unshift(key)).flatten
131
- }
132
- end
133
- next
134
- end
135
- end
136
- if value.kind_of?(String)
137
- if StringPattern.optimistic and value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
138
- pattern_fields << key
139
- end
140
- elsif value.kind_of?(Symbol)
141
- if value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
142
- pattern_fields << key
143
- end
144
- elsif value.kind_of?(Array)
145
-
146
- array_pattern=false
147
- value.each {|v|
148
- if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
149
- pattern_fields << key
150
- array_pattern=true
151
- break
152
- end
153
- }
154
- unless array_pattern
155
- i=0
156
- value.each {|v|
157
- res=NiceHash.pattern_fields(v, *select_hash_key)
158
- if res.size>0
159
- res.each {|r|
160
- pattern_fields<<(r.unshift(i).unshift(key)).flatten
161
- }
162
- end
163
- i+=1
164
- }
165
- end
166
- end
167
- }
168
- end
169
-
170
- return pattern_fields
171
- end
172
-
173
- ###########################################################################
174
- # It will return an array of the keys where we are using select values of the kind: "value1|value2|value3".
175
- #
176
- # input:
177
- # pattern_hash: (Hash) Hash we want to get the select_fields
178
- # select_hash_key: (key value) (optional) The key we want to select on the subhashes
179
- # output: (Array)
180
- # Array of the kind: [ [key], [key, subkey, subkey] ]
181
- # Each value of the array can be used as parameter for the methods: dig, bury
182
- # examples:
183
- # NiceHash.select_fields(my_hash)
184
- # #> [[:city, :correct]]
185
- # NiceHash.select_fields(my_hash, :correct)
186
- # #> [[:city]]
187
- # Using it directly on Hash class, select_fields(*select_hash_key):
188
- # my_hash.select_fields
189
- # my_hash.select_fields(:correct)
190
- ###########################################################################
191
- def NiceHash.select_fields(pattern_hash, *select_hash_key)
192
- select_fields = Array.new
193
-
194
- if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
195
- pattern_hash.each {|key, value|
196
- key=[key]
197
- if value.kind_of?(Hash)
198
- if select_hash_key.size==1 and value.keys.include?(select_hash_key[0])
199
- value=value[select_hash_key[0]]
200
- else
201
- res=NiceHash.select_fields(value, *select_hash_key)
202
- if res.size>0
203
- res.each {|r|
204
- select_fields<<(r.unshift(key)).flatten
205
- }
206
- end
207
- next
208
- end
209
- end
210
- if value.kind_of?(String)
211
- if StringPattern.optimistic and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
212
- select_fields << key
213
- end
214
- elsif value.kind_of?(Symbol)
215
- if value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
216
- select_fields << key
217
- end
218
- elsif value.kind_of?(Array)
219
-
220
- array_pattern=false
221
- value.each {|v|
222
- if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
223
- array_pattern=true
224
- break
225
- end
226
- }
227
- unless array_pattern
228
- i=0
229
- value.each {|v|
230
- res=NiceHash.select_fields(v, *select_hash_key)
231
- if res.size>0
232
- res.each {|r|
233
- select_fields<<(r.unshift(i).unshift(key)).flatten
234
- }
235
- end
236
- i+=1
237
- }
238
- end
239
- end
240
- }
241
- end
242
-
243
- return select_fields
244
- end
245
-
246
-
247
- ###########################################################################
248
- # It will generate a new hash with the values generated from the string patterns and select fields specified.
249
- # 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
250
- # If expected_errors specified the values will be generated with the specified errors.
251
- # input:
252
- # pattern_hash: (Hash) Hash we want to use to generate the values
253
- # select_hash_key: (key value) (optional) The key we want to select on the subhashes
254
- # expected_errors: (Array) (optional) (alias: errors) To generate the string patterns with the specified errors.
255
- # The possible values you can specify is one or more of these ones:
256
- # :length: wrong length, minimum or maximum
257
- # :min_length: wrong minimum length
258
- # :max_length: wrong maximum length
259
- # :value: wrong resultant value
260
- # :required_data: the output string won't include all necessary required data. It works only if required data supplied on the pattern.
261
- # :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.
262
- # :string_set_not_allowed: it will include one or more characters that are not supposed to be on the string.
263
- # output: (Hash)
264
- # The Hash with the select_hash_key selected and the values generated from the string patterns and select fields specified.
265
- # examples:
266
- # new_hash = NiceHash.generate(my_hash)
267
- # #> {:name=>"Peter",
268
- # :address=>{:wrong=>"\#$$$$$", :correct=>"KZPCzxsWGMLqonesu wbqH"},
269
- # :city=>{:wrong=>"Germany", :correct=>"Barcelona"},
270
- # :products=> [
271
- # {:name=>"gIqkWygmVm", :price=>{:wrong=>"-20", :correct=>"34338330"}},
272
- # {:name=>"CK68VLIcYf", :price=>{:wrong=>"-20", :correct=>"616066520"}}
273
- # ]
274
- # }
275
- # new_hash = NiceHash.generate(my_hash, :correct)
276
- # #> {:name=>"Peter",
277
- # :address=>"juQeAVZjIuWBPsE",
278
- # :city=>"Madrid",
279
- # :products=> [
280
- # {:name=>"G44Ilr0puV", :price=>"477813"},
281
- # {:name=>"v6ojs79LOp", :price=>"74820"}
282
- # ]
283
- # }
284
- # new_hash = NiceHash.generate(my_hash, :correct, expected_errors: [:min_length])
285
- # #> {:name=>"Peter",
286
- # :address=>"ZytjefJ",
287
- # :city=>"Madri",
288
- # :products=>[
289
- # {:name=>"cIBrzeO", :price=>""},
290
- # {:name=>"5", :price=>""}
291
- # ]
292
- # }
293
- # Using it directly on Hash class, generate(select_hash_key=nil, expected_errors: []) (alias: gen):
294
- # new_hash = my_hash.generate
295
- # new_hash = my_hash.gen(:correct)
296
- # new_hash = my_hash.generate(:correct, errors: [:min_length])
297
- ###########################################################################
298
- def NiceHash.generate(pattern_hash, select_hash_key=nil, expected_errors: [], **synonyms)
299
- hash=Hash.new()
300
- same_values=Hash.new()
301
- expected_errors=synonyms[:errors] if synonyms.keys.include?(:errors)
302
- if expected_errors.kind_of?(Symbol)
303
- expected_errors=[expected_errors]
304
- end
305
-
306
- if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
307
- pattern_hash.each {|key, value|
308
-
309
- if key.kind_of?(Array)
310
- same_values[key[0]]=key.dup
311
- same_values[key[0]].shift
312
- key=key[0]
313
- end
314
- if value.kind_of?(Hash)
315
- if value.keys.include?(select_hash_key)
316
- value=value[select_hash_key]
317
- else
318
- value=NiceHash.generate(value, select_hash_key, expected_errors: expected_errors)
319
- end
320
- end
321
-
322
- if value.kind_of?(String) or value.kind_of?(Symbol)
323
- if ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
324
- hash[key]=StringPattern.generate(value, expected_errors: expected_errors)
325
- elsif ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
326
- if expected_errors.include?(:min_length) or (expected_errors.include?(:length) and rand.round==0)
327
- min=value.to_s.split("|").min {|a, b| a.size <=> b.size}
328
- hash[key]=min[0..-2] unless min==""
329
- end
330
- if !hash.keys.include?(key) and (expected_errors.include?(:max_length) or expected_errors.include?(:length))
331
- max=value.to_s.split("|").max {|a, b| a.size <=> b.size}
332
- hash[key]=max+max[-1]
333
- end
334
- if expected_errors.include?(:value) or
335
- expected_errors.include?(:string_set_not_allowed) or
336
- expected_errors.include?(:required_data)
337
- if hash.keys.include?(key)
338
- v=hash[key]
339
- else
340
- v=value.to_s.split("|").sample
341
- end
342
- unless expected_errors.include?(:string_set_not_allowed)
343
- v=StringPattern.generate(:"#{v.size}:[#{value.to_s.split("|").join.split(//).uniq.join}]")
344
- hash[key]=v unless value.to_s.split("|").include?(v)
345
- end
346
- unless hash.keys.include?(key)
347
- one_wrong_letter=StringPattern.generate(:"1:LN$[%#{value.to_s.split("|").join.split(//).uniq.join}%]")
348
- v[rand(v.size)]=one_wrong_letter
349
- hash[key]=v unless value.to_s.split("|").include?(v)
350
- end
351
- end
352
- unless hash.keys.include?(key)
353
- hash[key]=value.to_s.split("|").sample
354
- end
355
- else
356
- hash[key]=value
357
- end
358
- elsif value.kind_of?(Array)
359
- array_pattern=false
360
- value.each {|v|
361
- if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
362
- hash[key]=StringPattern.generate(value, expected_errors: expected_errors)
363
- array_pattern=true
364
- break
365
- end
366
- }
367
- unless array_pattern
368
- value_ret=Array.new
369
- value.each {|v|
370
- ret=NiceHash.generate(v, select_hash_key, expected_errors: expected_errors)
371
- ret=v if ret.kind_of?(Hash) and ret.size==0
372
- value_ret<<ret
373
- }
374
- hash[key]=value_ret
375
- end
376
- else
377
- hash[key]=value
378
- end
379
-
380
- if same_values.include?(key)
381
- same_values[key].each {|k|
382
- hash[k]=hash[key]
383
- }
384
- end
385
-
386
- }
387
- end
388
-
389
- return hash
390
- end
391
-
392
-
393
- ###########################################################################
394
- # Validates a given values_hash_to_validate with string patterns and select fields from pattern_hash
395
- # input:
396
- # patterns_hash:
397
- # (Hash) Hash where we have defined the patterns to follow.
398
- # (Array) In case of array supplied, the pair: [pattern_hash, select_hash_key]. select_hash_key will filter the hash by that key
399
- # values_hash_to_validate: (Hash) Hash of values to validate
400
- # only_patterns: (TrueFalse) (by default true) If true it will validate only the patterns and not the other fields
401
- # output: (Hash)
402
- # A hash with the validation results. It will return only the validation errors so in case no validation errors found, empty hash.
403
- # The keys of the hash will be the keys of the values hash with the validation error.
404
- # The value in case of a pattern, will be an array with one or more of these possibilities:
405
- # :length: wrong length, minimum or maximum
406
- # :min_length: wrong minimum length
407
- # :max_length: wrong maximum length
408
- # :value: wrong resultant value
409
- # :required_data: the output string won't include all necessary required data. It works only if required data supplied on the pattern.
410
- # :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.
411
- # :string_set_not_allowed: it will include one or more characters that are not supposed to be on the string.
412
- # The value in any other case it will be false if the value is not corresponding to the expected.
413
- # examples:
414
- # values_to_validate = {:name=>"Peter",
415
- # :address=>"fnMuKW",
416
- # :city=>"Dublin",
417
- # :products=>[{:name=>"V4", :price=>"344"}, {:name=>"E", :price=>"a"}]
418
- # }
419
- # results = NiceHash.validate([my_hash, :correct], values_to_validate)
420
- # #> {:address=>[:min_length, :length],
421
- # :products=> [{:name=>[:min_length, :length]},
422
- # {:name=>[:min_length, :length], :price=>[:value, :string_set_not_allowed]}
423
- # ]
424
- # }
425
- # results = NiceHash.validate([my_hash, :correct], values_to_validate, only_patterns: false)
426
- # #> {:address=>[:min_length, :length],
427
- # :city=>false,
428
- # :products=> [{:name=>[:min_length, :length]},
429
- # {:name=>[:min_length, :length], :price=>[:value, :string_set_not_allowed]}
430
- # ]
431
- # }
432
- # Using it directly on Hash class:
433
- # validate(select_hash_key=nil, values_hash_to_validate) (alias: val)
434
- # validate_patterns(select_hash_key=nil, values_hash_to_validate)
435
- #
436
- # results = my_hash.validate_patterns(:correct, values_to_validate)
437
- # results = my_hash.validate(:correct, values_to_validate)
438
- ###########################################################################
439
- def NiceHash.validate(patterns_hash, values_hash_to_validate, only_patterns: true)
440
- if patterns_hash.kind_of?(Array)
441
- pattern_hash=patterns_hash[0]
442
- select_hash_key=patterns_hash[1]
443
- elsif patterns_hash.kind_of?(Hash)
444
- pattern_hash=patterns_hash
445
- select_hash_key=nil
446
- else
447
- puts "NiceHash.validate wrong pattern_hash supplied #{patterns_hash.inspect}"
448
- return {error: :error}
449
- end
450
- values = values_hash_to_validate
451
- results={}
452
- same_values={}
453
- if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
454
- pattern_hash.each {|key, value|
455
-
456
- if key.kind_of?(Array)
457
- same_values[key[0]]=key.dup
458
- same_values[key[0]].shift
459
- key=key[0]
460
- end
461
- if value.kind_of?(Hash)
462
- if !select_hash_key.nil? and value.keys.include?(select_hash_key)
463
- value=value[select_hash_key]
464
- elsif values.keys.include?(key) and values[key].kind_of?(Hash)
465
- res=NiceHash.validate([value, select_hash_key], values[key], only_patterns: only_patterns)
466
- results[key]=res if res.size>0
467
- next
468
- end
469
- end
470
-
471
- if values.keys.include?(key)
472
- if value.kind_of?(String) or value.kind_of?(Symbol)
473
- if ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
474
- res=StringPattern.validate(pattern: value, text: values[key])
475
- results[key]=res if res.size>0
476
- elsif !only_patterns and ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
477
- results[key]=false unless value.to_s.split("|").include?(values[key])
478
- elsif !only_patterns
479
- results[key]=false unless value.to_s==values[key].to_s
480
- end
481
- elsif value.kind_of?(Array)
482
- array_pattern=false
483
- complex_data=false
484
- value.each {|v|
485
- if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
486
- res=StringPattern.validate(pattern: value, text: values[key])
487
- results[key]=res if res==false
488
- array_pattern=true
489
- break
490
- elsif v.kind_of?(Hash) or v.kind_of?(Array) or v.kind_of?(Struct)
491
- complex_data=true
492
- break
493
- end
494
- }
495
- unless array_pattern or results.include?(key)
496
- i=0
497
- value.each {|v|
498
- res=NiceHash.validate([v, select_hash_key], values[key][i], only_patterns: only_patterns)
499
- if res.size>0
500
- results[key]=Array.new() if !results.keys.include?(key)
501
- results[key][i]=res
502
- end
503
- i+=1
504
- }
505
-
506
- end
507
- unless array_pattern or only_patterns or results.include?(key) or complex_data
508
- results[key]=false unless value==values[key]
509
- end
510
-
511
- else
512
- unless only_patterns
513
- results[key]=false unless value==values[key]
514
- end
515
- end
516
-
517
- if same_values.include?(key)
518
- same_values[key].each {|k|
519
- if values.keys.include?(k)
520
- if values[key]!=values[k]
521
- results[k]="Not equal to #{key}"
522
- end
523
- end
524
- }
525
- end
526
-
527
- end
528
- }
529
-
530
- end
531
-
532
- return results
533
- end
534
-
535
- ###########################################################################
536
- # Change only one value at a time and return an Array of Hashes
537
- # 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.
538
- # 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
539
- # input:
540
- # patterns_hash:
541
- # (Hash) Hash where we have defined the patterns to follow.
542
- # (Array) In case of array supplied, the pair: [pattern_hash, select_hash_key]. select_hash_key will filter the hash by that key
543
- # values_hash: (Hash) Hash of values to use to modify the values generated on patterns_hash
544
- # output: (Array of Hashes)
545
- # example:
546
- # wrong_min_length_hash = my_hash.generate(:correct, errors: :min_length)
547
- # array_of_hashes = NiceHash.change_one_by_one([my_hash, :correct], wrong_min_length_hash)
548
- # array_of_hashes.each {|hash_with_one_wrong_field|
549
- # #Here your code to send through http the JSON data stored in hash_with_one_wrong_field
550
- # #if you want to know which field is the one that is wrong:
551
- # res = my_hash.validate(:correct, hash_with_one_wrong_field)
552
- # }
553
- ###########################################################################
554
- def NiceHash.change_one_by_one(patterns_hash, values_hash)
555
- if patterns_hash.kind_of?(Array)
556
- select_key=patterns_hash[1]
557
- pattern_hash=patterns_hash[0]
558
- else
559
- pattern_hash=patterns_hash
560
- select_key=[]
561
- end
562
- array=Array.new
563
- good_values=NiceHash.generate(pattern_hash, select_key)
564
- select_keys=pattern_hash.pattern_fields(select_key)+pattern_hash.select_fields(select_key)
565
- select_keys.each {|field|
566
- new_hash=Marshal.load(Marshal.dump(good_values))
567
- # to deal with the case same values... like in pwd1, pwd2, pwd3
568
- if field[-1].kind_of?(Array)
569
- last_to_set=field[-1]
570
- else
571
- last_to_set=[field[-1]]
572
- end
573
- last_to_set.each {|f|
574
- keys=field[0..-2]<<f
575
- new_hash.bury(keys, values_hash.dig(*keys))
576
- }
577
- array<<new_hash
578
- }
579
- return array
580
- end
581
-
582
-
583
- ##################################################
584
- # Get values from the Hash structure (array of Hashes allowed)
585
- # In case the key supplied doesn't exist in the hash then it will be return nil for that one
586
- # input:
587
- # hash: a simple hash or a hash containing arrays. Example:
588
- # example={"id"=>344,
589
- # "customer"=>{
590
- # "name"=>"Peter Smith",
591
- # "phone"=>334334333
592
- # },
593
- # "tickets"=>[
594
- # {"idt"=>345,"name"=>"myFavor1"},
595
- # {"idt"=>3123},
596
- # {"idt"=>3145,"name"=>"Special ticket"}
597
- # ]
598
- # }
599
- # keys: one key (string) or an array of keys
600
- # output:
601
- # a Hash of Arrays with all values found.
602
- # Example of output with example.get_values("id","name")
603
- # {"id"=>[334],"name"=>["Peter North"]}
604
- # Example of output with example.get_values("idt")
605
- # {"idt"=>[345,3123,3145]}
606
- #
607
- ####################################################
608
- def NiceHash.get_values(hash,keys)
609
- if keys.kind_of?(String) or keys.kind_of?(Symbol) then
610
- keys=[keys]
611
- end
612
- result=Hash.new()
613
- number_of_results=Hash.new()
614
- keys.each {|key|
615
- number_of_results[key]=0
616
- }
617
- if hash.kind_of?(Array) then
618
- hash.each {|tmp|
619
- if tmp.kind_of?(Array) or tmp.kind_of?(Hash) then
620
- n_result=get_values(tmp, keys)
621
- if n_result!=:error then
622
- n_result.each {|n_key, n_value|
623
- if result.has_key?(n_key) then
624
- if !result[n_key].kind_of?(Array) or
625
- (result[n_key].kind_of?(Array) and number_of_results[n_key] < result[n_key].size) then
626
- if result[n_key].kind_of?(Hash) or result[n_key].kind_of?(Array) then
627
- res_tx=result[n_key].dup()
628
- else
629
- res_tx=result[n_key]
630
- end
631
- result[n_key]=Array.new()
632
- result[n_key].push(res_tx)
633
- result[n_key].push(n_value)
634
- else
635
- result[n_key].push(n_value)
636
- end
637
- else
638
- result[n_key]=n_value
639
- end
640
- number_of_results[n_key]+=1
641
- }
642
- end
643
- end
644
- }
645
- elsif hash.kind_of?(Hash) then
646
- hash.each {|key, value|
647
- #if keys.include?(key) then
648
- #added to be able to access the keys with symbols to strings and opposite
649
- if keys.include?(key) or keys.include?(key.to_s) or keys.include?(key.to_sym) then
650
- #added to be able to access the keys with symbols to strings and opposite
651
- key=key.to_s() if keys.include?(key.to_s)
652
- key=key.to_sym() if keys.include?(key.to_sym)
653
-
654
- if result.has_key?(key) then
655
- if !result[key].kind_of?(Array) or
656
- (result[key].kind_of?(Array) and number_of_results[key] < result[key].size) then
657
- if result[key].kind_of?(Hash) or result[key].kind_of?(Array) then
658
- res_tx=result[key].dup()
659
- else
660
- res_tx=result[key]
661
- end
662
- result[key]=Array.new()
663
- result[key].push(res_tx)
664
- result[key].push(value)
665
- else
666
- result[key].push(value)
667
- end
668
- else
669
- result[key]=value
670
- end
671
- number_of_results[key]+=1
672
- end
673
- if value.kind_of?(Array) or value.kind_of?(Hash) then
674
- n_result=get_values(value, keys)
675
- if n_result!=:error then
676
- n_result.each {|n_key, n_value|
677
- if result.has_key?(n_key) then
678
- if !result[n_key].kind_of?(Array) or
679
- (result[n_key].kind_of?(Array) and number_of_results[n_key] < result[n_key].size) then
680
- if result[n_key].kind_of?(Hash) or result[n_key].kind_of?(Array) then
681
- res_tx=result[n_key].dup()
682
- else
683
- res_tx=result[n_key]
684
- end
685
- result[n_key]=Array.new()
686
- result[n_key].push(res_tx)
687
- result[n_key].push(n_value)
688
- else
689
- result[n_key].push(n_value)
690
- end
691
- else
692
- result[n_key]=n_value
693
- end
694
- number_of_results[n_key]+=1
695
- }
696
- end
697
- end
698
- }
699
- else
700
- return :error
701
- end
702
- if result.kind_of?(Hash) and caller[0]["get_values"].nil? then #no error or anything weird
703
- (keys-result.keys).each {|k| #in case some keys don't exist in the hash
704
- result[k]=nil
705
- }
706
- end
707
- return result
708
- end
709
-
710
- end
1
+ SP_ADD_TO_RUBY = true if !defined?(SP_ADD_TO_RUBY)
2
+ require_relative 'nice/hash/add_to_ruby' if SP_ADD_TO_RUBY
3
+
4
+ require 'string_pattern'
5
+
6
+ ###########################################################################
7
+ # NiceHash creates hashes following certain patterns so your testing will be much easier.
8
+ # You can easily generates all the hashes you want following the criteria you specify.
9
+ # Many other features coming to Hash class like the methods 'bury' or select_key, access the keys like methods: my_hash.my_key.other_key.
10
+ # You will be able to generate thousands of different hashes just declaring one and test easily APIs based on JSON for example.
11
+ # To generate the strings following a pattern take a look at the documentation for string_pattern gem: https://github.com/MarioRuiz/string_pattern
12
+ # This is the Hash we will be using on the examples declared on the methods source code documentation:
13
+ # my_hash={
14
+ # name: 'Peter',
15
+ # address: {wrong: '#$$$$$', correct: :'10-30:L_'},
16
+ # city: {wrong: 'Germany', correct: :'Madrid|Barcelona|London|Akureyri'},
17
+ # products: [
18
+ # {
19
+ # name: :'10:Ln',
20
+ # price: {wrong: '-20', correct: :'1-10:N'}
21
+ # },
22
+ # {
23
+ # name: :'10:Ln',
24
+ # price: {wrong: '-20', correct: :'1-10:N'}
25
+ # },
26
+ # ]
27
+ # }
28
+ ###########################################################################
29
+ class NiceHash
30
+
31
+ ###########################################################################
32
+ # It will filter the hash by the key specified on select_hash_key.
33
+ # In case a subhash specified on a value it will be selected only the value of the key specified on select_hash_key
34
+ #
35
+ # input:
36
+ # pattern_hash: (Hash) Hash we want to select specific keys
37
+ # select_hash_key: (key value) The key we want to select on the subhashes
38
+ # output: (Hash)
39
+ # The same hash but in case a subhash specified on a value it will be selected only the value of the key specified on select_hash_key
40
+ # example:
41
+ # new_hash = NiceHash.select_key(my_hash, :wrong)
42
+ # #> {:name=>"Peter", :address=>"\#$$$$$", :city=>"Germany", :products=> [{:name=>:"10:Ln", :price=>"-20"}, {:name=>:"10:Ln", :price=>"-20"}]}
43
+ # Using it directly on Hash class, select_key(select_hash_key):
44
+ # new_hash = my_hash.select_key(:wrong)
45
+ ###########################################################################
46
+ def NiceHash.select_key(pattern_hash, select_hash_key)
47
+ hash=Hash.new()
48
+
49
+ if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
50
+ pattern_hash.each {|key, value|
51
+
52
+ if value.kind_of?(Hash)
53
+ if value.keys.include?(select_hash_key)
54
+ value=value[select_hash_key]
55
+ else
56
+ value=NiceHash.select_key(value, select_hash_key)
57
+ end
58
+ end
59
+ if value.kind_of?(Array)
60
+ array_pattern=false
61
+ value.each {|v|
62
+ if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
63
+ hash[key]=value
64
+ array_pattern=true
65
+ break
66
+ end
67
+ }
68
+ unless array_pattern
69
+ value_ret=Array.new
70
+ value.each {|v|
71
+ ret=NiceHash.select_key(v, select_hash_key)
72
+ value_ret<<ret
73
+ }
74
+ hash[key]=value_ret
75
+ end
76
+ else
77
+ hash[key]=value
78
+ end
79
+ }
80
+ else
81
+ return pattern_hash
82
+ end
83
+ return hash
84
+ end
85
+
86
+ ###########################################################################
87
+ # It will return an array of the keys where we are using string patterns.
88
+ #
89
+ # input:
90
+ # pattern_hash: (Hash) Hash we want to get the pattern_fields
91
+ # select_hash_key: (key value) (optional) The key we want to select on the subhashes
92
+ # output: (Array)
93
+ # Array of the kind: [ [key], [key, subkey, subkey] ]
94
+ # Each value of the array can be used as parameter for the methods: dig, bury
95
+ # examples:
96
+ # NiceHash.pattern_fields(my_hash)
97
+ # #> [
98
+ # [:address, :correct],
99
+ # [:products, 0, :name],
100
+ # [:products, 0, :price, :correct],
101
+ # [:products, 1, :name],
102
+ # [:products, 1, :price, :correct]
103
+ # ]
104
+ # NiceHash.pattern_fields(my_hash, :correct)
105
+ # #> [
106
+ # [:address],
107
+ # [:products, 0, :name],
108
+ # [:products, 0, :price],
109
+ # [:products, 1, :name],
110
+ # [:products, 1, :price]
111
+ # ]
112
+ # Using it directly on Hash class, pattern_fields(*select_hash_key) (alias: patterns):
113
+ # my_hash.pattern_fields
114
+ # my_hash.pattern_fields(:correct)
115
+ # my_hash.patterns(:correct)
116
+ ###########################################################################
117
+ def NiceHash.pattern_fields(pattern_hash, *select_hash_key)
118
+ pattern_fields = Array.new
119
+
120
+ if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
121
+ pattern_hash.each {|key, value|
122
+ key=[key]
123
+ if value.kind_of?(Hash)
124
+ if select_hash_key.size==1 and value.keys.include?(select_hash_key[0])
125
+ value=value[select_hash_key[0]]
126
+ else
127
+ res=NiceHash.pattern_fields(value, *select_hash_key)
128
+ if res.size>0
129
+ res.each {|r|
130
+ pattern_fields<<(r.unshift(key)).flatten
131
+ }
132
+ end
133
+ next
134
+ end
135
+ end
136
+ if value.kind_of?(String)
137
+ if StringPattern.optimistic and value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
138
+ pattern_fields << key
139
+ end
140
+ elsif value.kind_of?(Symbol)
141
+ if value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
142
+ pattern_fields << key
143
+ end
144
+ elsif value.kind_of?(Array)
145
+
146
+ array_pattern=false
147
+ value.each {|v|
148
+ if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
149
+ pattern_fields << key
150
+ array_pattern=true
151
+ break
152
+ end
153
+ }
154
+ unless array_pattern
155
+ i=0
156
+ value.each {|v|
157
+ res=NiceHash.pattern_fields(v, *select_hash_key)
158
+ if res.size>0
159
+ res.each {|r|
160
+ pattern_fields<<(r.unshift(i).unshift(key)).flatten
161
+ }
162
+ end
163
+ i+=1
164
+ }
165
+ end
166
+ end
167
+ }
168
+ end
169
+
170
+ return pattern_fields
171
+ end
172
+
173
+ ###########################################################################
174
+ # It will return an array of the keys where we are using select values of the kind: "value1|value2|value3".
175
+ #
176
+ # input:
177
+ # pattern_hash: (Hash) Hash we want to get the select_fields
178
+ # select_hash_key: (key value) (optional) The key we want to select on the subhashes
179
+ # output: (Array)
180
+ # Array of the kind: [ [key], [key, subkey, subkey] ]
181
+ # Each value of the array can be used as parameter for the methods: dig, bury
182
+ # examples:
183
+ # NiceHash.select_fields(my_hash)
184
+ # #> [[:city, :correct]]
185
+ # NiceHash.select_fields(my_hash, :correct)
186
+ # #> [[:city]]
187
+ # Using it directly on Hash class, select_fields(*select_hash_key):
188
+ # my_hash.select_fields
189
+ # my_hash.select_fields(:correct)
190
+ ###########################################################################
191
+ def NiceHash.select_fields(pattern_hash, *select_hash_key)
192
+ select_fields = Array.new
193
+
194
+ if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
195
+ pattern_hash.each {|key, value|
196
+ key=[key]
197
+ if value.kind_of?(Hash)
198
+ if select_hash_key.size==1 and value.keys.include?(select_hash_key[0])
199
+ value=value[select_hash_key[0]]
200
+ else
201
+ res=NiceHash.select_fields(value, *select_hash_key)
202
+ if res.size>0
203
+ res.each {|r|
204
+ select_fields<<(r.unshift(key)).flatten
205
+ }
206
+ end
207
+ next
208
+ end
209
+ end
210
+ if value.kind_of?(String)
211
+ if StringPattern.optimistic and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
212
+ select_fields << key
213
+ end
214
+ elsif value.kind_of?(Symbol)
215
+ if value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
216
+ select_fields << key
217
+ end
218
+ elsif value.kind_of?(Array)
219
+
220
+ array_pattern=false
221
+ value.each {|v|
222
+ if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
223
+ array_pattern=true
224
+ break
225
+ end
226
+ }
227
+ unless array_pattern
228
+ i=0
229
+ value.each {|v|
230
+ res=NiceHash.select_fields(v, *select_hash_key)
231
+ if res.size>0
232
+ res.each {|r|
233
+ select_fields<<(r.unshift(i).unshift(key)).flatten
234
+ }
235
+ end
236
+ i+=1
237
+ }
238
+ end
239
+ end
240
+ }
241
+ end
242
+
243
+ return select_fields
244
+ end
245
+
246
+
247
+ ###########################################################################
248
+ # It will generate a new hash with the values generated from the string patterns and select fields specified.
249
+ # 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
250
+ # If expected_errors specified the values will be generated with the specified errors.
251
+ # input:
252
+ # pattern_hash: (Hash) Hash we want to use to generate the values
253
+ # select_hash_key: (key value) (optional) The key we want to select on the subhashes
254
+ # expected_errors: (Array) (optional) (alias: errors) To generate the string patterns with the specified errors.
255
+ # The possible values you can specify is one or more of these ones:
256
+ # :length: wrong length, minimum or maximum
257
+ # :min_length: wrong minimum length
258
+ # :max_length: wrong maximum length
259
+ # :value: wrong resultant value
260
+ # :required_data: the output string won't include all necessary required data. It works only if required data supplied on the pattern.
261
+ # :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.
262
+ # :string_set_not_allowed: it will include one or more characters that are not supposed to be on the string.
263
+ # output: (Hash)
264
+ # The Hash with the select_hash_key selected and the values generated from the string patterns and select fields specified.
265
+ # examples:
266
+ # new_hash = NiceHash.generate(my_hash)
267
+ # #> {:name=>"Peter",
268
+ # :address=>{:wrong=>"\#$$$$$", :correct=>"KZPCzxsWGMLqonesu wbqH"},
269
+ # :city=>{:wrong=>"Germany", :correct=>"Barcelona"},
270
+ # :products=> [
271
+ # {:name=>"gIqkWygmVm", :price=>{:wrong=>"-20", :correct=>"34338330"}},
272
+ # {:name=>"CK68VLIcYf", :price=>{:wrong=>"-20", :correct=>"616066520"}}
273
+ # ]
274
+ # }
275
+ # new_hash = NiceHash.generate(my_hash, :correct)
276
+ # #> {:name=>"Peter",
277
+ # :address=>"juQeAVZjIuWBPsE",
278
+ # :city=>"Madrid",
279
+ # :products=> [
280
+ # {:name=>"G44Ilr0puV", :price=>"477813"},
281
+ # {:name=>"v6ojs79LOp", :price=>"74820"}
282
+ # ]
283
+ # }
284
+ # new_hash = NiceHash.generate(my_hash, :correct, expected_errors: [:min_length])
285
+ # #> {:name=>"Peter",
286
+ # :address=>"ZytjefJ",
287
+ # :city=>"Madri",
288
+ # :products=>[
289
+ # {:name=>"cIBrzeO", :price=>""},
290
+ # {:name=>"5", :price=>""}
291
+ # ]
292
+ # }
293
+ # Using it directly on Hash class, generate(select_hash_key=nil, expected_errors: []) (alias: gen):
294
+ # new_hash = my_hash.generate
295
+ # new_hash = my_hash.gen(:correct)
296
+ # new_hash = my_hash.generate(:correct, errors: [:min_length])
297
+ ###########################################################################
298
+ def NiceHash.generate(pattern_hash, select_hash_key=nil, expected_errors: [], **synonyms)
299
+ hash=Hash.new()
300
+ same_values=Hash.new()
301
+ expected_errors=synonyms[:errors] if synonyms.keys.include?(:errors)
302
+ if expected_errors.kind_of?(Symbol)
303
+ expected_errors=[expected_errors]
304
+ end
305
+
306
+ if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
307
+ pattern_hash.each {|key, value|
308
+
309
+ if key.kind_of?(Array)
310
+ same_values[key[0]]=key.dup
311
+ same_values[key[0]].shift
312
+ key=key[0]
313
+ end
314
+ if value.kind_of?(Hash)
315
+ if value.keys.include?(select_hash_key)
316
+ value=value[select_hash_key]
317
+ else
318
+ value=NiceHash.generate(value, select_hash_key, expected_errors: expected_errors)
319
+ end
320
+ end
321
+
322
+ if value.kind_of?(String) or value.kind_of?(Symbol)
323
+ if ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
324
+ hash[key]=StringPattern.generate(value, expected_errors: expected_errors)
325
+ elsif ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
326
+ if expected_errors.include?(:min_length) or (expected_errors.include?(:length) and rand.round==0)
327
+ min=value.to_s.split("|").min {|a, b| a.size <=> b.size}
328
+ hash[key]=min[0..-2] unless min==""
329
+ end
330
+ if !hash.keys.include?(key) and (expected_errors.include?(:max_length) or expected_errors.include?(:length))
331
+ max=value.to_s.split("|").max {|a, b| a.size <=> b.size}
332
+ hash[key]=max+max[-1]
333
+ end
334
+ if expected_errors.include?(:value) or
335
+ expected_errors.include?(:string_set_not_allowed) or
336
+ expected_errors.include?(:required_data)
337
+ if hash.keys.include?(key)
338
+ v=hash[key]
339
+ else
340
+ v=value.to_s.split("|").sample
341
+ end
342
+ unless expected_errors.include?(:string_set_not_allowed)
343
+ v=StringPattern.generate(:"#{v.size}:[#{value.to_s.split("|").join.split(//).uniq.join}]")
344
+ hash[key]=v unless value.to_s.split("|").include?(v)
345
+ end
346
+ unless hash.keys.include?(key)
347
+ one_wrong_letter=StringPattern.generate(:"1:LN$[%#{value.to_s.split("|").join.split(//).uniq.join}%]")
348
+ v[rand(v.size)]=one_wrong_letter
349
+ hash[key]=v unless value.to_s.split("|").include?(v)
350
+ end
351
+ end
352
+ unless hash.keys.include?(key)
353
+ hash[key]=value.to_s.split("|").sample
354
+ end
355
+ else
356
+ hash[key]=value
357
+ end
358
+ elsif value.kind_of?(Array)
359
+ array_pattern=false
360
+ value.each {|v|
361
+ if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
362
+ hash[key]=StringPattern.generate(value, expected_errors: expected_errors)
363
+ array_pattern=true
364
+ break
365
+ end
366
+ }
367
+ unless array_pattern
368
+ value_ret=Array.new
369
+ value.each {|v|
370
+ ret=NiceHash.generate(v, select_hash_key, expected_errors: expected_errors)
371
+ ret=v if ret.kind_of?(Hash) and ret.size==0
372
+ value_ret<<ret
373
+ }
374
+ hash[key]=value_ret
375
+ end
376
+ else
377
+ hash[key]=value
378
+ end
379
+
380
+ if same_values.include?(key)
381
+ same_values[key].each {|k|
382
+ hash[k]=hash[key]
383
+ }
384
+ end
385
+
386
+ }
387
+ end
388
+
389
+ return hash
390
+ end
391
+
392
+
393
+ ###########################################################################
394
+ # Validates a given values_hash_to_validate with string patterns and select fields from pattern_hash
395
+ # input:
396
+ # patterns_hash:
397
+ # (Hash) Hash where we have defined the patterns to follow.
398
+ # (Array) In case of array supplied, the pair: [pattern_hash, select_hash_key]. select_hash_key will filter the hash by that key
399
+ # values_hash_to_validate: (Hash) Hash of values to validate
400
+ # only_patterns: (TrueFalse) (by default true) If true it will validate only the patterns and not the other fields
401
+ # output: (Hash)
402
+ # A hash with the validation results. It will return only the validation errors so in case no validation errors found, empty hash.
403
+ # The keys of the hash will be the keys of the values hash with the validation error.
404
+ # The value in case of a pattern, will be an array with one or more of these possibilities:
405
+ # :length: wrong length, minimum or maximum
406
+ # :min_length: wrong minimum length
407
+ # :max_length: wrong maximum length
408
+ # :value: wrong resultant value
409
+ # :required_data: the output string won't include all necessary required data. It works only if required data supplied on the pattern.
410
+ # :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.
411
+ # :string_set_not_allowed: it will include one or more characters that are not supposed to be on the string.
412
+ # The value in any other case it will be false if the value is not corresponding to the expected.
413
+ # examples:
414
+ # values_to_validate = {:name=>"Peter",
415
+ # :address=>"fnMuKW",
416
+ # :city=>"Dublin",
417
+ # :products=>[{:name=>"V4", :price=>"344"}, {:name=>"E", :price=>"a"}]
418
+ # }
419
+ # results = NiceHash.validate([my_hash, :correct], values_to_validate)
420
+ # #> {:address=>[:min_length, :length],
421
+ # :products=> [{:name=>[:min_length, :length]},
422
+ # {:name=>[:min_length, :length], :price=>[:value, :string_set_not_allowed]}
423
+ # ]
424
+ # }
425
+ # results = NiceHash.validate([my_hash, :correct], values_to_validate, only_patterns: false)
426
+ # #> {:address=>[:min_length, :length],
427
+ # :city=>false,
428
+ # :products=> [{:name=>[:min_length, :length]},
429
+ # {:name=>[:min_length, :length], :price=>[:value, :string_set_not_allowed]}
430
+ # ]
431
+ # }
432
+ # Using it directly on Hash class:
433
+ # validate(select_hash_key=nil, values_hash_to_validate) (alias: val)
434
+ # validate_patterns(select_hash_key=nil, values_hash_to_validate)
435
+ #
436
+ # results = my_hash.validate_patterns(:correct, values_to_validate)
437
+ # results = my_hash.validate(:correct, values_to_validate)
438
+ ###########################################################################
439
+ def NiceHash.validate(patterns_hash, values_hash_to_validate, only_patterns: true)
440
+ if patterns_hash.kind_of?(Array)
441
+ pattern_hash=patterns_hash[0]
442
+ select_hash_key=patterns_hash[1]
443
+ elsif patterns_hash.kind_of?(Hash)
444
+ pattern_hash=patterns_hash
445
+ select_hash_key=nil
446
+ else
447
+ puts "NiceHash.validate wrong pattern_hash supplied #{patterns_hash.inspect}"
448
+ return {error: :error}
449
+ end
450
+ values = values_hash_to_validate
451
+ results={}
452
+ same_values={}
453
+ if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
454
+ pattern_hash.each {|key, value|
455
+
456
+ if key.kind_of?(Array)
457
+ same_values[key[0]]=key.dup
458
+ same_values[key[0]].shift
459
+ key=key[0]
460
+ end
461
+ if value.kind_of?(Hash)
462
+ if !select_hash_key.nil? and value.keys.include?(select_hash_key)
463
+ value=value[select_hash_key]
464
+ elsif values.keys.include?(key) and values[key].kind_of?(Hash)
465
+ res=NiceHash.validate([value, select_hash_key], values[key], only_patterns: only_patterns)
466
+ results[key]=res if res.size>0
467
+ next
468
+ end
469
+ end
470
+
471
+ if values.keys.include?(key)
472
+ if value.kind_of?(String) or value.kind_of?(Symbol)
473
+ if ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
474
+ res=StringPattern.validate(pattern: value, text: values[key])
475
+ results[key]=res if res.size>0
476
+ elsif !only_patterns and ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
477
+ results[key]=false unless value.to_s.split("|").include?(values[key])
478
+ elsif !only_patterns
479
+ results[key]=false unless value.to_s==values[key].to_s
480
+ end
481
+ elsif value.kind_of?(Array)
482
+ array_pattern=false
483
+ complex_data=false
484
+ value.each {|v|
485
+ if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
486
+ res=StringPattern.validate(pattern: value, text: values[key])
487
+ results[key]=res if res==false
488
+ array_pattern=true
489
+ break
490
+ elsif v.kind_of?(Hash) or v.kind_of?(Array) or v.kind_of?(Struct)
491
+ complex_data=true
492
+ break
493
+ end
494
+ }
495
+ unless array_pattern or results.include?(key)
496
+ i=0
497
+ value.each {|v|
498
+ res=NiceHash.validate([v, select_hash_key], values[key][i], only_patterns: only_patterns)
499
+ if res.size>0
500
+ results[key]=Array.new() if !results.keys.include?(key)
501
+ results[key][i]=res
502
+ end
503
+ i+=1
504
+ }
505
+
506
+ end
507
+ unless array_pattern or only_patterns or results.include?(key) or complex_data
508
+ results[key]=false unless value==values[key]
509
+ end
510
+
511
+ else
512
+ unless only_patterns
513
+ results[key]=false unless value==values[key]
514
+ end
515
+ end
516
+
517
+ if same_values.include?(key)
518
+ same_values[key].each {|k|
519
+ if values.keys.include?(k)
520
+ if values[key]!=values[k]
521
+ results[k]="Not equal to #{key}"
522
+ end
523
+ end
524
+ }
525
+ end
526
+
527
+ end
528
+ }
529
+
530
+ end
531
+
532
+ return results
533
+ end
534
+
535
+ ###########################################################################
536
+ # Change only one value at a time and return an Array of Hashes
537
+ # 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.
538
+ # 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
539
+ # input:
540
+ # patterns_hash:
541
+ # (Hash) Hash where we have defined the patterns to follow.
542
+ # (Array) In case of array supplied, the pair: [pattern_hash, select_hash_key]. select_hash_key will filter the hash by that key
543
+ # values_hash: (Hash) Hash of values to use to modify the values generated on patterns_hash
544
+ # output: (Array of Hashes)
545
+ # example:
546
+ # wrong_min_length_hash = my_hash.generate(:correct, errors: :min_length)
547
+ # array_of_hashes = NiceHash.change_one_by_one([my_hash, :correct], wrong_min_length_hash)
548
+ # array_of_hashes.each {|hash_with_one_wrong_field|
549
+ # #Here your code to send through http the JSON data stored in hash_with_one_wrong_field
550
+ # #if you want to know which field is the one that is wrong:
551
+ # res = my_hash.validate(:correct, hash_with_one_wrong_field)
552
+ # }
553
+ ###########################################################################
554
+ def NiceHash.change_one_by_one(patterns_hash, values_hash)
555
+ if patterns_hash.kind_of?(Array)
556
+ select_key=patterns_hash[1]
557
+ pattern_hash=patterns_hash[0]
558
+ else
559
+ pattern_hash=patterns_hash
560
+ select_key=[]
561
+ end
562
+ array=Array.new
563
+ good_values=NiceHash.generate(pattern_hash, select_key)
564
+ select_keys=pattern_hash.pattern_fields(select_key)+pattern_hash.select_fields(select_key)
565
+ select_keys.each {|field|
566
+ new_hash=Marshal.load(Marshal.dump(good_values))
567
+ # to deal with the case same values... like in pwd1, pwd2, pwd3
568
+ if field[-1].kind_of?(Array)
569
+ last_to_set=field[-1]
570
+ else
571
+ last_to_set=[field[-1]]
572
+ end
573
+ last_to_set.each {|f|
574
+ keys=field[0..-2]<<f
575
+ new_hash.bury(keys, values_hash.dig(*keys))
576
+ }
577
+ array<<new_hash
578
+ }
579
+ return array
580
+ end
581
+
582
+
583
+ ##################################################
584
+ # Get values from the Hash structure (array of Hashes allowed)
585
+ # In case the key supplied doesn't exist in the hash then it will be return nil for that one
586
+ # input:
587
+ # hash: a simple hash or a hash containing arrays. Example:
588
+ # example={"id"=>344,
589
+ # "customer"=>{
590
+ # "name"=>"Peter Smith",
591
+ # "phone"=>334334333
592
+ # },
593
+ # "tickets"=>[
594
+ # {"idt"=>345,"name"=>"myFavor1"},
595
+ # {"idt"=>3123},
596
+ # {"idt"=>3145,"name"=>"Special ticket"}
597
+ # ]
598
+ # }
599
+ # keys: one key (string) or an array of keys
600
+ # output:
601
+ # a Hash of Arrays with all values found.
602
+ # Example of output with example.get_values("id","name")
603
+ # {"id"=>[334],"name"=>["Peter North"]}
604
+ # Example of output with example.get_values("idt")
605
+ # {"idt"=>[345,3123,3145]}
606
+ #
607
+ ####################################################
608
+ def NiceHash.get_values(hash,keys)
609
+ if keys.kind_of?(String) or keys.kind_of?(Symbol) then
610
+ keys=[keys]
611
+ end
612
+ result=Hash.new()
613
+ number_of_results=Hash.new()
614
+ keys.each {|key|
615
+ number_of_results[key]=0
616
+ }
617
+ if hash.kind_of?(Array) then
618
+ hash.each {|tmp|
619
+ if tmp.kind_of?(Array) or tmp.kind_of?(Hash) then
620
+ n_result=get_values(tmp, keys)
621
+ if n_result!=:error then
622
+ n_result.each {|n_key, n_value|
623
+ if result.has_key?(n_key) then
624
+ if !result[n_key].kind_of?(Array) or
625
+ (result[n_key].kind_of?(Array) and number_of_results[n_key] < result[n_key].size) then
626
+ if result[n_key].kind_of?(Hash) or result[n_key].kind_of?(Array) then
627
+ res_tx=result[n_key].dup()
628
+ else
629
+ res_tx=result[n_key]
630
+ end
631
+ result[n_key]=Array.new()
632
+ result[n_key].push(res_tx)
633
+ result[n_key].push(n_value)
634
+ else
635
+ result[n_key].push(n_value)
636
+ end
637
+ else
638
+ result[n_key]=n_value
639
+ end
640
+ number_of_results[n_key]+=1
641
+ }
642
+ end
643
+ end
644
+ }
645
+ elsif hash.kind_of?(Hash) then
646
+ hash.each {|key, value|
647
+ #if keys.include?(key) then
648
+ #added to be able to access the keys with symbols to strings and opposite
649
+ if keys.include?(key) or keys.include?(key.to_s) or keys.include?(key.to_sym) then
650
+ #added to be able to access the keys with symbols to strings and opposite
651
+ key=key.to_s() if keys.include?(key.to_s)
652
+ key=key.to_sym() if keys.include?(key.to_sym)
653
+
654
+ if result.has_key?(key) then
655
+ if !result[key].kind_of?(Array) or
656
+ (result[key].kind_of?(Array) and number_of_results[key] < result[key].size) then
657
+ if result[key].kind_of?(Hash) or result[key].kind_of?(Array) then
658
+ res_tx=result[key].dup()
659
+ else
660
+ res_tx=result[key]
661
+ end
662
+ result[key]=Array.new()
663
+ result[key].push(res_tx)
664
+ result[key].push(value)
665
+ else
666
+ result[key].push(value)
667
+ end
668
+ else
669
+ result[key]=value
670
+ end
671
+ number_of_results[key]+=1
672
+ end
673
+ if value.kind_of?(Array) or value.kind_of?(Hash) then
674
+ n_result=get_values(value, keys)
675
+ if n_result!=:error then
676
+ n_result.each {|n_key, n_value|
677
+ if result.has_key?(n_key) then
678
+ if !result[n_key].kind_of?(Array) or
679
+ (result[n_key].kind_of?(Array) and number_of_results[n_key] < result[n_key].size) then
680
+ if result[n_key].kind_of?(Hash) or result[n_key].kind_of?(Array) then
681
+ res_tx=result[n_key].dup()
682
+ else
683
+ res_tx=result[n_key]
684
+ end
685
+ result[n_key]=Array.new()
686
+ result[n_key].push(res_tx)
687
+ result[n_key].push(n_value)
688
+ else
689
+ result[n_key].push(n_value)
690
+ end
691
+ else
692
+ result[n_key]=n_value
693
+ end
694
+ number_of_results[n_key]+=1
695
+ }
696
+ end
697
+ end
698
+ }
699
+ else
700
+ return :error
701
+ end
702
+ if result.kind_of?(Hash) and caller[0]["get_values"].nil? then #no error or anything weird
703
+ (keys-result.keys).each {|k| #in case some keys don't exist in the hash
704
+ result[k]=nil
705
+ }
706
+ end
707
+ return result
708
+ end
709
+
710
+ end