dynamicschema 2.0.0 → 2.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.
- checksums.yaml +4 -4
- data/README.md +380 -171
- data/dynamicschema.gemspec +2 -2
- data/lib/dynamic_schema/builder.rb +12 -6
- data/lib/dynamic_schema/compiler.rb +14 -9
- data/lib/dynamic_schema/receiver/object.rb +257 -200
- data/lib/dynamic_schema/struct.rb +71 -20
- data/lib/dynamic_schema/validator.rb +39 -5
- metadata +6 -9
data/dynamicschema.gemspec
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Gem::Specification.new do | spec |
|
|
2
2
|
|
|
3
3
|
spec.name = 'dynamicschema'
|
|
4
|
-
spec.version = '2.
|
|
4
|
+
spec.version = '2.2.0'
|
|
5
5
|
spec.authors = [ 'Kristoph Cichocki-Romanov' ]
|
|
6
6
|
spec.email = [ 'rubygems.org@kristoph.net' ]
|
|
7
7
|
|
|
@@ -38,7 +38,7 @@ Gem::Specification.new do | spec |
|
|
|
38
38
|
spec.files = Dir[ "lib/**/*.rb", "LICENSE", "README.md", "dynamicschema.gemspec" ]
|
|
39
39
|
spec.require_paths = [ "lib" ]
|
|
40
40
|
|
|
41
|
-
spec.add_development_dependency '
|
|
41
|
+
spec.add_development_dependency 'minitest', '~> 6.0'
|
|
42
42
|
spec.add_development_dependency 'debug', '~> 1.9'
|
|
43
43
|
|
|
44
44
|
end
|
|
@@ -29,22 +29,28 @@ module DynamicSchema
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def build( values = nil, &block )
|
|
33
|
-
receiver = Receiver::Object.new( values,
|
|
32
|
+
def build( values = nil, defaults: true, &block )
|
|
33
|
+
receiver = Receiver::Object.new( values,
|
|
34
|
+
schema: self.compiled_schema,
|
|
35
|
+
converter: self,
|
|
36
|
+
defaults: defaults )
|
|
34
37
|
receiver.instance_eval( &block ) if block
|
|
35
38
|
receiver.to_h
|
|
36
39
|
end
|
|
37
40
|
|
|
38
|
-
def build_from_bytes( bytes, filename: '(schema)', values: nil )
|
|
39
|
-
receiver = Receiver::Object.new( values,
|
|
41
|
+
def build_from_bytes( bytes, filename: '(schema)', values: nil, defaults: true )
|
|
42
|
+
receiver = Receiver::Object.new( values,
|
|
43
|
+
schema: compiled_schema,
|
|
44
|
+
converter: self,
|
|
45
|
+
defaults: defaults )
|
|
40
46
|
receiver.instance_eval( bytes, filename, 1 )
|
|
41
47
|
receiver.to_h
|
|
42
48
|
end
|
|
43
49
|
|
|
44
|
-
def build_from_file( path, values: nil )
|
|
50
|
+
def build_from_file( path, values: nil, defaults: true )
|
|
45
51
|
self.build_from_bytes(
|
|
46
52
|
File.read( path, encoding: 'UTF-8' ),
|
|
47
|
-
filename: path, values: values
|
|
53
|
+
filename: path, values: values, defaults: defaults
|
|
48
54
|
)
|
|
49
55
|
end
|
|
50
56
|
|
|
@@ -49,10 +49,12 @@ module DynamicSchema
|
|
|
49
49
|
::Kernel.raise ::NameError, "The name '#{name}' is reserved and cannot be used for parameters." \
|
|
50
50
|
if receiver.method_defined?( name ) || receiver.private_method_defined?( name )
|
|
51
51
|
|
|
52
|
+
type = options[ :type ]
|
|
53
|
+
options[ :type ] = ::Object unless type.is_a?( ::Array )
|
|
54
|
+
|
|
52
55
|
@compiled_schema[ name ] = options.merge( {
|
|
53
|
-
type: ::Object,
|
|
54
56
|
compiler: Compiler.new( compiled_blocks: @compiled_blocks ).compile( &block )
|
|
55
|
-
} )
|
|
57
|
+
} )
|
|
56
58
|
self
|
|
57
59
|
end
|
|
58
60
|
|
|
@@ -62,28 +64,31 @@ module DynamicSchema
|
|
|
62
64
|
if args.empty?
|
|
63
65
|
options = {}
|
|
64
66
|
elsif first.is_a?( ::Hash )
|
|
65
|
-
options = first
|
|
66
|
-
elsif args.length == 1 &&
|
|
67
|
+
options = first
|
|
68
|
+
elsif args.length == 1 &&
|
|
67
69
|
( first.is_a?( ::Class ) || first.is_a?( ::Module ) || first.is_a?( ::Array ) )
|
|
68
70
|
options = { type: first }
|
|
69
|
-
elsif args.length == 2 &&
|
|
70
|
-
( first.is_a?( ::Class ) || first.is_a?( ::Module ) || first.is_a?( ::Array ) ) &&
|
|
71
|
+
elsif args.length == 2 &&
|
|
72
|
+
( first.is_a?( ::Class ) || first.is_a?( ::Module ) || first.is_a?( ::Array ) ) &&
|
|
71
73
|
args[ 1 ].is_a?( ::Hash )
|
|
72
74
|
options = args[ 1 ]
|
|
73
75
|
options[ :type ] = args[ 0 ]
|
|
74
76
|
else
|
|
75
77
|
::Kernel.raise \
|
|
76
|
-
::ArgumentError,
|
|
78
|
+
::ArgumentError,
|
|
77
79
|
"A schema definition may only include the type (Class or Module) followed by options (Hash). "
|
|
78
80
|
end
|
|
79
81
|
|
|
80
82
|
type = options[ :type ]
|
|
81
|
-
|
|
83
|
+
|
|
84
|
+
if type.is_a?( ::Array ) && block
|
|
85
|
+
_object( method, options, &block )
|
|
86
|
+
elsif type == ::Object || ( type.nil? && block )
|
|
82
87
|
_object( method, options, &block )
|
|
83
88
|
else
|
|
84
89
|
_value( method, options )
|
|
85
90
|
end
|
|
86
|
-
|
|
91
|
+
|
|
87
92
|
end
|
|
88
93
|
|
|
89
94
|
def to_s
|
|
@@ -5,248 +5,305 @@ module DynamicSchema
|
|
|
5
5
|
module Receiver
|
|
6
6
|
class Object < Base
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
def initialize( values = nil, schema:, converter:, defaults: true )
|
|
9
|
+
raise ArgumentError, 'The Receiver values must be a nil or a Hash.'\
|
|
10
|
+
unless values.nil? || ( values.respond_to?( :[] ) && values.respond_to?( :key? ) )
|
|
11
|
+
|
|
12
|
+
@values = {}
|
|
13
|
+
@schema = schema
|
|
14
|
+
@defaults = defaults
|
|
15
|
+
@defaults_assigned = {}
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
@converter = converter
|
|
18
|
+
|
|
19
|
+
@schema.each do | key, criteria |
|
|
20
|
+
name = criteria[ :as ] || key
|
|
21
|
+
if @defaults && criteria.key?( :default )
|
|
22
|
+
self.__send__( key, criteria[ :default ] )
|
|
23
|
+
@defaults_assigned[ key ] = true
|
|
24
|
+
end
|
|
25
|
+
self.__send__( key, values[ key ] ) if values && values.key?( key )
|
|
23
26
|
end
|
|
24
|
-
self.__send__( key, values[ key ] ) if values && values.key?( key )
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def empty?
|
|
30
|
-
@values.empty?
|
|
31
|
-
end
|
|
32
27
|
|
|
33
|
-
def to_h
|
|
34
|
-
recursive_to_h = ->( object ) do
|
|
35
|
-
case object
|
|
36
|
-
when ::NilClass
|
|
37
|
-
nil
|
|
38
|
-
when ::DynamicSchema::Receiver::Object
|
|
39
|
-
recursive_to_h.call( object.to_h )
|
|
40
|
-
when ::Hash
|
|
41
|
-
object.transform_values { | value | recursive_to_h.call( value ) }
|
|
42
|
-
when ::Array
|
|
43
|
-
object.map { | element | recursive_to_h.call( element ) }
|
|
44
|
-
else
|
|
45
|
-
object.respond_to?( :to_h ) ? object.to_h : object
|
|
46
|
-
end
|
|
47
28
|
end
|
|
48
29
|
|
|
49
|
-
|
|
50
|
-
|
|
30
|
+
def empty?
|
|
31
|
+
@values.empty?
|
|
32
|
+
end
|
|
51
33
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
34
|
+
def to_h
|
|
35
|
+
recursive_to_h = ->( object ) do
|
|
36
|
+
case object
|
|
37
|
+
when ::NilClass
|
|
38
|
+
nil
|
|
39
|
+
when ::DynamicSchema::Receiver::Object
|
|
40
|
+
recursive_to_h.call( object.to_h )
|
|
41
|
+
when ::Hash
|
|
42
|
+
object.transform_values { | value | recursive_to_h.call( value ) }
|
|
43
|
+
when ::Array
|
|
44
|
+
object.map { | element | recursive_to_h.call( element ) }
|
|
45
|
+
else
|
|
46
|
+
object.respond_to?( :to_h ) ? object.to_h : object
|
|
47
|
+
end
|
|
48
|
+
end
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
klass == ::DynamicSchema::Receiver::Base ||
|
|
59
|
-
klass == ::BasicObject
|
|
60
|
-
end
|
|
50
|
+
recursive_to_h.call( @values )
|
|
51
|
+
end
|
|
61
52
|
|
|
62
|
-
|
|
53
|
+
def class
|
|
54
|
+
::DynamicSchema::Receiver::Object
|
|
55
|
+
end
|
|
63
56
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
def is_a?( klass )
|
|
58
|
+
klass == ::DynamicSchema::Receiver::Object ||
|
|
59
|
+
klass == ::DynamicSchema::Receiver::Base ||
|
|
60
|
+
klass == ::BasicObject
|
|
61
|
+
end
|
|
69
62
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
63
|
+
alias :kind_of? :is_a?
|
|
64
|
+
|
|
65
|
+
def method_missing( method, *args, &block )
|
|
66
|
+
if @schema.key?( method )
|
|
67
|
+
criteria = @schema[ method ]
|
|
68
|
+
name = criteria[ :as ] || method
|
|
69
|
+
value = @values[ name ]
|
|
70
|
+
|
|
71
|
+
type = criteria[ :type ]
|
|
72
|
+
has_multiple_types = type.is_a?( ::Array ) && criteria[ :compiler ]
|
|
73
|
+
|
|
74
|
+
unless criteria[ :array ]
|
|
75
|
+
if has_multiple_types
|
|
76
|
+
value = __types( method, args, value: value, criteria: criteria, &block )
|
|
77
|
+
elsif type == ::Object
|
|
78
|
+
value = __object( method, args, value: value, criteria: criteria, &block )
|
|
79
|
+
else
|
|
80
|
+
value = __value( method, args, value: value, criteria: criteria, &block )
|
|
81
|
+
end
|
|
80
82
|
else
|
|
81
|
-
value =
|
|
83
|
+
value = @defaults_assigned[ method ] ? ::Array.new : value || ::Array.new
|
|
84
|
+
if has_multiple_types
|
|
85
|
+
value = __types_array( method, args, value: value, criteria: criteria, &block )
|
|
86
|
+
elsif type == ::Object
|
|
87
|
+
value = __object_array( method, args, value: value, criteria: criteria, &block )
|
|
88
|
+
else
|
|
89
|
+
value = __values_array( method, args, value: value, criteria: criteria, &block )
|
|
90
|
+
end
|
|
82
91
|
end
|
|
83
|
-
end
|
|
84
92
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
@defaults_assigned[ method ] = false
|
|
94
|
+
@values[ name ] = value
|
|
95
|
+
else
|
|
96
|
+
::Kernel.raise ::NoMethodError,
|
|
97
|
+
"There is no schema value or object '#{ method }' defined in this scope which includes: " \
|
|
98
|
+
"#{ @schema.keys.join( ', ' ) }."
|
|
99
|
+
end
|
|
91
100
|
end
|
|
92
|
-
end
|
|
93
101
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
102
|
+
def respond_to?( method, include_private = false )
|
|
103
|
+
@schema.key?( method ) || self.class.instance_methods.include?( method )
|
|
104
|
+
end
|
|
97
105
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
def respond_to_missing?( method, include_private = false )
|
|
107
|
+
@schema.key?( method ) || self.class.instance_methods.include?( method )
|
|
108
|
+
end
|
|
101
109
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
110
|
+
protected
|
|
111
|
+
|
|
112
|
+
def __process_arguments( name, arguments, required_arguments: )
|
|
113
|
+
count = arguments.count
|
|
114
|
+
required_arguments = [ required_arguments ].flatten if required_arguments
|
|
115
|
+
required_count = required_arguments&.length || 0
|
|
116
|
+
::Kernel.raise ::ArgumentError,
|
|
117
|
+
"The attribute '#{ name }' requires #{ required_count } arguments " \
|
|
118
|
+
"(#{ required_arguments.join( ', ' ) }) but #{ count } was given." \
|
|
119
|
+
if count < required_count
|
|
120
|
+
::Kernel.raise ::ArgumentError,
|
|
121
|
+
"The attribute '#{ name }' should have at most #{ required_count + 1 } arguments but " \
|
|
122
|
+
"#{ count } was given." \
|
|
123
|
+
if count > required_count + 1
|
|
124
|
+
|
|
125
|
+
result = {}
|
|
126
|
+
|
|
127
|
+
required_arguments&.each_with_index do | name, index |
|
|
128
|
+
result[ name.to_sym ] = arguments[ index ]
|
|
129
|
+
end
|
|
130
|
+
arguments.slice!( 0, required_arguments.length ) if required_arguments
|
|
131
|
+
|
|
132
|
+
last = arguments.last
|
|
133
|
+
case last
|
|
134
|
+
when ::Hash
|
|
135
|
+
result.merge( last )
|
|
136
|
+
when ::Array
|
|
137
|
+
last.map { | v | result.merge( v ) }
|
|
138
|
+
else
|
|
139
|
+
result
|
|
140
|
+
end
|
|
132
141
|
end
|
|
133
|
-
end
|
|
134
142
|
|
|
135
|
-
|
|
136
|
-
|
|
143
|
+
def __coerce_value( types, value )
|
|
144
|
+
return value unless types && !value.nil?
|
|
137
145
|
|
|
138
|
-
|
|
139
|
-
|
|
146
|
+
types = ::Kernel.method( :Array ).call( types )
|
|
147
|
+
result = nil
|
|
140
148
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
if value.respond_to?( :is_a? )
|
|
150
|
+
types.each do | type |
|
|
151
|
+
result = value.is_a?( type ) ? value : nil
|
|
152
|
+
break unless result.nil?
|
|
153
|
+
end
|
|
145
154
|
end
|
|
146
|
-
end
|
|
147
155
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
156
|
+
if result.nil?
|
|
157
|
+
types.each do | type |
|
|
158
|
+
result = @converter.convert( value, to: type ) rescue nil
|
|
159
|
+
break unless result.nil?
|
|
160
|
+
end
|
|
152
161
|
end
|
|
153
|
-
end
|
|
154
162
|
|
|
155
|
-
|
|
156
|
-
|
|
163
|
+
result
|
|
164
|
+
end
|
|
157
165
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
+
def __value( method, arguments, value:, criteria:, &block )
|
|
167
|
+
value = arguments.first
|
|
168
|
+
new_value = criteria[ :type ] ? __coerce_value( criteria[ :type ], value ) : value
|
|
169
|
+
new_value = new_value.nil? ? value : new_value
|
|
170
|
+
new_value = block ?
|
|
171
|
+
__value_block( method, value: new_value, criteria: criteria, &block ) :
|
|
172
|
+
new_value
|
|
173
|
+
__normalize( new_value, criteria )
|
|
174
|
+
end
|
|
166
175
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
def __values_array( method, arguments, value:, criteria:, &block )
|
|
177
|
+
values = [ arguments.first ].flatten
|
|
178
|
+
if type = criteria[ :type ]
|
|
179
|
+
values = values.map do | v |
|
|
180
|
+
new_value = __coerce_value( type, v )
|
|
181
|
+
new_value.nil? ? v : new_value
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
if block
|
|
185
|
+
values = values.map do | value |
|
|
186
|
+
__value_block( method, value: value, criteria: criteria, &block )
|
|
187
|
+
end
|
|
178
188
|
end
|
|
189
|
+
values = values.map { | v | __normalize( v, criteria ) }
|
|
190
|
+
value.concat( values )
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def __object( method, arguments, value:, criteria:, &block )
|
|
194
|
+
attributes = __process_arguments(
|
|
195
|
+
method, arguments,
|
|
196
|
+
required_arguments: criteria[ :arguments ]
|
|
197
|
+
)
|
|
198
|
+
if value.nil? || attributes&.any?
|
|
199
|
+
value =
|
|
200
|
+
Receiver::Object.new(
|
|
201
|
+
attributes,
|
|
202
|
+
converter: @converter,
|
|
203
|
+
schema: criteria[ :schema ] ||= criteria[ :compiler ].compiled,
|
|
204
|
+
defaults: @defaults
|
|
205
|
+
)
|
|
206
|
+
end
|
|
207
|
+
value.instance_eval( &block ) if block
|
|
208
|
+
__normalize( value, criteria )
|
|
179
209
|
end
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
converter: @converter,
|
|
193
|
-
schema: criteria[ :schema ] ||= criteria[ :compiler ].compiled
|
|
210
|
+
|
|
211
|
+
def __object_array( method, arguments, value:, criteria:, &block )
|
|
212
|
+
attributes = __process_arguments(
|
|
213
|
+
method, arguments,
|
|
214
|
+
required_arguments: criteria[ :arguments ]
|
|
215
|
+
)
|
|
216
|
+
value.concat( [ attributes ].flatten.map { | a |
|
|
217
|
+
receiver = Receiver::Object.new(
|
|
218
|
+
a,
|
|
219
|
+
converter: @converter,
|
|
220
|
+
schema: criteria[ :schema ] ||= criteria[ :compiler ].compiled,
|
|
221
|
+
defaults: @defaults
|
|
194
222
|
)
|
|
223
|
+
receiver.instance_eval( &block ) if block
|
|
224
|
+
__normalize( receiver, criteria )
|
|
225
|
+
} )
|
|
195
226
|
end
|
|
196
|
-
value.instance_eval( &block ) if block
|
|
197
|
-
value
|
|
198
|
-
end
|
|
199
227
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
228
|
+
def __types( method, arguments, value:, criteria:, &block )
|
|
229
|
+
argument = arguments.first
|
|
230
|
+
if block || argument.is_a?( ::Hash )
|
|
231
|
+
if block && !value.nil? && !value.is_a?( ::DynamicSchema::Receiver::Object )
|
|
232
|
+
value = nil
|
|
233
|
+
end
|
|
234
|
+
__object( method, arguments, value: value, criteria: criteria, &block )
|
|
235
|
+
else
|
|
236
|
+
scalar_criteria = criteria.merge( type: __non_object_types( criteria[ :type ] ) )
|
|
237
|
+
__value( method, arguments, value: value, criteria: scalar_criteria, &block )
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def __types_array( method, arguments, value:, criteria:, &block )
|
|
242
|
+
items = [ arguments.first ].flatten
|
|
243
|
+
if block
|
|
244
|
+
__object_array( method, arguments, value: value, criteria: criteria, &block )
|
|
245
|
+
else
|
|
246
|
+
items.each do | item |
|
|
247
|
+
if item.is_a?( ::Hash )
|
|
248
|
+
__object_array( method, [ item ], value: value, criteria: criteria )
|
|
249
|
+
else
|
|
250
|
+
scalar_criteria = criteria.merge( type: __non_object_types( criteria[ :type ] ) )
|
|
251
|
+
__values_array( method, [ item ], value: value, criteria: scalar_criteria )
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
value
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def __non_object_types( types )
|
|
259
|
+
types_array = types.is_a?( ::Array ) ? types : [ types ]
|
|
260
|
+
result = types_array.reject { | type | type == ::Object }
|
|
261
|
+
result.length == 1 ? result.first : result
|
|
262
|
+
end
|
|
215
263
|
|
|
216
|
-
|
|
217
|
-
if value.nil?
|
|
264
|
+
def __value_block( method, value:, criteria:, &block )
|
|
218
265
|
type = criteria[ :type ]
|
|
266
|
+
|
|
267
|
+
# if the value type is a Proc the block is the value
|
|
268
|
+
return block if type == ::Proc
|
|
219
269
|
|
|
220
|
-
if
|
|
221
|
-
if type.
|
|
222
|
-
type
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
270
|
+
if value.nil?
|
|
271
|
+
if type.is_a?( ::Array )
|
|
272
|
+
if type.length == 1
|
|
273
|
+
type = type.first
|
|
274
|
+
else
|
|
275
|
+
::Kernel.raise ::TypeError,
|
|
276
|
+
"An explicit value for '#{method}' is required when using a block " +
|
|
277
|
+
"because multiple types were specified."
|
|
278
|
+
end
|
|
227
279
|
end
|
|
228
|
-
end
|
|
229
280
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
281
|
+
case type
|
|
282
|
+
when ::Class
|
|
283
|
+
begin
|
|
284
|
+
value = type.new
|
|
285
|
+
rescue => error
|
|
286
|
+
::Kernel.raise ::TypeError,
|
|
287
|
+
"An explicit value for '#{method}' is required because '#{type}' " +
|
|
288
|
+
"could not be constructed: #{error.message}."
|
|
289
|
+
end
|
|
290
|
+
else
|
|
235
291
|
::Kernel.raise ::TypeError,
|
|
236
|
-
"An explicit value for '#{method}' is required because '#{type}' " +
|
|
237
|
-
"
|
|
292
|
+
"An explicit value for '#{method}' is required because '#{type}' is " +
|
|
293
|
+
"not a Class."
|
|
238
294
|
end
|
|
239
|
-
|
|
240
|
-
::Kernel.raise ::TypeError,
|
|
241
|
-
"An explicit value for '#{method}' is required because '#{type}' is " +
|
|
242
|
-
"not a Class."
|
|
295
|
+
|
|
243
296
|
end
|
|
297
|
+
::DynamicSchema::Receiver::Value.new( value ).instance_eval( &block )
|
|
298
|
+
value
|
|
299
|
+
end
|
|
244
300
|
|
|
301
|
+
def __normalize( value, criteria )
|
|
302
|
+
normalize = criteria[ :normalize ]
|
|
303
|
+
return value unless normalize && !value.nil?
|
|
304
|
+
normalize.call( value )
|
|
245
305
|
end
|
|
246
|
-
::DynamicSchema::Receiver::Value.new( value ).instance_eval( &block )
|
|
247
|
-
value
|
|
248
|
-
end
|
|
249
306
|
|
|
250
|
-
|
|
307
|
+
end
|
|
251
308
|
end
|
|
252
309
|
end
|