adaptiveconfiguration 1.0.0.beta04 → 1.0.0.beta07
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bddcf16845596d56add432ccd7aefe97a9764b1e99a644b9947427ef49819a2
|
4
|
+
data.tar.gz: bf5c024845348795609942aace53b06da90b5f0cfa8e531bf26569554e57c2cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4d2af44187899024e1c2a4edbb7e811a613b438ee87a63badc87a3574a8740b6217289463cdc286d0312f4e353958c00a89c69b4dab9e6f93221446dc7ed1f8
|
7
|
+
data.tar.gz: 7a247388fdad9d6c99e2c2f6dd78e8490a0cfe5ce8172fb0388c25e19f5e2e4ef579c5613b614c29ce8cb56bc231f605473a064594c110307adc282722f2f924
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require_relative 'group_builder'
|
2
|
-
require_relative '
|
2
|
+
require_relative 'scaffold'
|
3
3
|
|
4
4
|
# types must be included to support conversation
|
5
5
|
require 'time'
|
@@ -16,6 +16,7 @@ module AdaptiveConfiguration
|
|
16
16
|
Time => ->( v ) { v.respond_to?( :to_time ) ? v.to_time : Time.parse( v.to_s ) },
|
17
17
|
URI => ->( v ) { URI.parse( v.to_s ) },
|
18
18
|
String => ->( v ) { String( v ) },
|
19
|
+
Symbol => ->( v ) { v.respond_to?( :to_sym ) ? v.to_sym : nil },
|
19
20
|
Rational => ->( v ) { Rational( v ) },
|
20
21
|
Float => ->( v ) { Float( v ) },
|
21
22
|
Integer => ->( v ) { Integer( v ) },
|
@@ -48,19 +49,123 @@ module AdaptiveConfiguration
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def build( values = nil, &block )
|
51
|
-
|
52
|
+
scaffold = AdaptiveConfiguration::Scaffold.new(
|
52
53
|
values,
|
53
54
|
converters: @converters,
|
54
55
|
definitions: @definitions
|
55
56
|
)
|
56
|
-
|
57
|
-
|
57
|
+
scaffold.instance_eval( &block ) if block
|
58
|
+
scaffold.to_h
|
58
59
|
end
|
59
60
|
|
60
61
|
def build!( values = nil, &block )
|
61
|
-
|
62
|
-
|
63
|
-
|
62
|
+
scaffold = AdaptiveConfiguration::Scaffold.new(
|
63
|
+
values,
|
64
|
+
converters: @converters,
|
65
|
+
definitions: @definitions
|
66
|
+
)
|
67
|
+
scaffold.instance_eval( &block ) if block
|
68
|
+
result = scaffold.to_h
|
69
|
+
validate!( result )
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate!( values )
|
74
|
+
traverse_and_validate_values( values, definitions: @definitions ) { | error |
|
75
|
+
raise error
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def validate( values )
|
80
|
+
errors = []
|
81
|
+
traverse_and_validate_values( values, definitions: @definitions ) { | error |
|
82
|
+
errors << error
|
83
|
+
}
|
84
|
+
errors
|
85
|
+
end
|
86
|
+
|
87
|
+
def valid?( values )
|
88
|
+
traverse_and_validate_values( values, definitions: @definitions ) {
|
89
|
+
return false
|
90
|
+
}
|
91
|
+
return true
|
92
|
+
end
|
93
|
+
|
94
|
+
protected
|
95
|
+
|
96
|
+
def value_matches_types?( value, types )
|
97
|
+
type_match = false
|
98
|
+
Array( types ).each do | type |
|
99
|
+
type_match = value.is_a?( type )
|
100
|
+
break if type_match
|
101
|
+
end
|
102
|
+
type_match
|
103
|
+
end
|
104
|
+
|
105
|
+
def traverse_and_validate_values( values, definitions:, path: nil, options: nil, &block )
|
106
|
+
|
107
|
+
path.chomp( '/' ) if path
|
108
|
+
unless values.is_a?( Hash )
|
109
|
+
# TODO: raise error
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
113
|
+
definitions.each do | key, definition |
|
114
|
+
|
115
|
+
name = definition[ :as ] || key
|
116
|
+
value = values[ name ]
|
117
|
+
|
118
|
+
if definition[ :required ] &&
|
119
|
+
( !value || ( value.respond_to?( :empty ) && value.empty? ) )
|
120
|
+
block.call( RequirementUnmetError.new( path: path, key: key ) )
|
121
|
+
elsif !definition[ :default_assigned ] && !value.nil?
|
122
|
+
unless definition[ :array ]
|
123
|
+
if definition[ :type ] == :group
|
124
|
+
traverse_and_validate_values(
|
125
|
+
values[ name ],
|
126
|
+
definitions: definition[ :definitions ],
|
127
|
+
path: "#{ ( path || '' ) + ( path ? '/' : '' ) + key.to_s }",
|
128
|
+
&block
|
129
|
+
)
|
130
|
+
else
|
131
|
+
if definition[ :type ] && value && !definition[ :default_assigned ]
|
132
|
+
unless value_matches_types?( value, definition[ :type ] )
|
133
|
+
block.call( IncompatibleTypeError.new(
|
134
|
+
path: path, key: key, type: definition[ :type ], value: value
|
135
|
+
) )
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
else
|
140
|
+
if definition[ :type ] == :group
|
141
|
+
groups = Array( value )
|
142
|
+
groups.each do | group |
|
143
|
+
traverse_and_validate_values(
|
144
|
+
group,
|
145
|
+
definitions: definition[ :definitions ],
|
146
|
+
path: "#{ ( path || '' ) + ( path ? '/' : '' ) + key.to_s }",
|
147
|
+
&block
|
148
|
+
)
|
149
|
+
end
|
150
|
+
else
|
151
|
+
if definition[ :type ] && !definition[ :default_assigned ]
|
152
|
+
value_array = Array( value )
|
153
|
+
value_array.each do | v |
|
154
|
+
unless value_matches_types?( v, definition[ :type ] )
|
155
|
+
block.call( IncompatibleTypeError.new(
|
156
|
+
path: path, key: key, type: definition[ :type ], value: v
|
157
|
+
) )
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
nil
|
168
|
+
|
64
169
|
end
|
65
170
|
|
66
171
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative '
|
1
|
+
require_relative 'scaffold'
|
2
2
|
|
3
3
|
module AdaptiveConfiguration
|
4
4
|
class GroupBuilder
|
@@ -14,8 +14,8 @@ module AdaptiveConfiguration
|
|
14
14
|
name = name.to_sym
|
15
15
|
options = nil
|
16
16
|
|
17
|
-
raise NameError, "The
|
18
|
-
if AdaptiveConfiguration::
|
17
|
+
raise NameError, "The name '#{name}' is reserved and cannot be used for parameters." \
|
18
|
+
if AdaptiveConfiguration::Scaffold.instance_methods.include?( name )
|
19
19
|
|
20
20
|
if args.first.is_a?( ::Hash )
|
21
21
|
# when called without type: parameter :stream, as: :streams
|
@@ -30,12 +30,17 @@ module AdaptiveConfiguration
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def group( name, options = {}, &block )
|
33
|
+
|
34
|
+
raise NameError, "The name '#{name}' is reserved and cannot be used for parameters." \
|
35
|
+
if AdaptiveConfiguration::Scaffold.instance_methods.include?( name )
|
36
|
+
|
33
37
|
builder = GroupBuilder.new
|
34
38
|
builder.instance_eval( &block ) if block
|
35
39
|
@definitions[ name ] = options.merge( {
|
36
40
|
type: :group,
|
37
41
|
definitions: builder.definitions
|
38
42
|
} )
|
43
|
+
|
39
44
|
end
|
40
45
|
|
41
46
|
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
module AdaptiveConfiguration
|
2
|
+
class Scaffold < BasicObject
|
3
|
+
|
4
|
+
include ::PP::ObjectMixin if defined?( ::PP )
|
5
|
+
|
6
|
+
attr_reader :errors
|
7
|
+
|
8
|
+
def initialize( values = nil, definitions:, converters: )
|
9
|
+
raise ArgumentError, 'The Scaffold initialitization attributes must be a Hash pr Hash-like.'\
|
10
|
+
unless values.nil? || ( values.respond_to?( :[] ) && values.respond_to?( :key? ) )
|
11
|
+
|
12
|
+
@converters = converters&.dup
|
13
|
+
@definitions = definitions&.dup
|
14
|
+
@values = {}
|
15
|
+
@errors = []
|
16
|
+
|
17
|
+
@definitions.each do | key, definition |
|
18
|
+
name = definition[ :as ] || key
|
19
|
+
if definition.key?( :default )
|
20
|
+
self.__send__( key, definition[ :default ] )
|
21
|
+
# note: this is needed to know when an array parameter which was initially assigned
|
22
|
+
# to a default should be replaced rather than appended
|
23
|
+
definition[ :default_assigned ] = true
|
24
|
+
end
|
25
|
+
self.__send__( key, values[ key ] ) if values && values.key?( key )
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def nil?
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
def empty?
|
35
|
+
@values.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_h
|
39
|
+
recursive_to_h = ->( object ) do
|
40
|
+
case object
|
41
|
+
when ::NilClass
|
42
|
+
nil
|
43
|
+
when ::AdaptiveConfiguration::Scaffold
|
44
|
+
recursive_to_h.call( object.to_h )
|
45
|
+
when ::Hash
|
46
|
+
object.transform_values { | value | recursive_to_h.call( value ) }
|
47
|
+
when ::Array
|
48
|
+
object.map { | element | recursive_to_h.call( element ) }
|
49
|
+
else
|
50
|
+
object.respond_to?( :to_h ) ? object.to_h : object
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
recursive_to_h.call( @values )
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
inspect
|
59
|
+
end
|
60
|
+
|
61
|
+
def inspect
|
62
|
+
{ values: @values, definitions: @definitions }.inspect
|
63
|
+
end
|
64
|
+
|
65
|
+
if defined?( ::PP )
|
66
|
+
def pretty_print( pp )
|
67
|
+
pp.pp( { values: @values, definitions: @definitions } )
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def class
|
72
|
+
::AdaptiveConfiguration::Scaffold
|
73
|
+
end
|
74
|
+
|
75
|
+
def is_a?( klass )
|
76
|
+
klass == ::AdaptiveConfiguration::Scaffold || klass == ::BasicObject
|
77
|
+
end
|
78
|
+
|
79
|
+
alias :kind_of? :is_a?
|
80
|
+
|
81
|
+
def method_missing( method, *args, &block )
|
82
|
+
|
83
|
+
if @definitions.key?( method )
|
84
|
+
definition = @definitions[ method ]
|
85
|
+
name = definition[ :as ] || method
|
86
|
+
|
87
|
+
unless definition[ :array ]
|
88
|
+
if definition[ :type ] == :group
|
89
|
+
value = args.first
|
90
|
+
context = @values[ name ]
|
91
|
+
if context.nil? || value
|
92
|
+
context =
|
93
|
+
Scaffold.new(
|
94
|
+
value,
|
95
|
+
converters: @converters,
|
96
|
+
definitions: definition[ :definitions ]
|
97
|
+
)
|
98
|
+
end
|
99
|
+
context.instance_eval( &block ) if block
|
100
|
+
@values[ name ] = context
|
101
|
+
else
|
102
|
+
value = args.first
|
103
|
+
new_value = definition[ :type ] ? __coerce_value( definition[ :type ], value ) : value
|
104
|
+
@values[ name ] = new_value.nil? ? value : new_value
|
105
|
+
end
|
106
|
+
else
|
107
|
+
@values[ name ] = definition[ :default_assigned ] ?
|
108
|
+
::Array.new :
|
109
|
+
@values[ name ] || ::Array.new
|
110
|
+
if definition[ :type ] == :group
|
111
|
+
values = [ args.first ].flatten
|
112
|
+
values = values.map do | v |
|
113
|
+
context = Scaffold.new(
|
114
|
+
v,
|
115
|
+
converters: @converters,
|
116
|
+
definitions: definition[ :definitions ]
|
117
|
+
)
|
118
|
+
context.instance_eval( &block ) if block
|
119
|
+
context
|
120
|
+
end
|
121
|
+
@values[ name ].concat( values )
|
122
|
+
else
|
123
|
+
values = ::Kernel.method( :Array ).call( args.first )
|
124
|
+
if type = definition[ :type ]
|
125
|
+
values = values.map do | v |
|
126
|
+
new_value = __coerce_value( type, v )
|
127
|
+
new_value.nil? ? v : new_value
|
128
|
+
end
|
129
|
+
end
|
130
|
+
@values[ name ].concat( values )
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
definition[ :default_assigned ] = false
|
135
|
+
@values[ name ]
|
136
|
+
else
|
137
|
+
super
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
def respond_to?( method, include_private = false )
|
143
|
+
@definitions.key?( method ) || self.class.instance_methods.include?( method )
|
144
|
+
end
|
145
|
+
|
146
|
+
def respond_to_missing?( method, include_private = false )
|
147
|
+
@definitions.key?( method ) || self.class.instance_methods.include?( method )
|
148
|
+
end
|
149
|
+
|
150
|
+
protected
|
151
|
+
|
152
|
+
def __coerce_value( types, value )
|
153
|
+
|
154
|
+
return value unless types && !value.nil?
|
155
|
+
|
156
|
+
types = ::Kernel.method( :Array ).call( types )
|
157
|
+
result = nil
|
158
|
+
|
159
|
+
if value.respond_to?( :is_a? )
|
160
|
+
types.each do | type |
|
161
|
+
result = value.is_a?( type ) ? value : nil
|
162
|
+
break unless result.nil?
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
if result.nil?
|
167
|
+
types.each do | type |
|
168
|
+
result = @converters[ type ].call( value ) rescue nil
|
169
|
+
break unless result.nil?
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
result
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: adaptiveconfiguration
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta07
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kristoph Cichocki-Romanov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -57,9 +57,9 @@ files:
|
|
57
57
|
- lib/adaptive_configuration.rb
|
58
58
|
- lib/adaptive_configuration/builder.rb
|
59
59
|
- lib/adaptive_configuration/configurable.rb
|
60
|
-
- lib/adaptive_configuration/context.rb
|
61
60
|
- lib/adaptive_configuration/errors.rb
|
62
61
|
- lib/adaptive_configuration/group_builder.rb
|
62
|
+
- lib/adaptive_configuration/scaffold.rb
|
63
63
|
homepage: https://github.com/EndlessInternational/adaptive_configuration
|
64
64
|
licenses:
|
65
65
|
- MIT
|
@@ -1,271 +0,0 @@
|
|
1
|
-
module AdaptiveConfiguration
|
2
|
-
class Context < BasicObject
|
3
|
-
|
4
|
-
attr_reader :errors
|
5
|
-
|
6
|
-
def initialize( values = nil, definitions:, converters: )
|
7
|
-
|
8
|
-
values = values ? values.transform_keys( &:to_sym ) : {}
|
9
|
-
|
10
|
-
@converters = converters&.dup
|
11
|
-
@definitions = definitions&.dup
|
12
|
-
@values = {}
|
13
|
-
@errors = []
|
14
|
-
|
15
|
-
@definitions.each do | key, definition |
|
16
|
-
name = definition[ :as ] || key
|
17
|
-
if definition[ :type ] == :group
|
18
|
-
context = Context.new(
|
19
|
-
values[ key ] || {},
|
20
|
-
converters: @converters, definitions: definition[ :definitions ],
|
21
|
-
)
|
22
|
-
@values[ name ] = context unless context.empty?
|
23
|
-
elsif definition.key?( :default )
|
24
|
-
@values[ name ] = definition[ :array ] ?
|
25
|
-
::Kernel.method( :Array ).call( definition[ :default ] ) :
|
26
|
-
definition[ :default ]
|
27
|
-
# note: this is needed to know when an array paramter which was initially assigned
|
28
|
-
# to a default should be replaced rather than appended
|
29
|
-
definition[ :default_assigned ] = true
|
30
|
-
end
|
31
|
-
self.__send__( key, values[ key ] ) if values[ key ]
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def nil?
|
37
|
-
false
|
38
|
-
end
|
39
|
-
|
40
|
-
def empty?
|
41
|
-
@values.empty?
|
42
|
-
end
|
43
|
-
|
44
|
-
def []( key )
|
45
|
-
@values[ key ]
|
46
|
-
end
|
47
|
-
|
48
|
-
def []=( key, value )
|
49
|
-
@values[ key ] = value
|
50
|
-
end
|
51
|
-
|
52
|
-
def each( &block )
|
53
|
-
@values.each( &block )
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
def merge( hash )
|
58
|
-
self.to_h.merge( hash )
|
59
|
-
end
|
60
|
-
|
61
|
-
def valid?
|
62
|
-
__validate_values
|
63
|
-
@errors.empty?
|
64
|
-
end
|
65
|
-
|
66
|
-
def validate!
|
67
|
-
__validate_values { | error | ::Kernel.raise error }
|
68
|
-
end
|
69
|
-
|
70
|
-
def to_h
|
71
|
-
recursive_to_h = ->( object ) do
|
72
|
-
case object
|
73
|
-
when ::AdaptiveConfiguration::Context
|
74
|
-
recursive_to_h.call( object.to_h )
|
75
|
-
when ::Hash
|
76
|
-
object.transform_values { | value | recursive_to_h.call( value ) }
|
77
|
-
when ::Array
|
78
|
-
object.map { | element | recursive_to_h.call( element ) }
|
79
|
-
else
|
80
|
-
object.respond_to?( :to_h ) ? object.to_h : object
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
recursive_to_h.call( @values )
|
85
|
-
end
|
86
|
-
|
87
|
-
def to_s
|
88
|
-
inspect
|
89
|
-
end
|
90
|
-
|
91
|
-
def to_yaml
|
92
|
-
self.to_h.to_yaml
|
93
|
-
end
|
94
|
-
|
95
|
-
def inspect
|
96
|
-
@values.inspect
|
97
|
-
end
|
98
|
-
|
99
|
-
def class
|
100
|
-
::AdaptiveConfiguration::Context
|
101
|
-
end
|
102
|
-
|
103
|
-
def is_a?( klass )
|
104
|
-
klass == ::AdaptiveConfiguration::Context || klass == ::BasicObject
|
105
|
-
end
|
106
|
-
|
107
|
-
alias :kind_of? :is_a?
|
108
|
-
|
109
|
-
def method_missing( method, *args, &block )
|
110
|
-
|
111
|
-
if @definitions.key?( method )
|
112
|
-
|
113
|
-
definition = @definitions[ method ]
|
114
|
-
name = definition[ :as ] || method
|
115
|
-
|
116
|
-
unless definition[ :array ]
|
117
|
-
if definition[ :type ] == :group
|
118
|
-
context =
|
119
|
-
@values[ name ] || Context.new(
|
120
|
-
args.first,
|
121
|
-
converters: @converters,
|
122
|
-
definitions: definition[ :definitions ]
|
123
|
-
)
|
124
|
-
context.instance_eval( &block ) if block
|
125
|
-
@values[ name ] = context
|
126
|
-
else
|
127
|
-
value = args.first
|
128
|
-
new_value = definition[ :type ] ? __coerce_value( definition[ :type ], value ) : value
|
129
|
-
@values[ name ] = new_value.nil? ? value : new_value
|
130
|
-
end
|
131
|
-
else
|
132
|
-
@values[ name ] = definition[ :default_assigned ] ?
|
133
|
-
::Array.new :
|
134
|
-
@values[ name ] || ::Array.new
|
135
|
-
if definition[ :type ] == :group
|
136
|
-
context = Context.new(
|
137
|
-
args.first,
|
138
|
-
converters: @converters,
|
139
|
-
definitions: definition[ :definitions ]
|
140
|
-
)
|
141
|
-
context.instance_eval( &block ) if block
|
142
|
-
@values[ name ] << context
|
143
|
-
else
|
144
|
-
values = ::Kernel.method( :Array ).call( args.first )
|
145
|
-
if type = definition[ :type ]
|
146
|
-
values = values.map do | v |
|
147
|
-
new_value = __coerce_value( type, v )
|
148
|
-
new_value.nil? ? v : new_value
|
149
|
-
end
|
150
|
-
end
|
151
|
-
@values[ name ].concat( values )
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
definition[ :default_assigned ] = false
|
156
|
-
@values[ name ]
|
157
|
-
|
158
|
-
else
|
159
|
-
super
|
160
|
-
end
|
161
|
-
|
162
|
-
end
|
163
|
-
|
164
|
-
def respond_to?( method, include_private = false )
|
165
|
-
@definitions.key?( method ) || self.class.instance_methods.include?( method )
|
166
|
-
end
|
167
|
-
|
168
|
-
def respond_to_missing?( method, include_private = false )
|
169
|
-
@definitions.key?( method ) || self.class.instance_methods.include?( method )
|
170
|
-
end
|
171
|
-
|
172
|
-
protected
|
173
|
-
|
174
|
-
def __coerce_value( types, value )
|
175
|
-
|
176
|
-
return value unless types && !value.nil?
|
177
|
-
|
178
|
-
types = ::Kernel.method( :Array ).call( types )
|
179
|
-
result = nil
|
180
|
-
|
181
|
-
if value.respond_to?( :is_a? )
|
182
|
-
types.each do | type |
|
183
|
-
result = value.is_a?( type ) ? value : nil
|
184
|
-
break unless result.nil?
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
if result.nil?
|
189
|
-
types.each do | type |
|
190
|
-
result = @converters[ type ].call( value ) rescue nil
|
191
|
-
break unless result.nil?
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
result
|
196
|
-
end
|
197
|
-
|
198
|
-
def __validate_values( path = nil, &block )
|
199
|
-
|
200
|
-
path.chomp( '/' ) if path
|
201
|
-
@errors = []
|
202
|
-
|
203
|
-
is_of_matching_types = ::Proc.new do | value, types |
|
204
|
-
type_match = false
|
205
|
-
::Kernel.method( :Array ).call( types ).each do | type |
|
206
|
-
type_match = value.is_a?( type )
|
207
|
-
break if type_match
|
208
|
-
end
|
209
|
-
type_match
|
210
|
-
end
|
211
|
-
|
212
|
-
@definitions.each do | key, definition |
|
213
|
-
|
214
|
-
name = definition[ :as ] || key
|
215
|
-
value = @values[ name ]
|
216
|
-
|
217
|
-
if definition[ :required ] &&
|
218
|
-
( !value || ( value.respond_to?( :empty ) && value.empty? ) )
|
219
|
-
|
220
|
-
error = RequirementUnmetError.new( path: path, key: key )
|
221
|
-
block.call( error ) if block
|
222
|
-
@errors << error
|
223
|
-
|
224
|
-
elsif !definition[ :default_assigned ] && !value.nil?
|
225
|
-
|
226
|
-
unless definition[ :array ]
|
227
|
-
|
228
|
-
if definition[ :type ] == :group
|
229
|
-
value.__validate_values( "#{ ( path || '' ) + ( path ? '/' : '' ) + key.to_s }", &block )
|
230
|
-
@errors.concat( value.errors )
|
231
|
-
else
|
232
|
-
if definition[ :type ] && value && !definition[ :default_assigned ]
|
233
|
-
unless is_of_matching_types.call( value, definition[ :type ] )
|
234
|
-
error = IncompatibleTypeError.new(
|
235
|
-
path: path, key: key, type: definition[ :type ], value: value
|
236
|
-
)
|
237
|
-
block.call( error ) if block
|
238
|
-
@errors << error
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
else
|
244
|
-
|
245
|
-
if definition[ :type ] == :group
|
246
|
-
groups.each do | group |
|
247
|
-
group.__validate_values( "#{ ( path || '' ) + ( path ? '/' : '' ) + key.to_s }", &block )
|
248
|
-
@errors.concat( group.errors )
|
249
|
-
end
|
250
|
-
else
|
251
|
-
if definition[ :type ] && !definition[ :default_assigned ]
|
252
|
-
values = ::Kernel.method( :Array ).call( value )
|
253
|
-
values.each do | v |
|
254
|
-
unless is_of_matching_types.call( v, definition[ :type ] )
|
255
|
-
error = IncompatibleTypeError.new(
|
256
|
-
path: path, key: key, type: definition[ :type ], value: v
|
257
|
-
)
|
258
|
-
block.call( error ) if block
|
259
|
-
@errors << error
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
end
|
271
|
-
end
|