hash_params 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +12 -9
  3. data/README.md +103 -166
  4. data/lib/hash_params/hash_validator.rb +12 -4
  5. data/lib/hash_params.rb +1 -1
  6. data/spec/hash_params_spec.rb +1 -0
  7. metadata +3 -58
  8. data/coverage/assets/0.8.0/application.css +0 -799
  9. data/coverage/assets/0.8.0/application.js +0 -1559
  10. data/coverage/assets/0.8.0/colorbox/border.png +0 -0
  11. data/coverage/assets/0.8.0/colorbox/controls.png +0 -0
  12. data/coverage/assets/0.8.0/colorbox/loading.gif +0 -0
  13. data/coverage/assets/0.8.0/colorbox/loading_background.png +0 -0
  14. data/coverage/assets/0.8.0/favicon_green.png +0 -0
  15. data/coverage/assets/0.8.0/favicon_red.png +0 -0
  16. data/coverage/assets/0.8.0/favicon_yellow.png +0 -0
  17. data/coverage/assets/0.8.0/loading.gif +0 -0
  18. data/coverage/assets/0.8.0/magnify.png +0 -0
  19. data/coverage/assets/0.8.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  20. data/coverage/assets/0.8.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  21. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  22. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  23. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  24. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  25. data/coverage/assets/0.8.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  26. data/coverage/assets/0.8.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  27. data/coverage/assets/0.8.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
  28. data/coverage/assets/0.8.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  29. data/coverage/assets/0.8.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
  30. data/coverage/assets/0.8.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
  31. data/coverage/assets/0.8.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  32. data/coverage/assets/0.9.0/application.css +0 -799
  33. data/coverage/assets/0.9.0/application.js +0 -1707
  34. data/coverage/assets/0.9.0/colorbox/border.png +0 -0
  35. data/coverage/assets/0.9.0/colorbox/controls.png +0 -0
  36. data/coverage/assets/0.9.0/colorbox/loading.gif +0 -0
  37. data/coverage/assets/0.9.0/colorbox/loading_background.png +0 -0
  38. data/coverage/assets/0.9.0/favicon_green.png +0 -0
  39. data/coverage/assets/0.9.0/favicon_red.png +0 -0
  40. data/coverage/assets/0.9.0/favicon_yellow.png +0 -0
  41. data/coverage/assets/0.9.0/loading.gif +0 -0
  42. data/coverage/assets/0.9.0/magnify.png +0 -0
  43. data/coverage/assets/0.9.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  44. data/coverage/assets/0.9.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  45. data/coverage/assets/0.9.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  46. data/coverage/assets/0.9.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  47. data/coverage/assets/0.9.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  48. data/coverage/assets/0.9.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  49. data/coverage/assets/0.9.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  50. data/coverage/assets/0.9.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  51. data/coverage/assets/0.9.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
  52. data/coverage/assets/0.9.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  53. data/coverage/assets/0.9.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
  54. data/coverage/assets/0.9.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
  55. data/coverage/assets/0.9.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  56. data/coverage/index.html +0 -2192
  57. data/tmp/hash_params.rb +0 -181
  58. data/tmp/hash_params_spec.rb +0 -102
  59. data/tmp/module_spec.rb +0 -27
  60. data/tmp/var_spec.rb +0 -9
  61. data/tmp/yaml_params.rb +0 -109
