Class: NiceHash

Inherits:
Object
  • Object
show all
Defined in:
lib/nice_hash.rb

Overview

NiceHash creates hashes following certain patterns so your testing will be much easier. You can easily generates all the hashes you want following the criteria you specify. 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. You will be able to generate thousands of different hashes just declaring one and test easily APIs based on JSON for example. To generate the strings following a pattern take a look at the documentation for string_pattern gem: https://github.com/MarioRuiz/string_pattern This is the Hash we will be using on the examples declared on the methods source code documentation: my_hash={ name: 'Peter', address: '#$$$$$', correct: :'10-30:L_', city: 'Germany', correct: :'Madrid|Barcelona|London|Akureyri', products: [ { name: :'10:Ln', price: '-20', correct: :'1-10:N' }, { name: :'10:Ln', price: '-20', correct: :'1-10:N' }, ] }

Class Method Summary collapse

Class Method Details

.change_one_by_one(patterns_hash, values_hash) ⇒ Object

Change only one value at a time and return an Array of Hashes 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. 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 input: patterns_hash: (Hash) Hash where we have defined the patterns to follow. (Array) In case of array supplied, the pair: [pattern_hash, select_hash_key]. select_hash_key will filter the hash by that key values_hash: (Hash) Hash of values to use to modify the values generated on patterns_hash output: (Array of Hashes) example: wrong_min_length_hash = my_hash.generate(:correct, errors: :min_length) array_of_hashes = NiceHash.change_one_by_one([my_hash, :correct], wrong_min_length_hash) array_of_hashes.each {|hash_with_one_wrong_field| #Here your code to send through http the JSON data stored in hash_with_one_wrong_field #if you want to know which field is the one that is wrong: res = my_hash.validate(:correct, hash_with_one_wrong_field) }


556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
# File 'lib/nice_hash.rb', line 556

def NiceHash.change_one_by_one(patterns_hash, values_hash)
  if patterns_hash.kind_of?(Array)
    select_key=patterns_hash[1]
    pattern_hash=patterns_hash[0]
  else
    pattern_hash=patterns_hash
    select_key=[]
  end
  array=Array.new
  good_values=NiceHash.generate(pattern_hash, select_key)
  select_keys=pattern_hash.pattern_fields(select_key)+pattern_hash.select_fields(select_key)
  select_keys.each {|field|
    new_hash=Marshal.load(Marshal.dump(good_values))    # to deal with the case same values... like in pwd1, pwd2, pwd3

    if field[-1].kind_of?(Array)
      last_to_set=field[-1]
    else
      last_to_set=[field[-1]]
    end
    last_to_set.each {|f|
      keys=field[0..-2]<<f
      new_hash.bury(keys, values_hash.dig(*keys))
    }
    array<<new_hash
  }
  return array
end

.generate(pattern_hash, select_hash_key = nil, expected_errors: [], **synonyms) ⇒ Object

It will generate a new hash with the values generated from the string patterns and select fields specified. 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 If expected_errors specified the values will be generated with the specified errors. input: pattern_hash: (Hash) Hash we want to use to generate the values select_hash_key: (key value) (optional) The key we want to select on the subhashes expected_errors: (Array) (optional) (alias: errors) To generate the string patterns with the specified errors. The possible values you can specify is one or more of these ones: :length: wrong length, minimum or maximum :min_length: wrong minimum length :max_length: wrong maximum length :value: wrong resultant value :required_data: the output string won't include all necessary required data. It works only if required data supplied on the pattern. :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. :string_set_not_allowed: it will include one or more characters that are not supposed to be on the string. output: (Hash) The Hash with the select_hash_key selected and the values generated from the string patterns and select fields specified. examples: new_hash = NiceHash.generate(my_hash) #> :address=>{:wrong=>"#$$$$$", :correct=>"KZPCzxsWGMLqonesu wbqH", :city=>:correct=>"Barcelona", :products=> [ :price=>{:wrong=>"-20", :correct=>"34338330"}, :price=>{:wrong=>"-20", :correct=>"616066520"} ] } new_hash = NiceHash.generate(my_hash, :correct) #> :address=>"juQeAVZjIuWBPsE", :city=>"Madrid", :products=> [ {:name=>"G44Ilr0puV", :price=>"477813", :price=>"74820" ] } new_hash = NiceHash.generate(my_hash, :correct, expected_errors: [:min_length]) #> :address=>"ZytjefJ", :city=>"Madri", :products=>[ {:name=>"cIBrzeO", :price=>"", :price=>"" ] } Using it directly on Hash class, generate(select_hash_key=nil, expected_errors: []) (alias: gen): new_hash = my_hash.generate new_hash = my_hash.gen(:correct) new_hash = my_hash.generate(:correct, errors: [:min_length])


298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/nice_hash.rb', line 298

def NiceHash.generate(pattern_hash, select_hash_key=nil, expected_errors: [], **synonyms)
  hash=Hash.new()
  same_values=Hash.new()
  expected_errors=synonyms[:errors] if synonyms.keys.include?(:errors)
  if expected_errors.kind_of?(Symbol)
    expected_errors=[expected_errors]
  end

  if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
    pattern_hash.each {|key, value|

      if key.kind_of?(Array)
        same_values[key[0]]=key.dup
        same_values[key[0]].shift
        key=key[0]
      end
      if value.kind_of?(Hash)
        if value.keys.include?(select_hash_key)
          value=value[select_hash_key]
        else
          value=NiceHash.generate(value, select_hash_key, expected_errors: expected_errors)
        end
      end

      if value.kind_of?(String) or value.kind_of?(Symbol)
        if ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
          hash[key]=StringPattern.generate(value, expected_errors: expected_errors)
        elsif ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
          if expected_errors.include?(:min_length) or (expected_errors.include?(:length) and rand.round==0)
            min=value.to_s.split("|").min {|a, b| a.size <=> b.size}
            hash[key]=min[0..-2] unless min==""
          end
          if !hash.keys.include?(key) and (expected_errors.include?(:max_length) or expected_errors.include?(:length))
            max=value.to_s.split("|").max {|a, b| a.size <=> b.size}
            hash[key]=max+max[-1]
          end
          if expected_errors.include?(:value) or
              expected_errors.include?(:string_set_not_allowed) or
              expected_errors.include?(:required_data)
            if hash.keys.include?(key)
              v=hash[key]
            else
              v=value.to_s.split("|").sample
            end
            unless expected_errors.include?(:string_set_not_allowed)
              v=StringPattern.generate(:"#{v.size}:[#{value.to_s.split("|").join.split(//).uniq.join}]")
              hash[key]=v unless value.to_s.split("|").include?(v)
            end
            unless hash.keys.include?(key)
              one_wrong_letter=StringPattern.generate(:"1:LN$[%#{value.to_s.split("|").join.split(//).uniq.join}%]")
              v[rand(v.size)]=one_wrong_letter
              hash[key]=v unless value.to_s.split("|").include?(v)
            end
          end
          unless hash.keys.include?(key)
            hash[key]=value.to_s.split("|").sample
          end
        else
          hash[key]=value
        end
      elsif value.kind_of?(Array)
        array_pattern=false
        value.each {|v|
          if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
            hash[key]=StringPattern.generate(value, expected_errors: expected_errors)
            array_pattern=true
            break
          end
        }
        unless array_pattern
          value_ret=Array.new
          value.each {|v|
            ret=NiceHash.generate(v, select_hash_key, expected_errors: expected_errors)
            ret=v if ret.kind_of?(Hash) and ret.size==0
            value_ret<<ret
          }
          hash[key]=value_ret
        end
      elsif value.kind_of?(Proc)
        hash[key]=value.call
      else
        hash[key]=value
      end

      if same_values.include?(key)
        same_values[key].each {|k|
          hash[k]=hash[key]
        }
      end

    }
  end

  return hash
end

.get_values(hash, keys) ⇒ Object

Get values from the Hash structure (array of Hashes allowed) In case the key supplied doesn't exist in the hash then it will be return nil for that one input: hash: a simple hash or a hash containing arrays. Example: example={"id"=>344, "customer"=>{ "name"=>"Peter Smith", "phone"=>334334333 }, "tickets"=>[ "idt"=>345,"name"=>"myFavor1", "idt"=>3123, ticket" ] } keys: one key (string) or an array of keys output: a Hash of Arrays with all values found. Example of output with example.get_values("id","name") North"] Example of output with example.get_values("idt") "idt"=>[345,3123,3145]


610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
# File 'lib/nice_hash.rb', line 610

def NiceHash.get_values(hash,keys)
  if keys.kind_of?(String) or keys.kind_of?(Symbol) then
    keys=[keys]
  end
  result=Hash.new()
  number_of_results=Hash.new()
  keys.each {|key|
    number_of_results[key]=0
  }
  if hash.kind_of?(Array) then
    hash.each {|tmp|
      if tmp.kind_of?(Array) or tmp.kind_of?(Hash) then
        n_result=get_values(tmp, keys)
        if n_result!=:error then
          n_result.each {|n_key, n_value|
            if result.has_key?(n_key) then
              if !result[n_key].kind_of?(Array) or
                  (result[n_key].kind_of?(Array) and number_of_results[n_key] < result[n_key].size) then
                if result[n_key].kind_of?(Hash) or result[n_key].kind_of?(Array) then
                  res_tx=result[n_key].dup()
                else
                  res_tx=result[n_key]
                end
                result[n_key]=Array.new()
                result[n_key].push(res_tx)
                result[n_key].push(n_value)
              else
                result[n_key].push(n_value)
              end
            else
              result[n_key]=n_value
            end
            number_of_results[n_key]+=1
          }
        end
      end
    }
  elsif hash.kind_of?(Hash) then
    hash.each {|key, value|
      #if keys.include?(key) then
      #added to be able to access the keys with symbols to strings and opposite
      if keys.include?(key) or keys.include?(key.to_s) or keys.include?(key.to_sym) then
        #added to be able to access the keys with symbols to strings and opposite
        key=key.to_s() if keys.include?(key.to_s)
        key=key.to_sym() if keys.include?(key.to_sym)

        if result.has_key?(key) then
          if !result[key].kind_of?(Array) or
              (result[key].kind_of?(Array) and number_of_results[key] < result[key].size) then
            if result[key].kind_of?(Hash) or result[key].kind_of?(Array) then
              res_tx=result[key].dup()
            else
              res_tx=result[key]
            end
            result[key]=Array.new()
            result[key].push(res_tx)
            result[key].push(value)
          else
            result[key].push(value)
          end
        else
          result[key]=value
        end
        number_of_results[key]+=1
      end
      if value.kind_of?(Array) or value.kind_of?(Hash) then
        n_result=get_values(value, keys)
        if n_result!=:error then
          n_result.each {|n_key, n_value|
            if result.has_key?(n_key) then
              if !result[n_key].kind_of?(Array) or
                  (result[n_key].kind_of?(Array) and number_of_results[n_key] < result[n_key].size) then
                if result[n_key].kind_of?(Hash) or result[n_key].kind_of?(Array) then
                  res_tx=result[n_key].dup()
                else
                  res_tx=result[n_key]
                end
                result[n_key]=Array.new()
                result[n_key].push(res_tx)
                result[n_key].push(n_value)
              else
                result[n_key].push(n_value)
              end
            else
              result[n_key]=n_value
            end
            number_of_results[n_key]+=1
          }
        end
      end
    }
  else
    return :error
  end
  if result.kind_of?(Hash) and caller[0]["get_values"].nil? then #no error or anything weird
    (keys-result.keys).each {|k| #in case some keys don't exist in the hash
      result[k]=nil
    }
  end
  return result
end

.pattern_fields(pattern_hash, *select_hash_key) ⇒ Object

It will return an array of the keys where we are using string patterns.

input: pattern_hash: (Hash) Hash we want to get the pattern_fields select_hash_key: (key value) (optional) The key we want to select on the subhashes output: (Array) Array of the kind: [ [key], [key, subkey, subkey] ] Each value of the array can be used as parameter for the methods: dig, bury examples: NiceHash.pattern_fields(my_hash) #> [ [:address, :correct], [:products, 0, :name], [:products, 0, :price, :correct], [:products, 1, :name], [:products, 1, :price, :correct] ] NiceHash.pattern_fields(my_hash, :correct) #> [ [:address], [:products, 0, :name], [:products, 0, :price], [:products, 1, :name], [:products, 1, :price] ] Using it directly on Hash class, pattern_fields(*select_hash_key) (alias: patterns): my_hash.pattern_fields my_hash.pattern_fields(:correct) my_hash.patterns(:correct)


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/nice_hash.rb', line 117

def NiceHash.pattern_fields(pattern_hash, *select_hash_key)
  pattern_fields = Array.new

  if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
    pattern_hash.each {|key, value|
      key=[key]
      if value.kind_of?(Hash)
        if select_hash_key.size==1 and value.keys.include?(select_hash_key[0])
          value=value[select_hash_key[0]]
        else
          res=NiceHash.pattern_fields(value, *select_hash_key)
          if res.size>0
            res.each {|r|
              pattern_fields<<(r.unshift(key)).flatten
            }
          end
          next
        end
      end
      if value.kind_of?(String)
        if StringPattern.optimistic and value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
          pattern_fields << key
        end
      elsif value.kind_of?(Symbol)
        if value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
          pattern_fields << key
        end
      elsif value.kind_of?(Array)

        array_pattern=false
        value.each {|v|
          if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
            pattern_fields << key
            array_pattern=true
            break
          end
        }
        unless array_pattern
          i=0
          value.each {|v|
            res=NiceHash.pattern_fields(v, *select_hash_key)
            if res.size>0
              res.each {|r|
                pattern_fields<<(r.unshift(i).unshift(key)).flatten
              }
            end
            i+=1
          }
        end
      end
    }
  end

  return pattern_fields
end

.select_fields(pattern_hash, *select_hash_key) ⇒ Object

It will return an array of the keys where we are using select values of the kind: "value1|value2|value3".

input: pattern_hash: (Hash) Hash we want to get the select_fields select_hash_key: (key value) (optional) The key we want to select on the subhashes output: (Array) Array of the kind: [ [key], [key, subkey, subkey] ] Each value of the array can be used as parameter for the methods: dig, bury examples: NiceHash.select_fields(my_hash) #> [[:city, :correct]] NiceHash.select_fields(my_hash, :correct) #> [[:city]] Using it directly on Hash class, select_fields(*select_hash_key): my_hash.select_fields my_hash.select_fields(:correct)


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/nice_hash.rb', line 191

def NiceHash.select_fields(pattern_hash, *select_hash_key)
  select_fields = Array.new

  if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
    pattern_hash.each {|key, value|
      key=[key]
      if value.kind_of?(Hash)
        if select_hash_key.size==1 and value.keys.include?(select_hash_key[0])
          value=value[select_hash_key[0]]
        else
          res=NiceHash.select_fields(value, *select_hash_key)
          if res.size>0
            res.each {|r|
              select_fields<<(r.unshift(key)).flatten
            }
          end
          next
        end
      end
      if value.kind_of?(String)
        if StringPattern.optimistic and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
          select_fields << key
        end
      elsif value.kind_of?(Symbol)
        if value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size>0
          select_fields << key
        end
      elsif value.kind_of?(Array)

        array_pattern=false
        value.each {|v|
          if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
            array_pattern=true
            break
          end
        }
        unless array_pattern
          i=0
          value.each {|v|
            res=NiceHash.select_fields(v, *select_hash_key)
            if res.size>0
              res.each {|r|
                select_fields<<(r.unshift(i).unshift(key)).flatten
              }
            end
            i+=1
          }
        end
      end
    }
  end

  return select_fields
end

.select_key(pattern_hash, select_hash_key) ⇒ Object

It will filter the hash by the key specified on select_hash_key. In case a subhash specified on a value it will be selected only the value of the key specified on select_hash_key

input: pattern_hash: (Hash) Hash we want to select specific keys select_hash_key: (key value) The key we want to select on the subhashes output: (Hash) 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 example: new_hash = NiceHash.select_key(my_hash, :wrong) #> :address=>"#$$$$$", :city=>"Germany", :products=> [{:name=>:"10:Ln", :price=>"-20", :price=>"-20"]} Using it directly on Hash class, select_key(select_hash_key): new_hash = my_hash.select_key(:wrong)


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/nice_hash.rb', line 46

def NiceHash.select_key(pattern_hash, select_hash_key)
  hash=Hash.new()

  if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
    pattern_hash.each {|key, value|

      if value.kind_of?(Hash)
        if value.keys.include?(select_hash_key)
          value=value[select_hash_key]
        else
          value=NiceHash.select_key(value, select_hash_key)
        end
      end
      if value.kind_of?(Array)
        array_pattern=false
        value.each {|v|
          if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
            hash[key]=value
            array_pattern=true
            break
          end
        }
        unless array_pattern
          value_ret=Array.new
          value.each {|v|
            ret=NiceHash.select_key(v, select_hash_key)
            value_ret<<ret
          }
          hash[key]=value_ret
        end
      else
        hash[key]=value
      end
    }
  else
    return pattern_hash
  end
  return hash
end

.validate(patterns_hash, values_hash_to_validate, only_patterns: true) ⇒ Object

Validates a given values_hash_to_validate with string patterns and select fields from pattern_hash input: patterns_hash: (Hash) Hash where we have defined the patterns to follow. (Array) In case of array supplied, the pair: [pattern_hash, select_hash_key]. select_hash_key will filter the hash by that key values_hash_to_validate: (Hash) Hash of values to validate only_patterns: (TrueFalse) (by default true) If true it will validate only the patterns and not the other fields output: (Hash) A hash with the validation results. It will return only the validation errors so in case no validation errors found, empty hash. The keys of the hash will be the keys of the values hash with the validation error. The value in case of a pattern, will be an array with one or more of these possibilities: :length: wrong length, minimum or maximum :min_length: wrong minimum length :max_length: wrong maximum length :value: wrong resultant value :required_data: the output string won't include all necessary required data. It works only if required data supplied on the pattern. :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. :string_set_not_allowed: it will include one or more characters that are not supposed to be on the string. The value in any other case it will be false if the value is not corresponding to the expected. examples: values_to_validate = :address=>"fnMuKW", :city=>"Dublin", :products=>[{:name=>"V4", :price=>"344", :price=>"a"] } results = NiceHash.validate([my_hash, :correct], values_to_validate) #> :length], :products=> [{:name=>[:min_length, :length], :length], :price=>[:value, :string_set_not_allowed] ] } results = NiceHash.validate([my_hash, :correct], values_to_validate, only_patterns: false) #> :length], :city=>false, :products=> [{:name=>[:min_length, :length], :length], :price=>[:value, :string_set_not_allowed] ] } Using it directly on Hash class: validate(select_hash_key=nil, values_hash_to_validate) (alias: val) validate_patterns(select_hash_key=nil, values_hash_to_validate)

results = my_hash.validate_patterns(:correct, values_to_validate) results = my_hash.validate(:correct, values_to_validate)


441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/nice_hash.rb', line 441

def NiceHash.validate(patterns_hash, values_hash_to_validate, only_patterns: true)
  if patterns_hash.kind_of?(Array)
    pattern_hash=patterns_hash[0]
    select_hash_key=patterns_hash[1]
  elsif patterns_hash.kind_of?(Hash)
    pattern_hash=patterns_hash
    select_hash_key=nil
  else
    puts "NiceHash.validate wrong pattern_hash supplied #{patterns_hash.inspect}"
    return {error: :error}
  end
  values = values_hash_to_validate
  results={}
  same_values={}
  if pattern_hash.kind_of?(Hash) and pattern_hash.size>0
    pattern_hash.each {|key, value|

      if key.kind_of?(Array)
        same_values[key[0]]=key.dup
        same_values[key[0]].shift
        key=key[0]
      end
      if value.kind_of?(Hash)
        if !select_hash_key.nil? and value.keys.include?(select_hash_key)
          value=value[select_hash_key]
        elsif values.keys.include?(key) and values[key].kind_of?(Hash)
          res=NiceHash.validate([value, select_hash_key], values[key], only_patterns: only_patterns)
          results[key]=res if res.size>0
          next
        end
      end

      if values.keys.include?(key)
        if value.kind_of?(String) or value.kind_of?(Symbol)
          if ((StringPattern.optimistic and value.kind_of?(String)) or value.kind_of?(Symbol)) and value.to_s.scan(/^!?\d+-?\d*:.+/).size>0
            res=StringPattern.validate(pattern: value, text: values[key])
            results[key]=res if res.size>0
          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
            results[key]=false unless value.to_s.split("|").include?(values[key])
          elsif !only_patterns
            results[key]=false unless value.to_s==values[key].to_s
          end
        elsif value.kind_of?(Array)
          array_pattern=false
          complex_data=false
          value.each {|v|
            if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
              res=StringPattern.validate(pattern: value, text: values[key])
              results[key]=res if res==false
              array_pattern=true
              break
            elsif v.kind_of?(Hash) or v.kind_of?(Array) or v.kind_of?(Struct)
              complex_data=true
              break
            end
          }
          unless array_pattern or results.include?(key)
            i=0
            value.each {|v|
              res=NiceHash.validate([v, select_hash_key], values[key][i], only_patterns: only_patterns)
              if res.size>0
                results[key]=Array.new() if !results.keys.include?(key)
                results[key][i]=res
              end
              i+=1
            }

          end
          unless array_pattern or only_patterns or results.include?(key) or complex_data
            results[key]=false unless value==values[key]
          end

        else
          unless only_patterns or value.kind_of?(Proc)
            results[key]=false unless value==values[key]
          end
        end

        if same_values.include?(key)
          same_values[key].each {|k|
            if values.keys.include?(k)
              if values[key]!=values[k]
                results[k]="Not equal to #{key}"
              end
            end
          }
        end

      end
    }

  end

  return results
end