adaptiveconfiguration 1.0.0.beta01 → 1.0.0.beta03
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec8e4cec6a37127b4bc376f810cbee603723b067dab0d335f93b3dbcc3650704
|
4
|
+
data.tar.gz: 713dab6e604323df35ce20cacd034165801240c22ac0d92f86a65828811626cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2675668e7ed07d9f17d410dd0be09fb4a52c40e9e98e30f770494e4cbebbcb6cb7e5b34c6b4677fa06e5ac60b36619730ef6144bed94e5453bb8de667766af1e
|
7
|
+
data.tar.gz: d794189593853971ac8bb9edf88ee2d8bae4aa1f6299fed358c40c29c5b9f9194af56e75aed5d58fbdff5169679fd34b4b1d31586b5dc48f67697da8161031c3
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do | spec |
|
2
2
|
|
3
3
|
spec.name = 'adaptiveconfiguration'
|
4
|
-
spec.version = '1.0.0.
|
4
|
+
spec.version = '1.0.0.beta03'
|
5
5
|
spec.authors = [ 'Kristoph Cichocki-Romanov' ]
|
6
6
|
spec.email = [ 'rubygems.org@kristoph.net' ]
|
7
7
|
|
@@ -34,4 +34,4 @@ Gem::Specification.new do | spec |
|
|
34
34
|
spec.add_development_dependency 'rspec', '~> 3.13'
|
35
35
|
spec.add_development_dependency 'debug', '~> 1.9'
|
36
36
|
|
37
|
-
end
|
37
|
+
end
|
@@ -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,39 @@
|
|
1
|
+
module AdaptiveConfiguration
|
2
|
+
|
3
|
+
class Error < StandardError; end
|
4
|
+
|
5
|
+
|
6
|
+
class IncompatibleTypeError < Error
|
7
|
+
|
8
|
+
attr_reader :keypath
|
9
|
+
attr_reader :key
|
10
|
+
attr_reader :type
|
11
|
+
|
12
|
+
def initialize( path: nil, key:, type:, value: )
|
13
|
+
|
14
|
+
path = path ? path.to_s.chomp( '/' ) : nil
|
15
|
+
@key = key
|
16
|
+
@keypath = path ? ( path + '/' + @key.to_s ) : @key.to_s
|
17
|
+
@type = type
|
18
|
+
type_text = @type.respond_to?( :join ) ? type.join( ', ' ) : type
|
19
|
+
|
20
|
+
super( "The parameter '#{@keypath}' expects #{type_text} but received incompatible #{value.class.name}." )
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class RequirementUnmetError < Error
|
26
|
+
|
27
|
+
attr_reader :keypath
|
28
|
+
attr_reader :key
|
29
|
+
|
30
|
+
def initialize( path: nil, key: )
|
31
|
+
path = path ? path.chomp( '/' ) : nil
|
32
|
+
@key = key
|
33
|
+
@keypath = path ? ( path + '/' + @key.to_s ) : key.to_s
|
34
|
+
super( "The parameter #{@keypath} is required." )
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
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.beta03
|
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-
|
11
|
+
date: 2024-10-06 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:
|