adaptiveconfiguration 1.0.0.beta01 → 1.0.0.beta02
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: 1c9efb51c751d9e2d5ed9f13cde645e6ad67eb33e657bb5a9942d8bc32ec09da
|
4
|
+
data.tar.gz: 4bb48b03dcecf0ccc32a4a5c107ea149cf006d1d7bf7d9d10fec7e585eb00d6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dadebc70156e871f0986e1858080de3c67e411b3a39dae3328962642d39157be221615b9811d7170e6f3c8fbc2f198d4037a14f109015b8cfc17cd6e139c69bf
|
7
|
+
data.tar.gz: 501f930713ec9f0ce6396d5bcb308065c3448b34f845225c20c57e6152306ba7a930a7a67868616394fd0f620d36e988e454aa4d7a89fce2ac88c1e383bebe70
|
@@ -11,14 +11,14 @@ module AdaptiveConfiguration
|
|
11
11
|
|
12
12
|
DEFAULT_CONVERTERS = {
|
13
13
|
|
14
|
+
Array => ->( v ) { Array( v ) },
|
14
15
|
Date => ->( v ) { v.respond_to?( :to_date ) ? v.to_date : Date.parse( v.to_s ) },
|
15
16
|
Time => ->( v ) { v.respond_to?( :to_time ) ? v.to_time : Time.parse( v.to_s ) },
|
16
17
|
URI => ->( v ) { URI.parse( v.to_s ) },
|
17
18
|
String => ->( v ) { String( v ) },
|
18
|
-
Integer => ->( v ) { Integer( v ) },
|
19
|
-
Float => ->( v ) { Float( v ) },
|
20
19
|
Rational => ->( v ) { Rational( v ) },
|
21
|
-
|
20
|
+
Float => ->( v ) { Float( v ) },
|
21
|
+
Integer => ->( v ) { Integer( v ) },
|
22
22
|
TrueClass => ->( v ) {
|
23
23
|
case v
|
24
24
|
when Numeric
|
@@ -47,7 +47,7 @@ module AdaptiveConfiguration
|
|
47
47
|
@converters[ klass ] = block
|
48
48
|
end
|
49
49
|
|
50
|
-
def build
|
50
|
+
def build( values = nil, &block )
|
51
51
|
context = AdaptiveConfiguration::Context.new(
|
52
52
|
values,
|
53
53
|
converters: @converters,
|
@@ -57,5 +57,11 @@ module AdaptiveConfiguration
|
|
57
57
|
context
|
58
58
|
end
|
59
59
|
|
60
|
+
def build!( values = nil, &block )
|
61
|
+
context = self.build( values, &block )
|
62
|
+
context.validate!
|
63
|
+
context
|
64
|
+
end
|
65
|
+
|
60
66
|
end
|
61
67
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module AdaptiveConfiguration
|
2
2
|
class Context < BasicObject
|
3
3
|
|
4
|
+
attr_reader :errors
|
5
|
+
|
4
6
|
def initialize( values = nil, definitions:, converters: )
|
5
7
|
|
6
8
|
values = values ? values.transform_keys( &:to_sym ) : {}
|
@@ -8,6 +10,7 @@ module AdaptiveConfiguration
|
|
8
10
|
@converters = converters&.dup
|
9
11
|
@definitions = definitions&.dup
|
10
12
|
@values = {}
|
13
|
+
@errors = []
|
11
14
|
|
12
15
|
@definitions.each do | key, definition |
|
13
16
|
name = definition[ :as ] || key
|
@@ -30,6 +33,14 @@ module AdaptiveConfiguration
|
|
30
33
|
|
31
34
|
end
|
32
35
|
|
36
|
+
def nil?
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
def empty?
|
41
|
+
@values.empty?
|
42
|
+
end
|
43
|
+
|
33
44
|
def []( key )
|
34
45
|
@values[ key ]
|
35
46
|
end
|
@@ -42,12 +53,18 @@ module AdaptiveConfiguration
|
|
42
53
|
@values.each( &block )
|
43
54
|
end
|
44
55
|
|
56
|
+
|
45
57
|
def merge( hash )
|
46
58
|
self.to_h.merge( hash )
|
47
59
|
end
|
48
60
|
|
49
|
-
def
|
50
|
-
|
61
|
+
def valid?
|
62
|
+
__validate_values
|
63
|
+
@errors.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate!
|
67
|
+
__validate_values { | error | ::Kernel.raise error }
|
51
68
|
end
|
52
69
|
|
53
70
|
def to_h
|
@@ -103,10 +120,10 @@ module AdaptiveConfiguration
|
|
103
120
|
Context.new( converters: @converters, definitions: definition[ :definitions ] )
|
104
121
|
context.instance_eval( &block ) if block
|
105
122
|
@values[ name ] = context
|
106
|
-
else
|
123
|
+
else
|
107
124
|
value = args.first
|
108
|
-
|
109
|
-
@values[ name ] = value
|
125
|
+
new_value = definition[ :type ] ? __coerce_value( definition[ :type ], value ) : value
|
126
|
+
@values[ name ] = new_value.nil? ? value : new_value
|
110
127
|
end
|
111
128
|
else
|
112
129
|
@values[ name ] = definition[ :default_assigned ] ?
|
@@ -119,7 +136,10 @@ module AdaptiveConfiguration
|
|
119
136
|
else
|
120
137
|
values = ::Kernel.method( :Array ).call( args.first )
|
121
138
|
if type = definition[ :type ]
|
122
|
-
values = values.map
|
139
|
+
values = values.map do | v |
|
140
|
+
new_value = __coerce_value( type, v )
|
141
|
+
new_value.nil? ? v : new_value
|
142
|
+
end
|
123
143
|
end
|
124
144
|
@values[ name ].concat( values )
|
125
145
|
end
|
@@ -142,29 +162,103 @@ module AdaptiveConfiguration
|
|
142
162
|
@definitions.key?( method ) || self.class.instance_methods.include?( method )
|
143
163
|
end
|
144
164
|
|
145
|
-
|
146
|
-
|
165
|
+
protected
|
166
|
+
|
167
|
+
def __coerce_value( types, value )
|
168
|
+
|
169
|
+
return value unless types && !value.nil?
|
147
170
|
|
148
|
-
types
|
171
|
+
types = ::Kernel.method( :Array ).call( types )
|
149
172
|
result = nil
|
150
173
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
174
|
+
if value.respond_to?( :is_a? )
|
175
|
+
types.each do | type |
|
176
|
+
result = value.is_a?( type ) ? value : nil
|
177
|
+
break unless result.nil?
|
178
|
+
end
|
156
179
|
end
|
157
180
|
|
158
181
|
if result.nil?
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
TEXT
|
182
|
+
types.each do | type |
|
183
|
+
result = @converters[ type ].call( value ) rescue nil
|
184
|
+
break unless result.nil?
|
185
|
+
end
|
164
186
|
end
|
165
187
|
|
166
188
|
result
|
167
189
|
end
|
168
190
|
|
191
|
+
def __validate_values( path = nil, &block )
|
192
|
+
|
193
|
+
path.chomp( '/' ) if path
|
194
|
+
@errors = []
|
195
|
+
|
196
|
+
is_of_matching_types = ::Proc.new do | value, types |
|
197
|
+
type_match = false
|
198
|
+
::Kernel.method( :Array ).call( types ).each do | type |
|
199
|
+
type_match = value.is_a?( type )
|
200
|
+
break if type_match
|
201
|
+
end
|
202
|
+
type_match
|
203
|
+
end
|
204
|
+
|
205
|
+
@definitions.each do | key, definition |
|
206
|
+
|
207
|
+
name = definition[ :as ] || key
|
208
|
+
value = @values[ name ]
|
209
|
+
|
210
|
+
if definition[ :required ] &&
|
211
|
+
( !value || ( value.respond_to?( :empty ) && value.empty? ) )
|
212
|
+
|
213
|
+
error = RequirementUnmetError.new( path: path, key: key )
|
214
|
+
block.call( error ) if block
|
215
|
+
@errors << error
|
216
|
+
|
217
|
+
elsif !definition[ :default_assigned ] && !value.nil?
|
218
|
+
|
219
|
+
unless definition[ :array ]
|
220
|
+
|
221
|
+
if definition[ :type ] == :group
|
222
|
+
value.__validate_values( "#{ ( path || '' ) + ( path ? '/' : '' ) + key.to_s }", &block )
|
223
|
+
@errors.concat( value.errors )
|
224
|
+
else
|
225
|
+
if definition[ :type ] && value && !definition[ :default_assigned ]
|
226
|
+
unless is_of_matching_types.call( value, definition[ :type ] )
|
227
|
+
error = IncompatibleTypeError.new(
|
228
|
+
path: path, key: key, type: definition[ :type ], value: value
|
229
|
+
)
|
230
|
+
block.call( error ) if block
|
231
|
+
@errors << error
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
else
|
237
|
+
|
238
|
+
if definition[ :type ] == :group
|
239
|
+
groups.each do | group |
|
240
|
+
group.__validate_values( "#{ ( path || '' ) + ( path ? '/' : '' ) + key.to_s }", &block )
|
241
|
+
@errors.concat( group.errors )
|
242
|
+
end
|
243
|
+
else
|
244
|
+
if definition[ :type ] && !definition[ :default_assigned ]
|
245
|
+
values = ::Kernel.method( :Array ).call( value )
|
246
|
+
values.each do | v |
|
247
|
+
unless is_of_matching_types.call( v, definition[ :type ] )
|
248
|
+
error = IncompatibleTypeError.new(
|
249
|
+
path: path, key: key, type: definition[ :type ], value: v
|
250
|
+
)
|
251
|
+
block.call( error ) if block
|
252
|
+
@errors << error
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
169
263
|
end
|
170
264
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'debug'
|
2
|
+
|
3
|
+
module AdaptiveConfiguration
|
4
|
+
|
5
|
+
class Error < StandardError; end
|
6
|
+
|
7
|
+
|
8
|
+
class IncompatibleTypeError < Error
|
9
|
+
|
10
|
+
attr_reader :keypath
|
11
|
+
attr_reader :key
|
12
|
+
attr_reader :type
|
13
|
+
|
14
|
+
def initialize( path: nil, key:, type:, value: )
|
15
|
+
|
16
|
+
path = path ? path.to_s.chomp( '/' ) : nil
|
17
|
+
@key = key
|
18
|
+
@keypath = path ? ( path + '/' + @key.to_s ) : @key.to_s
|
19
|
+
@type = type
|
20
|
+
type_text = @type.respond_to?( :join ) ? type.join( ', ' ) : type
|
21
|
+
|
22
|
+
super( "The parameter '#{@keypath}' expects #{type_text} but received incompatible #{value.class.name}." )
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
class RequirementUnmetError < Error
|
28
|
+
|
29
|
+
attr_reader :keypath
|
30
|
+
attr_reader :key
|
31
|
+
|
32
|
+
def initialize( path: nil, key: )
|
33
|
+
path = path ? path.chomp( '/' ) : nil
|
34
|
+
@key = key
|
35
|
+
@keypath = path ? ( path + '/' + @key.to_s ) : key.to_s
|
36
|
+
super( "The parameter #{@keypath} is required." )
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
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.beta02
|
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-09-
|
11
|
+
date: 2024-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- lib/adaptive_configuration/builder.rb
|
59
59
|
- lib/adaptive_configuration/configurable.rb
|
60
60
|
- lib/adaptive_configuration/context.rb
|
61
|
+
- lib/adaptive_configuration/errors.rb
|
61
62
|
- lib/adaptive_configuration/group_builder.rb
|
62
63
|
homepage: https://github.com/EndlessInternational/adaptive_configuration
|
63
64
|
licenses:
|