data/tmp/hash_params.rb DELETED
@@ -1,181 +0,0 @@
1
- class HashParams < Hash
2
- VERSION = '0.0.3'
3
-
4
- attr :errors
5
-
6
- def initialize(incoming_hash={}, opts={})
7
- @opts = opts
8
- @incoming_hash = incoming_hash
9
- @errors =[]
10
- # @parent = code.binding.eval 'self'
11
-
12
- #@opts[:injection_target] = self if @opts[:injection_target] == :self
13
-
14
- #binding.pry
15
-
16
- if block_given?
17
- instance_eval(&Proc.new)
18
- else
19
- #no proc was given. This means pass all values
20
- @incoming_hash.each do |k, v|
21
- set_key_value k, v
22
- end
23
- end
24
- end
25
-
26
- def valid?
27
- @errors.empty?
28
- end
29
-
30
- def param(key, h = {})
31
- begin
32
- #What happens if value is FalseClass ? Need something a little better
33
- val = @incoming_hash[key] || @incoming_hash[key.to_sym] || @incoming_hash[key.to_s]
34
- if val.nil? && h[:default]
35
- val = h[:default].respond_to?(:call) ? h[:default].call(self) : h[:default]
36
- end
37
- #don't bother with the rest if required parameter is missing
38
- raise "Parameter #{key} is required and missing" if h[:required] && val.nil?
39
- #do all coercion and transformation first there could be an array of coersions they will be run in order
40
- Array(h[:coerce]).each do |c|
41
- begin
42
- val = HashParams.coerce(val, c, h)
43
- rescue => e
44
- @errors << e.to_s
45
- end
46
- end
47
- binding.pry if key == :integer_coercion
48
- #coersion could return a nil which won't validate, it could return a false which will attempt to validate
49
- begin
50
- if HashParams.validate(val, h)
51
- #The value is valid add it
52
- set_key_value key, val, h[:as]
53
- end
54
- rescue => e
55
- @errors << e.to_s
56
- end
57
-
58
- #after all that see if a block is given and process that
59
- if block_given? && val.is_a?(Hash)
60
- #Proc.new references the implict block
61
- val = HashParams.new(val, {}, &Proc.new)
62
- set_key_value key, val, h[:as]
63
- end
64
- val
65
- rescue => e
66
- @errors << e.to_s
67
- end
68
- if @errors.length > 0 && @opts[:raise_errors]
69
- raise @errors.join("\n")
70
- end
71
- val
72
- end
73
-
74
- def inject_into_target(target, var_name, val)
75
- if target
76
- #for read write methods
77
- target.singleton_class.class_eval do
78
- attr_accessor var_name;
79
- end
80
- target.send("#{var_name}=", val)
81
- end
82
- end
83
-
84
- def self.validate(param, options ={})
85
- return false if param.nil?
86
- is_valid = true
87
- errors =[]
88
- options.each do |key, value|
89
-
90
- error = case key
91
- when :validate
92
- "#{param.to_s} failed validation using proc" if value.respond_to?(:call) && !value.call(param)
93
- when :blank
94
- 'Parameter cannot be blank' if !value && blank?(param)
95
- when :format
96
- 'Parameter must be a string if using the format validation' && next unless param.kind_of?(String)
97
- "Parameter must match format #{value}" unless param =~ value
98
- when :is
99
- "Parameter must be #{value}" unless param === value
100
- when :in, :within, :range
101
- "Parameter must be within #{value}" unless value.respond_to?(:include) ? value.include?(param) : Array(value).include?(param)
102
- when :min
103
- "Parameter cannot be less than #{value}" unless value <= param
104
- when :max
105
- "Parameter cannot be greater than #{value}" unless value >= param
106
- when :min_length
107
- "Parameter cannot have length less than #{value}" unless value <= param.length
108
- when :max_length
109
- "Parameter cannot have length greater than #{value}" unless value >= param.length
110
- else
111
- nil
112
- end
113
- if error
114
- errors << error
115
- is_valid = false
116
- end
117
- end
118
-
119
- #return true or false depending on if it validated
120
- unless errors.empty?
121
- raise errors.join("\n")
122
- end
123
- is_valid
124
- end
125
-
126
-
127
- def self.coerce(val, type, h)
128
-
129
- # exceptions bubble up
130
- #order is important
131
- return val if type.nil? || val.nil?
132
-
133
- #two special types of transforms
134
- #There is no Boolean type so we handle them special
135
- if type == :boolean || type =='boolean'
136
- return val if (val == true || val == false)
137
- return false if /(false|f|no|n|0)$/i === val.to_s.downcase
138
- return true if /(true|t|yes|y|1)$/i === val.to_s.downcase
139
-
140
- # if we can't parse we return a nil
141
- # maybe !!val is a better return?
142
- return nil
143
- end
144
- #they have given us a coercion which is a string or symbol which is not "boolean", we are going to cast this into a proc and run it
145
-
146
- return type.to_proc.call(val) if type.is_a?(Symbol) || type.is_a?(String)
147
- #could be a proc
148
-
149
- return type.call(val) if type.respond_to?(:call)
150
- #nothing but simple types left
151
- return val if val.is_a?(type)
152
- return Integer(val) if type == Integer
153
- return Float(val) if type == Float
154
- return String(val) if type == String
155
- return Date.parse(val) if type == Date
156
- return Time.parse(val) if type == Time
157
- return DateTime.parse(val) if type == DateTime
158
- return Array(val.split(h[:delimiter] || ',')) if type == Array
159
- return Hash[val.gsub(/[{}]/, '').gsub('}', '').split(h[:delimiter] || ',').map { |c| c.split(h[:separator] ||':').map { |i| i.strip } }] if type == Hash
160
-
161
- nil
162
- end
163
-
164
- def present?(object)
165
- !blank?(object)
166
- end
167
-
168
- def blank?(object)
169
- object.nil? || (object.respond_to?(:empty) && object.empty)
170
- end
171
-
172
- def set_key_value(key, value, as = nil)
173
- key = as unless as.nil?
174
- key = key.to_s.to_sym if @opts[:symbolize_keys]
175
- inject_into_target(@opts[:injection_target], key, value) if @opts[:injection_target]
176
- inject_into_target(self, key, value) if @opts[:make_methods]
177
- self[key]=value
178
- end
179
-
180
-
181
- end
@@ -1,102 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
-
4
- describe HashParams do
5
-
6
- let (:r) {
7
- HashParams.new(
8
- {
9
- ignored: "this will be ignored because it's not mentioned",
10
- to_be_renamed: :to_be_renamed,
11
- integer_coercion: "1",
12
- bad_number: '1aaa2',
13
- array_with_delim: '1|2|3',
14
- hash_as_string: "{a => 1,b => 2,c => d}",
15
- proc_validation: "is_this_valid?",
16
- some_number: 122,
17
- some_string: 'this is a test string' ,
18
- is_true: 'true',
19
- is_false: 'f',
20
- recursive: {}
21
- }
22
- ) do
23
- param :doesnt_exist, required: true
24
- param :to_be_renamed, as: :renamed
25
- param :no_value, default: 1
26
- #proc default relying on previously set value
27
- param :proc_default, default: lambda { |o| o[:no_value] * 5 }
28
- param :integer_coercion, coerce: Integer
29
- #chained coersions of various types
30
- param :bad_number, coerce: [lambda { |o| o.gsub('a', '') }, :to_i, Float]
31
- #arrays and hashes
32
- param :array_with_delim, coerce: Array, delimiter: '|'
33
- param :hash_as_string, coerce: Hash, delimiter: ',', separator: '=>'
34
- param :proc_validation, validate: lambda { |v| v == 'Failed_proc_validation' }
35
- #validations
36
- param :some_number, min: 120, max: 500, in: (100..200), is: 122
37
- param :some_string, min_length: 21, max_length: 30, format: /^t.*g$/
38
- #combinations
39
- param :missing_with_validation, coerce: Integer, :default => 60 * 60, :validate => lambda { |v| v >= 60 * 60 }
40
- param :is_true, coerce: :boolean
41
- param :is_false, coerce: :boolean
42
- #recursive
43
- param :recursive do
44
- param :wasnt_here_before, default: true
45
- end
46
- end
47
- }
48
-
49
-
50
- it 'does amazing things' do
51
- (r.valid?).must_equal false
52
- r[:ignored].must_be_nil
53
- r[:no_value].must_equal 1
54
- r[:proc_default].must_equal 5
55
- r[:renamed].must_equal :to_be_renamed
56
- r[:integer_coercion].must_equal 1
57
- r[:bad_number].must_equal 12.0
58
-
59
- r[:array_with_delim].must_equal ["1", "2", "3"]
60
- r[:hash_as_string].must_equal ({ "a" => "1", "b" => "2", "c" => "d" })
61
- r[:missing_with_validation].must_equal 60 * 60
62
- r[:is_true].must_equal true
63
- r[:is_false].must_equal false
64
-
65
- #recursive checking
66
- r[:recursive][:wasnt_here_before].must_equal true
67
-
68
- #failed items don't show up
69
- r.errors.size.must_equal 2
70
- r[:doesnt_exist].must_be_nil
71
- r[:proc_validation].must_be_nil
72
- r.errors[0].must_equal 'Parameter doesnt_exist is required and missing'
73
- r.errors[1].must_equal 'is_this_valid? failed validation using proc'
74
-
75
- end
76
-
77
- it 'injects into current class' do
78
- r = HashParams.new({will_be_injected: 12345}, injection_target: self) do
79
- param :will_be_injected
80
- end
81
- r[:will_be_injected].must_equal 12345
82
- @will_be_injected.must_equal 12345
83
- will_be_injected.must_equal 12345
84
- end
85
-
86
- it 'passes through without alteration' do
87
- r=HashParams.new(test: 1, two: {three: :four})
88
- r[:test].must_equal 1
89
- r[:two][:three].must_equal :four
90
- end
91
-
92
- it 'validates plain objects' do
93
- HashParams.validate(1, min: 0, max: 10, is: 1).must_equal true
94
- end
95
- it 'coerces plain objects' do
96
- hash_as_string = "{a => 1,b => 2,c => d}"
97
- h=HashParams.coerce(hash_as_string, Hash, delimiter: ',', separator: '=>' )
98
- h.must_be_instance_of Hash
99
-
100
-
101
- end
102
- end
data/tmp/module_spec.rb DELETED
@@ -1,27 +0,0 @@
1
- require 'pry'
2
- module M1
3
- def im
4
- puts 'm1 im'
5
- end
6
- end
7
-
8
- module M2
9
- def self.cm
10
- puts 'm2 cm'
11
- end
12
- end
13
-
14
-
15
- module T1
16
- include M1
17
- end
18
- module T2
19
- extend M1
20
- end
21
- module T3
22
- include M2
23
- end
24
- module T4
25
- extend M2
26
- end
27
-
data/tmp/var_spec.rb DELETED
@@ -1,9 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
- describe HashParams do
4
- let(:v) { HashParams }
5
- it 'does things' do
6
- HashParams::BindingValidator("test")
7
- binding.pry
8
- end
9
- end
data/tmp/yaml_params.rb DELETED
@@ -1,109 +0,0 @@
1
- class YamlParams < HashParams
2
-
3
- ENVIRONMENT = ENV['HASH_PARAMS_ENV'] || (defined?(Rails) && Rails.env) || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
4
-
5
- def initialize(file_name=nil, opts={})
6
-
7
- env ||= opts[:env] || opts[:environment] || ENVIRONMENT
8
-
9
- file_name = nil if [:defaults, :default, :auto].include?(file_name)
10
-
11
- h =if file_name
12
- hash_from_yaml_file(file_name)
13
- else
14
- hash_from_default_yaml_files(opts[:app_name], env, opts[:roots], opts[:file_separator], opts[:file_extension])
15
- end
16
-
17
- if block_given?
18
- # warn '[DEPRECATION] Passing blocks into the constructor is deprecated. Please use validate or strictly validate in the future'
19
- super(h, opts, &Proc.new)
20
- else
21
- super(h, opts)
22
- end
23
- end
24
-
25
-
26
- def hash_from_yaml_file(filename, env=ENVIRONMENT)
27
- r = File.exists?(filename) ? YAML::load(ERB.new(File.read(filename)).result) : {}
28
- r[env] || r
29
- end
30
-
31
-
32
- def hash_from_default_yaml_files(app_name=nil, env=nil, roots=nil, file_separator=nil, file_extension=nil)
33
- #if a nil is passed in we still use the defaults
34
- app_name ||= ''
35
- env ||= ENVIRONMENT
36
- roots ||= nil
37
- file_separator ||= '_'
38
- file_extension ||= 'yml'
39
-
40
- h = {}
41
- home_dir = File.expand_path('~')
42
- hostname = Socket.gethostname
43
-
44
- base_file_names = %W(
45
- settings.#{file_extension}
46
- default.#{file_extension}
47
-
48
- #{env}.#{file_extension}
49
-
50
- #{hostname}.#{file_extension}
51
- #{hostname}#{file_separator}#{env}.#{file_extension}
52
-
53
- local.#{file_extension}
54
- local#{file_separator}#{env}.#{file_extension}
55
- settings.local.#{file_extension}
56
- settings.local#{file_separator}#{env}.#{file_extension}
57
- config.local.#{file_extension}
58
- config.local#{file_separator}#{env}.#{file_extension}
59
- #{app_name}#{file_separator}settings.#{file_extension}
60
- #{app_name}#{file_separator}config.#{file_extension}
61
- #{app_name}#{file_separator}default.#{file_extension}
62
- #{app_name}#{file_separator}#{env}.#{file_extension}
63
- #{app_name}#{file_separator}#{hostname}.#{file_extension}
64
- #{app_name}#{file_separator}#{hostname}#{file_separator}#{env}.#{file_extension}
65
- #{app_name}#{file_separator}local.#{file_extension}
66
- #{app_name}#{file_separator}local#{file_separator}#{env}.#{file_extension}
67
- #{app_name}#{file_separator}settings.local.#{file_extension}
68
- #{app_name}#{file_separator}settings.local#{file_separator}#{env}.#{file_extension}
69
- #{app_name}#{file_separator}config.local.#{file_extension}
70
- #{app_name}#{file_separator}config.local#{file_separator}#{env}.#{file_extension}
71
-
72
- )
73
-
74
- all_roots = Array(roots) if roots
75
- all_roots ||= [
76
- Dir.pwd,
77
- File.join('/etc', app_name.to_s),
78
- File.join('/usr', 'local', 'etc', app_name.to_s),
79
- File.join(home_dir, 'etc', app_name.to_s),
80
- File.join(home_dir, ".#{app_name}"),
81
- File.join(home_dir, '.hash_params', app_name.to_s),
82
- File.join(Dir.pwd, 'config'),
83
- File.join(Dir.pwd, 'settings')
84
- ]
85
- if defined?(Rails)
86
- all_roots << Rails.root.join('config')
87
- end
88
-
89
- all_roots.each do |root|
90
- base_file_names.each do |fname|
91
- file = File.join(root, fname)
92
- h = deep_merge(h, hash_from_yaml_file(file)) if File.exists?(file)
93
- end
94
- end
95
- h
96
- end
97
-
98
- def deep_merge(hash, other_hash)
99
- if other_hash.is_a?(::Hash) && hash.is_a?(::Hash)
100
- other_hash.each do |k, v|
101
- hash[k] = hash.key?(k) ? deep_merge(hash[k], v) : v
102
- end
103
- hash
104
- else
105
- other_hash
106
- end
107
- end
108
- end
109
-