hashmake 0.1.9 → 0.2.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.
- data/ChangeLog.rdoc +11 -2
- data/README.rdoc +11 -5
- data/lib/hashmake.rb +2 -0
- data/lib/hashmake/arg_spec.rb +28 -19
- data/lib/hashmake/array_arg_spec.rb +49 -0
- data/lib/hashmake/hash_arg_spec.rb +49 -0
- data/lib/hashmake/hash_makeable.rb +13 -148
- data/lib/hashmake/version.rb +1 -1
- data/spec/arg_spec_spec.rb +30 -14
- data/spec/array_arg_spec_spec.rb +45 -0
- data/spec/hash_arg_spec_spec.rb +45 -0
- data/spec/hash_makeable_spec.rb +3 -105
- metadata +10 -4
data/ChangeLog.rdoc
CHANGED
@@ -37,6 +37,15 @@ Add #find_arg_specs and #make_hash methods to HashMakeable.
|
|
37
37
|
|
38
38
|
In HashMakeable.make_hash, only make objects into hashes if the object class matches the arg spec type (and, still, if it is hash makeable).
|
39
39
|
|
40
|
-
=== 0.1.
|
40
|
+
=== 0.1.9 / 2013-06-21
|
41
|
+
|
42
|
+
Add :allow_nil option to ArgSpec.new. If an arg spec allows nil, it mean that if a hashed arg is nil, no ArgumentError will be raised and the validator won't be called.
|
43
|
+
|
44
|
+
=== 0.2.0 / 2013-06-21
|
41
45
|
|
42
|
-
|
46
|
+
A bit of a major release. mostly to cut back features and modify interfaces a bit.
|
47
|
+
-hash_make does not recursively build objects from hashes, even if the expected object type is hash-makeable
|
48
|
+
-removed allow_nil from arg_spec
|
49
|
+
-add separate classes for container arg specs (array and hash)
|
50
|
+
-remove make_hash
|
51
|
+
-switch order of arguments for hash_make. Hashed args come first now, and arg spec Hash comes next.
|
data/README.rdoc
CHANGED
@@ -8,11 +8,13 @@
|
|
8
8
|
|
9
9
|
Make hash-based object initialization easy!
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
There is also a make_hash method to turn an object into a representative Hash object. Any hash-makeable sub-objects can be turned into Hash objects as well.
|
11
|
+
The hash_make method checks hashed arguments against a set of specifications, then values are assigned to instance variables matching the arg keys.
|
14
12
|
|
15
13
|
== Features
|
14
|
+
Type checking via Object#is_a?. The default type is Object, allowing anything.
|
15
|
+
Mark as required/not. Set to true, by default.
|
16
|
+
Default value, for non-required args that aren't given. For default values that are mutable, make the default value a Proc that can be called to generate the mutable value.
|
17
|
+
Validation of values via a Proc.
|
16
18
|
|
17
19
|
== Examples
|
18
20
|
|
@@ -24,9 +26,10 @@ There is also a make_hash method to turn an object into a representative Hash ob
|
|
24
26
|
ARG_SPECS = {
|
25
27
|
:x => arg_spec(:reqd => true, :type => Float, :validator => ->(a){ a.between?(0.0,1.0) }),
|
26
28
|
:y => arg_spec(:reqd => false, :type => Float, :validator => ->(a){ a.between?(0.0,1.0) }, :default => 0.0),
|
29
|
+
:z => arg_spec_array(:reqd => false, :type => String, :validator => ->(a){ a.size > 0 })
|
27
30
|
}
|
28
31
|
|
29
|
-
attr_reader :x, :y
|
32
|
+
attr_reader :x, :y, :z
|
30
33
|
|
31
34
|
def initialize hashed_args
|
32
35
|
hash_make(ARG_SPECS, hashed_args)
|
@@ -37,7 +40,10 @@ There is also a make_hash method to turn an object into a representative Hash ob
|
|
37
40
|
a = MyClass.new :x => 0.5, :y => 0.2 # a.x => 0.5, a.y => 0.2
|
38
41
|
a = MyClass.new # raise ArgumentError because :x is reqd and not given
|
39
42
|
a = MyClass.new :y => 0.5 # raise ArgumentError because :x is reqd and not given
|
40
|
-
|
43
|
+
|
44
|
+
a = MyClass.new :x => 0.5, :z => ["abc", "efg"] # OK
|
45
|
+
a = MyClass.new :x => 0.5, :z => ["abc", ""] # raise ArgumentError, because validator requires str.size > 0
|
46
|
+
|
41
47
|
== Requirements
|
42
48
|
|
43
49
|
== Install
|
data/lib/hashmake.rb
CHANGED
data/lib/hashmake/arg_spec.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'pry'
|
3
|
+
|
1
4
|
module Hashmake
|
2
5
|
|
3
6
|
# Provides a specification of how a hashed arg is to be processed by the
|
@@ -7,28 +10,22 @@ module Hashmake
|
|
7
10
|
#
|
8
11
|
class ArgSpec
|
9
12
|
|
10
|
-
# The valid container types. If nil, indicates no container is expected,
|
11
|
-
# just a plain object of type given by :type.
|
12
|
-
CONTAINERS = [ nil, Hash, Array ]
|
13
|
-
|
14
13
|
# Defines default key/value pairs to use in initializing an instance.
|
15
14
|
# The :reqd key is set to true by default.
|
16
15
|
# The :validator key is set to a Proc that always returns true.
|
17
|
-
# The :container key is set to CONTAINER_NONE.
|
18
16
|
DEFAULT_ARGS = {
|
19
17
|
:reqd => true,
|
20
18
|
:validator => ->(a){true},
|
21
|
-
:container => nil,
|
22
19
|
:type => Object,
|
23
20
|
:allow_nil => false
|
24
21
|
}
|
25
22
|
|
26
|
-
attr_reader :type, :validator, :reqd, :default
|
23
|
+
attr_reader :type, :validator, :reqd, :default
|
27
24
|
|
28
25
|
# A new instance of ArgSpec.
|
29
26
|
#
|
30
27
|
# @param [Hash] hashed_args Hash to use in initializing an instance. Optional keys
|
31
|
-
# are :type, :reqd, :validator,
|
28
|
+
# are :type, :reqd, :validator, and :default.
|
32
29
|
# :type => the type of object expected to be paired
|
33
30
|
# with the key.
|
34
31
|
# :reqd => If true, the arg key must be in the hash
|
@@ -41,30 +38,42 @@ class ArgSpec
|
|
41
38
|
# expecting it to produce the default.
|
42
39
|
# :validator => a Proc used to check the validity of
|
43
40
|
# whatever value is paired with an arg key.
|
44
|
-
# :container => indicates whether the arg key will be paired
|
45
|
-
# with a container (array or hash) which contains
|
46
|
-
# objects of the type specified by :type. Valid values
|
47
|
-
# for this are given by ArgSpec::CONTAINERS.
|
48
41
|
def initialize hashed_args
|
49
42
|
new_args = DEFAULT_ARGS.merge(hashed_args)
|
50
43
|
|
51
44
|
@type = new_args[:type]
|
52
|
-
raise ArgumentError, "
|
45
|
+
raise ArgumentError, "#{@type} is not a Class" unless @type.is_a?(Class)
|
53
46
|
|
54
47
|
@validator = new_args[:validator]
|
55
48
|
@reqd = new_args[:reqd]
|
56
49
|
|
57
|
-
@container = new_args[:container]
|
58
|
-
raise ArgumentError, "CONTAINERS does not include container #{@container}" unless CONTAINERS.include?(@container)
|
59
|
-
|
60
|
-
@allow_nil = new_args[:allow_nil]
|
61
|
-
|
62
50
|
unless @reqd
|
63
51
|
msg = "if hashed arg is not required, a default value or value generator (proc) must be defined via :default key"
|
64
52
|
raise ArgumentError, msg unless new_args.has_key?(:default)
|
65
53
|
@default = new_args[:default]
|
66
54
|
end
|
67
55
|
end
|
68
|
-
|
56
|
+
|
57
|
+
# If the val is not of the right type, but is a Hash, attempt to
|
58
|
+
# make an object of the right type if it is hash-makeable
|
59
|
+
def hash_make_if_needed val
|
60
|
+
if Hashmake.hash_makeable?(@type) and val.is_a?(Hash)
|
61
|
+
val = @type.new val
|
62
|
+
end
|
63
|
+
return val
|
64
|
+
end
|
65
|
+
|
66
|
+
# Check the given value, and raise ArgumentError it is not valid.
|
67
|
+
def validate_value val
|
68
|
+
raise ArgumentError, "val #{val} is not a #{@type}" unless val.is_a?(@type)
|
69
|
+
raise ArgumentError, "val #{val} is not valid" unless @validator.call(val)
|
70
|
+
end
|
71
|
+
|
72
|
+
def make_hash_if_possible val
|
73
|
+
if Hashmake::hash_makeable?(val.class) and val.class.is_a?(@type)
|
74
|
+
val = val.make_hash
|
75
|
+
end
|
76
|
+
return val
|
77
|
+
end
|
69
78
|
end
|
70
79
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module Hashmake
|
3
|
+
|
4
|
+
class ArrayArgSpec
|
5
|
+
|
6
|
+
attr_reader :arg_spec
|
7
|
+
|
8
|
+
def initialize hashed_args = {}
|
9
|
+
hashed_args = { :default => ->(){ [] } }.merge hashed_args
|
10
|
+
@arg_spec = ArgSpec.new hashed_args
|
11
|
+
end
|
12
|
+
|
13
|
+
def type
|
14
|
+
@arg_spec.type
|
15
|
+
end
|
16
|
+
|
17
|
+
def validator
|
18
|
+
@arg_spec.validator
|
19
|
+
end
|
20
|
+
|
21
|
+
def reqd
|
22
|
+
@arg_spec.reqd
|
23
|
+
end
|
24
|
+
|
25
|
+
def default
|
26
|
+
@arg_spec.default
|
27
|
+
end
|
28
|
+
|
29
|
+
def hash_make_if_needed val
|
30
|
+
val.each_index do |i|
|
31
|
+
item = val[i]
|
32
|
+
val[i] = @arg_spec.hash_make_if_needed item
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate_value val
|
37
|
+
val.each do |item|
|
38
|
+
@arg_spec.validate_value item
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def make_hash_if_possible ary
|
43
|
+
ary.each_index do |i|
|
44
|
+
ary[i] = @arg_spec.make_hash_if_possible ary[i]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module Hashmake
|
3
|
+
|
4
|
+
class HashArgSpec
|
5
|
+
|
6
|
+
attr_reader :arg_spec
|
7
|
+
|
8
|
+
def initialize hashed_args = {}
|
9
|
+
hashed_args = { :default => ->(){ {} } }.merge hashed_args
|
10
|
+
@arg_spec = ArgSpec.new hashed_args
|
11
|
+
end
|
12
|
+
|
13
|
+
def type
|
14
|
+
@arg_spec.type
|
15
|
+
end
|
16
|
+
|
17
|
+
def validator
|
18
|
+
@arg_spec.validator
|
19
|
+
end
|
20
|
+
|
21
|
+
def reqd
|
22
|
+
@arg_spec.reqd
|
23
|
+
end
|
24
|
+
|
25
|
+
def default
|
26
|
+
@arg_spec.default
|
27
|
+
end
|
28
|
+
|
29
|
+
def hash_make_if_needed val
|
30
|
+
val.each_key do |item_key|
|
31
|
+
item = val[item_key]
|
32
|
+
val[item_key] = @arg_spec.hash_make_if_needed item
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate_value val
|
37
|
+
val.each do |key, item|
|
38
|
+
@arg_spec.validate_value item
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def make_hash_if_possible hash
|
43
|
+
hash.each_key do |key|
|
44
|
+
hash[key] = @arg_spec.make_hash_if_possible hash[key]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -20,47 +20,21 @@ module HashMakeable
|
|
20
20
|
# Process a hash that contains 'hashed args'. Each hashed arg is intended to
|
21
21
|
# be used in initializing an object instance.
|
22
22
|
#
|
23
|
-
# @param [Enumerable] arg_specs An enumerable of ArgSpec objects. Each object
|
24
|
-
# details an arg key that might be expected in the
|
25
|
-
# args hash.
|
26
23
|
# @param [Hash] hashed_args A hash that should contain at least all the required
|
27
24
|
# keys and valid values, according to the arg_specs passed in.
|
28
25
|
# Nonrequired keys can be given as well, but if they are
|
29
26
|
# not then a default value is assigned (again, according to
|
30
27
|
# arg_specs passed in).
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
# @param [Hash] arg_specs A hash of ArgSpec objects. An ArgSpec object details
|
29
|
+
# what to expect from the hashed argument with a
|
30
|
+
# matching same key.
|
31
|
+
# @param [true/false] assign_args If true, the hashed args will be assigned to
|
32
|
+
# instance variables. If false, the hashed args
|
33
|
+
# will still be checked, but not assigned.
|
34
|
+
def hash_make hashed_args, arg_specs = find_arg_specs, assign_args = true
|
37
35
|
arg_specs.each do |key, arg_spec|
|
38
36
|
if hashed_args.has_key?(key)
|
39
37
|
val = hashed_args[key]
|
40
|
-
|
41
|
-
if Hashmake::hash_makeable?(arg_spec.type)
|
42
|
-
# If the val is not of the right type, but is a Hash, attempt to
|
43
|
-
# make an object of the right type if it is hash-makeable
|
44
|
-
if arg_spec.container == Array && val.is_a?(Array)
|
45
|
-
val.each_index do |i|
|
46
|
-
item = val[i]
|
47
|
-
if !item.is_a?(arg_spec.type) && item.is_a?(Hash)
|
48
|
-
val[i] = arg_spec.type.new item
|
49
|
-
end
|
50
|
-
end
|
51
|
-
elsif arg_spec.container == Hash && val.is_a?(Hash)
|
52
|
-
val.each_key do |item_key|
|
53
|
-
item = val[item_key]
|
54
|
-
if !item.is_a?(arg_spec.type) && item.is_a?(Hash)
|
55
|
-
val[item_key] = arg_spec.type.new item
|
56
|
-
end
|
57
|
-
end
|
58
|
-
else
|
59
|
-
if !val.is_a?(arg_spec.type) && val.is_a?(Hash)
|
60
|
-
val = arg_spec.type.new val
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
38
|
else
|
65
39
|
if arg_spec.reqd
|
66
40
|
raise ArgumentError, "hashed_args does not have required key #{key}"
|
@@ -73,50 +47,14 @@ module HashMakeable
|
|
73
47
|
end
|
74
48
|
end
|
75
49
|
|
76
|
-
|
50
|
+
arg_spec.validate_value val
|
51
|
+
|
77
52
|
if assign_args
|
78
53
|
self.instance_variable_set("@#{key.to_s}".to_sym, val)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Check the given value, using the given ArgSpec object. An ArgumentError
|
84
|
-
# exception will be raised if the value is not valid.
|
85
|
-
def validate_arg arg_spec, val
|
86
|
-
if arg_spec.container == Array
|
87
|
-
raise ArgumentError, "val #{val} is not an array" unless val.is_a?(Array)
|
88
|
-
val.each do |item|
|
89
|
-
if item.nil?
|
90
|
-
raise ArgumentError, "nil was given" unless arg_spec.allow_nil
|
91
|
-
else
|
92
|
-
raise ArgumentError, "array item #{item} is not a #{arg_spec.type}" unless item.is_a?(arg_spec.type)
|
93
|
-
raise ArgumentError, "array item #{item} is not valid" unless arg_spec.validator.call(item)
|
94
|
-
end
|
95
54
|
end
|
96
|
-
elsif arg_spec.container == Hash
|
97
|
-
raise ArgumentError, "val #{val} is not a hash" unless val.is_a?(Hash)
|
98
|
-
val.values.each do |item|
|
99
|
-
if item.nil?
|
100
|
-
raise ArgumentError, "nil was given" unless arg_spec.allow_nil
|
101
|
-
else
|
102
|
-
raise ArgumentError, "hash item #{item} is not a #{arg_spec.type}" unless item.is_a?(arg_spec.type)
|
103
|
-
raise ArgumentError, "hash item #{item} is not valid" unless arg_spec.validator.call(item)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
elsif arg_spec.container.nil?
|
107
|
-
if val.nil?
|
108
|
-
raise ArgumentError, "nil was given" unless arg_spec.allow_nil
|
109
|
-
else
|
110
|
-
raise ArgumentError, "val #{val} is not a #{arg_spec.type}" unless val.is_a?(arg_spec.type)
|
111
|
-
raise ArgumentError, "val #{val} is not valid" unless arg_spec.validator.call(val)
|
112
|
-
end
|
113
|
-
else
|
114
|
-
raise ArgumentError, "arg_spec.container #{arg_spec.container} is not valid"
|
115
55
|
end
|
116
|
-
|
117
|
-
return true
|
118
56
|
end
|
119
|
-
|
57
|
+
|
120
58
|
# Look in the current class for a constant that is a Hash containing (only)
|
121
59
|
# ArgSpec objects. Returns the first constant matching this criteria, or nil
|
122
60
|
# if none was found.
|
@@ -126,7 +64,7 @@ module HashMakeable
|
|
126
64
|
if val.is_a? Hash
|
127
65
|
all_arg_specs = true
|
128
66
|
val.each do |key,value|
|
129
|
-
unless value.is_a? ArgSpec
|
67
|
+
unless value.is_a? ArgSpec or value.is_a? ArrayArgSpec or value.is_a?(HashArgSpec)
|
130
68
|
all_arg_specs = false
|
131
69
|
break
|
132
70
|
end
|
@@ -140,76 +78,6 @@ module HashMakeable
|
|
140
78
|
|
141
79
|
return nil
|
142
80
|
end
|
143
|
-
|
144
|
-
# Produce a hash that contains 'hashed args'. Each hashed arg is intended to
|
145
|
-
# be used in initializing an object instance.
|
146
|
-
#
|
147
|
-
# @param [Enumerable] arg_specs An enumerable of ArgSpec objects. Each one
|
148
|
-
# details an arg key that might be expected in the
|
149
|
-
# args hash. This param is nil by default. If the param
|
150
|
-
# is nil, this method will attempt to locate arg specs
|
151
|
-
# using find_arg_specs.
|
152
|
-
#
|
153
|
-
def make_hash arg_specs = nil
|
154
|
-
if arg_specs.nil?
|
155
|
-
arg_specs = self.find_arg_specs
|
156
|
-
raise "No arg specs given, and no class constant that is a Hash containing only ArgSpec objects was found" if arg_specs.nil?
|
157
|
-
end
|
158
|
-
|
159
|
-
arg_specs.each do |key, arg_spec|
|
160
|
-
raise ArgumentError, "arg_specs item #{arg_spec} is not a ArgSpec" unless arg_spec.is_a?(ArgSpec)
|
161
|
-
end
|
162
|
-
|
163
|
-
hash = {}
|
164
|
-
|
165
|
-
arg_specs.each do |key, arg_spec|
|
166
|
-
sym = "@#{key}".to_sym
|
167
|
-
raise ArgumentError, "current obj #{self} does not include instance variable #{sym}" if !self.instance_variables.include?(sym)
|
168
|
-
val = self.instance_variable_get(sym)
|
169
|
-
|
170
|
-
should_assign = false
|
171
|
-
|
172
|
-
if arg_spec.reqd
|
173
|
-
should_assign = true
|
174
|
-
else
|
175
|
-
if arg_spec.default.is_a?(Proc)
|
176
|
-
should_assign = (val != arg_spec.default.call)
|
177
|
-
else
|
178
|
-
should_assign = (val != arg_spec.default)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
if should_assign
|
183
|
-
if val.is_a?(Array) && arg_spec.container == Array
|
184
|
-
ary = val
|
185
|
-
val = []
|
186
|
-
ary.each do |item|
|
187
|
-
if Hashmake::hash_makeable?(item.class) and item.class == arg_spec.type
|
188
|
-
val << item.make_hash
|
189
|
-
else
|
190
|
-
val << item
|
191
|
-
end
|
192
|
-
end
|
193
|
-
elsif val.is_a?(Hash) && arg_spec.container == Hash
|
194
|
-
hsh = val
|
195
|
-
val = {}
|
196
|
-
hsh.each do |hsh_key,item|
|
197
|
-
if Hashmake::hash_makeable? item.class and item.class == arg_spec.type
|
198
|
-
val[hsh_key] = item.make_hash
|
199
|
-
else
|
200
|
-
val[hsh_key] = item
|
201
|
-
end
|
202
|
-
end
|
203
|
-
elsif Hashmake::hash_makeable?(val.class) and val.class == arg_spec.type
|
204
|
-
val = val.make_hash
|
205
|
-
end
|
206
|
-
|
207
|
-
hash[key] = val
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
return hash
|
212
|
-
end
|
213
81
|
|
214
82
|
# Contains class methods to be added to a class that includes the
|
215
83
|
# HashMakeable module.
|
@@ -222,17 +90,14 @@ module HashMakeable
|
|
222
90
|
# Helper method to make a ArgSpec object where the container is an Array.
|
223
91
|
# Set :default to a Proc that generates an empty array.
|
224
92
|
def arg_spec_array args
|
225
|
-
|
226
|
-
ArgSpec.new args
|
93
|
+
ArrayArgSpec.new args
|
227
94
|
end
|
228
95
|
|
229
96
|
# Helper method to make a ArgSpec object where the container is an Hash.
|
230
97
|
# Set :default to a Proc that generates an empty hash.
|
231
98
|
def arg_spec_hash args
|
232
|
-
|
233
|
-
ArgSpec.new args
|
99
|
+
HashArgSpec.new args
|
234
100
|
end
|
235
101
|
end
|
236
|
-
|
237
102
|
end
|
238
103
|
end
|
data/lib/hashmake/version.rb
CHANGED
data/spec/arg_spec_spec.rb
CHANGED
@@ -16,22 +16,38 @@ describe Hashmake::ArgSpec do
|
|
16
16
|
|
17
17
|
lambda { Hashmake::ArgSpec.new hash }.should_not raise_error(ArgumentError)
|
18
18
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
|
20
|
+
context '#validate_value' do
|
21
|
+
before :each do
|
22
|
+
@arg_spec = ArgSpec.new(:reqd => true, :type => Fixnum, :validator => ->(a){ a > 0})
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'value given is correct type' do
|
26
|
+
context 'value given is valid' do
|
27
|
+
it 'should not raise ArgumentError' do
|
28
|
+
lambda { @arg_spec.validate_value 1 }.should_not raise_error
|
29
|
+
end
|
30
|
+
end
|
25
31
|
|
26
|
-
|
32
|
+
context 'value given is not valid' do
|
33
|
+
it 'should raise ArgumentError' do
|
34
|
+
lambda { @arg_spec.validate_value 0 }.should raise_error(ArgumentError)
|
35
|
+
end
|
36
|
+
end
|
27
37
|
end
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'should raise ArgumentError if invalid container is given' do
|
31
|
-
hash = {
|
32
|
-
:reqd => true, :key => :stuff, :type => String, :container => Fixnum
|
33
|
-
}
|
34
38
|
|
35
|
-
|
39
|
+
context 'value given is not correct type' do
|
40
|
+
context 'value given is valid' do
|
41
|
+
it 'should raise ArgumentError' do
|
42
|
+
lambda { @arg_spec.validate_value 1.0 }.should raise_error(ArgumentError)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'value given is not valid' do
|
47
|
+
it 'should raise ArgumentError' do
|
48
|
+
lambda { @arg_spec.validate_value 0.0 }.should raise_error(ArgumentError)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
36
52
|
end
|
37
53
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Hashmake::ArrayArgSpec do
|
4
|
+
it 'should not raise ArgumentError if :reqd is false and a :default value is given' do
|
5
|
+
hash = {
|
6
|
+
:reqd => false, :key => :some_variable, :type => String, :default => ""
|
7
|
+
}
|
8
|
+
|
9
|
+
lambda { Hashmake::ArrayArgSpec.new hash }.should_not raise_error(ArgumentError)
|
10
|
+
end
|
11
|
+
|
12
|
+
context '#validate_value' do
|
13
|
+
before :each do
|
14
|
+
@arg_spec = ArrayArgSpec.new(:reqd => true, :type => Fixnum, :validator => ->(a){ a > 0})
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'value given is correct type' do
|
18
|
+
context 'value given is valid' do
|
19
|
+
it 'should not raise ArgumentError' do
|
20
|
+
lambda { @arg_spec.validate_value([1, 2]) }.should_not raise_error
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'value given is not valid' do
|
25
|
+
it 'should raise ArgumentError' do
|
26
|
+
lambda { @arg_spec.validate_value([0, 2]) }.should raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'value given is not correct type' do
|
32
|
+
context 'value given is valid' do
|
33
|
+
it 'should raise ArgumentError' do
|
34
|
+
lambda { @arg_spec.validate_value([1.0, 2]) }.should raise_error(ArgumentError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'value given is not valid' do
|
39
|
+
it 'should raise ArgumentError' do
|
40
|
+
lambda { @arg_spec.validate_value([0.0, 2]) }.should raise_error(ArgumentError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Hashmake::HashArgSpec do
|
4
|
+
it 'should not raise ArgumentError if :reqd is false and a :default value is given' do
|
5
|
+
hash = {
|
6
|
+
:reqd => false, :key => :some_variable, :type => String, :default => ""
|
7
|
+
}
|
8
|
+
|
9
|
+
lambda { Hashmake::HashArgSpec.new hash }.should_not raise_error(ArgumentError)
|
10
|
+
end
|
11
|
+
|
12
|
+
context '#validate_value' do
|
13
|
+
before :each do
|
14
|
+
@arg_spec = HashArgSpec.new(:reqd => true, :type => Fixnum, :validator => ->(a){ a > 0})
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'value given is correct type' do
|
18
|
+
context 'value given is valid' do
|
19
|
+
it 'should not raise ArgumentError' do
|
20
|
+
lambda { @arg_spec.validate_value(:a => 1, :b => 2) }.should_not raise_error
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'value given is not valid' do
|
25
|
+
it 'should raise ArgumentError' do
|
26
|
+
lambda { @arg_spec.validate_value(:a => 0, :b => 2) }.should raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'value given is not correct type' do
|
32
|
+
context 'value given is valid' do
|
33
|
+
it 'should raise ArgumentError' do
|
34
|
+
lambda { @arg_spec.validate_value(:a => 1.0, :b => 2) }.should raise_error(ArgumentError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'value given is not valid' do
|
39
|
+
it 'should raise ArgumentError' do
|
40
|
+
lambda { @arg_spec.validate_value(:a => 0.0, :b => 2) }.should raise_error(ArgumentError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/spec/hash_makeable_spec.rb
CHANGED
@@ -2,25 +2,6 @@ require 'pry'
|
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
3
|
|
4
4
|
describe Hashmake::HashMakeable do
|
5
|
-
class AlsoHashMakeable
|
6
|
-
include Comparable
|
7
|
-
include HashMakeable
|
8
|
-
|
9
|
-
ARG_SPECS = {
|
10
|
-
:a_number => arg_spec(:reqd => false, :type => Numeric, :default => 1.0)
|
11
|
-
}
|
12
|
-
|
13
|
-
attr_accessor :a_number
|
14
|
-
|
15
|
-
def initialize args = {}
|
16
|
-
hash_make ARG_SPECS, args
|
17
|
-
end
|
18
|
-
|
19
|
-
def <=>(other)
|
20
|
-
a_number <=> other.a_number
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
5
|
class MyTestClass
|
25
6
|
include HashMakeable
|
26
7
|
|
@@ -31,29 +12,13 @@ describe Hashmake::HashMakeable do
|
|
31
12
|
:not_reqd_float => arg_spec(:reqd => false, :type => Float, :default => NON_REQD_FLOAT_DEFAULT, :validator => ->(a){ a.between?(0.0,1.0) }),
|
32
13
|
:not_reqd_array_of_float => arg_spec_array(:reqd => false, :type => Float, :validator => ->(a){ a.between?(0.0,1.0) }),
|
33
14
|
:not_reqd_hash_of_float => arg_spec_hash(:reqd => false, :type => Float, :validator => ->(a){ a.between?(0.0,1.0) }),
|
34
|
-
:also_hash_makeable => arg_spec(:reqd => false, :type => AlsoHashMakeable, :default => ->(){ AlsoHashMakeable.new }),
|
35
|
-
:ary_of_also_hash_makeables => arg_spec_array(:reqd => false, :type => AlsoHashMakeable)
|
36
15
|
}
|
37
16
|
|
38
|
-
attr_accessor :not_reqd_float
|
39
|
-
attr_reader :reqd_string, :not_reqd_array_of_float, :not_reqd_hash_of_float
|
17
|
+
attr_accessor :not_reqd_float
|
18
|
+
attr_reader :reqd_string, :not_reqd_array_of_float, :not_reqd_hash_of_float
|
40
19
|
|
41
20
|
def initialize hashed_args = {}
|
42
|
-
hash_make
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
class TestAllowNil
|
47
|
-
include HashMakeable
|
48
|
-
|
49
|
-
ARG_SPECS = {
|
50
|
-
:allows_nil => arg_spec(:reqd => false, :default => ->(){ "123" }, :type => String, :allow_nil => true),
|
51
|
-
:disallows_nil => arg_spec(:reqd => false, :default => ->(){ "123" }, :type => String, :allow_nil => false)
|
52
|
-
}
|
53
|
-
|
54
|
-
attr_reader :allows_nil, :disallows_nil
|
55
|
-
def initialize args
|
56
|
-
hash_make ARG_SPECS, args
|
21
|
+
hash_make hashed_args, ARG_SPECS
|
57
22
|
end
|
58
23
|
end
|
59
24
|
|
@@ -142,72 +107,5 @@ describe Hashmake::HashMakeable do
|
|
142
107
|
end.should raise_error(ArgumentError)
|
143
108
|
end
|
144
109
|
end
|
145
|
-
|
146
|
-
context 'hash-makeable arg' do
|
147
|
-
it 'should construct the hash-makeable arg from just a Hash' do
|
148
|
-
a_number = 5
|
149
|
-
a = MyTestClass.new(:reqd_string => "ok", :also_hash_makeable => { :a_number => a_number })
|
150
|
-
a.also_hash_makeable.a_number.should eq(a_number)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
it 'should not raise ArgumentError if nil is given when nil is allowed' do
|
155
|
-
lambda { TestAllowNil.new(:allows_nil => nil) }.should_not raise_error
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'should raise ArgumentError if nil is given when nil is not allowed' do
|
159
|
-
lambda { TestAllowNil.new(:disallows_nil => nil) }.should raise_error(ArgumentError)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
describe '#make_hash' do
|
164
|
-
before :each do
|
165
|
-
@reqd_string = "okeydoke"
|
166
|
-
@obj = MyTestClass.new :reqd_string => @reqd_string, :non_reqd_float => MyTestClass::NON_REQD_FLOAT_DEFAULT
|
167
|
-
@hash = @obj.make_hash
|
168
|
-
end
|
169
|
-
|
170
|
-
it 'should produce a Hash' do
|
171
|
-
@hash.should be_a Hash
|
172
|
-
end
|
173
|
-
|
174
|
-
it "should always include req'd values" do
|
175
|
-
@hash.should include(:reqd_string)
|
176
|
-
@hash[:reqd_string].should eq(@reqd_string)
|
177
|
-
end
|
178
|
-
|
179
|
-
it "should never include non-req'd default values" do
|
180
|
-
@hash.should_not include(:non_reqd_float)
|
181
|
-
end
|
182
|
-
|
183
|
-
it "should always include non-req'd non-default values" do
|
184
|
-
@obj.not_reqd_float = 2.0
|
185
|
-
hash = @obj.make_hash
|
186
|
-
hash.should include(:not_reqd_float)
|
187
|
-
hash[:not_reqd_float].should eq(2.0)
|
188
|
-
end
|
189
|
-
|
190
|
-
it "should turn any hash-makeable objects into Hash objects" do
|
191
|
-
@obj.also_hash_makeable.a_number = 2.0
|
192
|
-
hash = @obj.make_hash
|
193
|
-
hash.should include(:also_hash_makeable)
|
194
|
-
hash[:also_hash_makeable].should be_a Hash
|
195
|
-
hash[:also_hash_makeable].should include(:a_number)
|
196
|
-
hash[:also_hash_makeable][:a_number].should eq(2.0)
|
197
|
-
end
|
198
|
-
|
199
|
-
it "should turn an array of hash-makeable objects into an array of Hash objects" do
|
200
|
-
obj2 = MyTestClass.new @obj.make_hash
|
201
|
-
@obj.ary_of_also_hash_makeables = [
|
202
|
-
AlsoHashMakeable.new(:a_number => 1),
|
203
|
-
AlsoHashMakeable.new(:a_number => 2),
|
204
|
-
AlsoHashMakeable.new(:a_number => 3),
|
205
|
-
]
|
206
|
-
obj2 = MyTestClass.new @obj.make_hash
|
207
|
-
obj2.ary_of_also_hash_makeables.count.should be(3)
|
208
|
-
obj2.ary_of_also_hash_makeables[0].a_number.should eq(1)
|
209
|
-
obj2.ary_of_also_hash_makeables[1].a_number.should eq(2)
|
210
|
-
obj2.ary_of_also_hash_makeables[2].a_number.should eq(3)
|
211
|
-
end
|
212
110
|
end
|
213
111
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hashmake
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -112,9 +112,13 @@ files:
|
|
112
112
|
- hashmake.gemspec
|
113
113
|
- lib/hashmake.rb
|
114
114
|
- lib/hashmake/arg_spec.rb
|
115
|
+
- lib/hashmake/array_arg_spec.rb
|
116
|
+
- lib/hashmake/hash_arg_spec.rb
|
115
117
|
- lib/hashmake/hash_makeable.rb
|
116
118
|
- lib/hashmake/version.rb
|
117
119
|
- spec/arg_spec_spec.rb
|
120
|
+
- spec/array_arg_spec_spec.rb
|
121
|
+
- spec/hash_arg_spec_spec.rb
|
118
122
|
- spec/hash_makeable_spec.rb
|
119
123
|
- spec/hashmake_spec.rb
|
120
124
|
- spec/spec_helper.rb
|
@@ -133,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
137
|
version: '0'
|
134
138
|
segments:
|
135
139
|
- 0
|
136
|
-
hash: -
|
140
|
+
hash: -4514910862506440485
|
137
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
142
|
none: false
|
139
143
|
requirements:
|
@@ -142,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
146
|
version: '0'
|
143
147
|
segments:
|
144
148
|
- 0
|
145
|
-
hash: -
|
149
|
+
hash: -4514910862506440485
|
146
150
|
requirements: []
|
147
151
|
rubyforge_project:
|
148
152
|
rubygems_version: 1.8.23
|
@@ -151,6 +155,8 @@ specification_version: 3
|
|
151
155
|
summary: Make hashed-based object initialization easy!
|
152
156
|
test_files:
|
153
157
|
- spec/arg_spec_spec.rb
|
158
|
+
- spec/array_arg_spec_spec.rb
|
159
|
+
- spec/hash_arg_spec_spec.rb
|
154
160
|
- spec/hash_makeable_spec.rb
|
155
161
|
- spec/hashmake_spec.rb
|
156
162
|
- spec/spec_helper.rb
|