adaptiveconfiguration 1.0.0.beta06 → 1.0.0.beta08
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/adaptiveconfiguration.gemspec +1 -1
- data/lib/adaptive_configuration/builder.rb +111 -7
- data/lib/adaptive_configuration/configurable.rb +7 -1
- data/lib/adaptive_configuration/group_builder.rb +8 -3
- data/lib/adaptive_configuration/{context.rb → scaffold.rb} +11 -117
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cca3cc7af7f052e713d6d1065610f79fe1857f4c677c9cf860098b6136aad366
|
4
|
+
data.tar.gz: 28a8496792f95133a62b7a3696d5dfff4b96fa5ed2d8214f50831b4a8c78996b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e8df5aa99cdc79ce4aedac99a737f09c814df5e6287f30c4fb3595ce93fff7417d1311d150e9eddaca8fc6ea60dd82ff7d7ffed946f49463b30411356eeb147
|
7
|
+
data.tar.gz: ac67be155f79e5261c75bd805d0eaec9825cc2aa354b556227c4f9d8968b0cdd2ae634ed0377f024acdf2d4b518a5811a90a6006c42057dbe6911fb9d412c0a0
|
@@ -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'
|
@@ -49,19 +49,123 @@ module AdaptiveConfiguration
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def build( values = nil, &block )
|
52
|
-
|
52
|
+
scaffold = AdaptiveConfiguration::Scaffold.new(
|
53
53
|
values,
|
54
54
|
converters: @converters,
|
55
55
|
definitions: @definitions
|
56
56
|
)
|
57
|
-
|
58
|
-
|
57
|
+
scaffold.instance_eval( &block ) if block
|
58
|
+
scaffold.to_h
|
59
59
|
end
|
60
60
|
|
61
61
|
def build!( values = nil, &block )
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
+
|
65
169
|
end
|
66
170
|
|
67
171
|
end
|
@@ -10,7 +10,13 @@ module AdaptiveConfiguration
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def configure( attributes = nil, &block )
|
13
|
-
raise RuntimeError, "The
|
13
|
+
raise RuntimeError, "The configuration has not been defined." \
|
14
|
+
if @configuration_builder.nil?
|
15
|
+
configuration = @configuration_builder.build( attributes, &block )
|
16
|
+
end
|
17
|
+
|
18
|
+
def configure!( attributes = nil, &block )
|
19
|
+
raise RuntimeError, "The configuration has not been defined." \
|
14
20
|
if @configuration_builder.nil?
|
15
21
|
configuration = @configuration_builder.build!( attributes, &block )
|
16
22
|
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
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module AdaptiveConfiguration
|
2
|
-
class
|
2
|
+
class Scaffold < BasicObject
|
3
3
|
|
4
4
|
include ::PP::ObjectMixin if defined?( ::PP )
|
5
5
|
|
@@ -35,40 +35,12 @@ module AdaptiveConfiguration
|
|
35
35
|
@values.empty?
|
36
36
|
end
|
37
37
|
|
38
|
-
def key?( key )
|
39
|
-
@values.key?( key )
|
40
|
-
end
|
41
|
-
|
42
|
-
def []( key )
|
43
|
-
@values[ key ]
|
44
|
-
end
|
45
|
-
|
46
|
-
def []=( key, value )
|
47
|
-
@values[ key ] = value
|
48
|
-
end
|
49
|
-
|
50
|
-
def each( &block )
|
51
|
-
@values.each( &block )
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
def merge( hash )
|
56
|
-
self.to_h.merge( hash )
|
57
|
-
end
|
58
|
-
|
59
|
-
def valid?
|
60
|
-
__validate_values
|
61
|
-
@errors.empty?
|
62
|
-
end
|
63
|
-
|
64
|
-
def validate!
|
65
|
-
__validate_values { | error | ::Kernel.raise error }
|
66
|
-
end
|
67
|
-
|
68
38
|
def to_h
|
69
39
|
recursive_to_h = ->( object ) do
|
70
40
|
case object
|
71
|
-
when ::
|
41
|
+
when ::NilClass
|
42
|
+
nil
|
43
|
+
when ::AdaptiveConfiguration::Scaffold
|
72
44
|
recursive_to_h.call( object.to_h )
|
73
45
|
when ::Hash
|
74
46
|
object.transform_values { | value | recursive_to_h.call( value ) }
|
@@ -86,10 +58,6 @@ module AdaptiveConfiguration
|
|
86
58
|
inspect
|
87
59
|
end
|
88
60
|
|
89
|
-
def to_yaml
|
90
|
-
self.to_h.to_yaml
|
91
|
-
end
|
92
|
-
|
93
61
|
def inspect
|
94
62
|
{ values: @values, definitions: @definitions }.inspect
|
95
63
|
end
|
@@ -101,11 +69,11 @@ module AdaptiveConfiguration
|
|
101
69
|
end
|
102
70
|
|
103
71
|
def class
|
104
|
-
::AdaptiveConfiguration::
|
72
|
+
::AdaptiveConfiguration::Scaffold
|
105
73
|
end
|
106
74
|
|
107
75
|
def is_a?( klass )
|
108
|
-
klass == ::AdaptiveConfiguration::
|
76
|
+
klass == ::AdaptiveConfiguration::Scaffold || klass == ::BasicObject
|
109
77
|
end
|
110
78
|
|
111
79
|
alias :kind_of? :is_a?
|
@@ -118,12 +86,12 @@ module AdaptiveConfiguration
|
|
118
86
|
|
119
87
|
unless definition[ :array ]
|
120
88
|
if definition[ :type ] == :group
|
121
|
-
|
89
|
+
value = args.first
|
122
90
|
context = @values[ name ]
|
123
|
-
if context.nil? ||
|
91
|
+
if context.nil? || value
|
124
92
|
context =
|
125
|
-
|
126
|
-
|
93
|
+
Scaffold.new(
|
94
|
+
value,
|
127
95
|
converters: @converters,
|
128
96
|
definitions: definition[ :definitions ]
|
129
97
|
)
|
@@ -142,7 +110,7 @@ module AdaptiveConfiguration
|
|
142
110
|
if definition[ :type ] == :group
|
143
111
|
values = [ args.first ].flatten
|
144
112
|
values = values.map do | v |
|
145
|
-
context =
|
113
|
+
context = Scaffold.new(
|
146
114
|
v,
|
147
115
|
converters: @converters,
|
148
116
|
definitions: definition[ :definitions ]
|
@@ -165,7 +133,6 @@ module AdaptiveConfiguration
|
|
165
133
|
|
166
134
|
definition[ :default_assigned ] = false
|
167
135
|
@values[ name ]
|
168
|
-
|
169
136
|
else
|
170
137
|
super
|
171
138
|
end
|
@@ -206,78 +173,5 @@ module AdaptiveConfiguration
|
|
206
173
|
result
|
207
174
|
end
|
208
175
|
|
209
|
-
def __validate_values( path = nil, &block )
|
210
|
-
|
211
|
-
path.chomp( '/' ) if path
|
212
|
-
@errors = []
|
213
|
-
|
214
|
-
is_of_matching_types = ::Proc.new do | value, types |
|
215
|
-
type_match = false
|
216
|
-
::Kernel.method( :Array ).call( types ).each do | type |
|
217
|
-
type_match = value.is_a?( type )
|
218
|
-
break if type_match
|
219
|
-
end
|
220
|
-
type_match
|
221
|
-
end
|
222
|
-
|
223
|
-
@definitions.each do | key, definition |
|
224
|
-
|
225
|
-
name = definition[ :as ] || key
|
226
|
-
value = @values[ name ]
|
227
|
-
|
228
|
-
if definition[ :required ] &&
|
229
|
-
( !value || ( value.respond_to?( :empty ) && value.empty? ) )
|
230
|
-
|
231
|
-
error = RequirementUnmetError.new( path: path, key: key )
|
232
|
-
block.call( error ) if block
|
233
|
-
@errors << error
|
234
|
-
|
235
|
-
elsif !definition[ :default_assigned ] && !value.nil?
|
236
|
-
|
237
|
-
unless definition[ :array ]
|
238
|
-
|
239
|
-
if definition[ :type ] == :group
|
240
|
-
value.__validate_values( "#{ ( path || '' ) + ( path ? '/' : '' ) + key.to_s }", &block )
|
241
|
-
@errors.concat( value.errors )
|
242
|
-
else
|
243
|
-
if definition[ :type ] && value && !definition[ :default_assigned ]
|
244
|
-
unless is_of_matching_types.call( value, definition[ :type ] )
|
245
|
-
error = IncompatibleTypeError.new(
|
246
|
-
path: path, key: key, type: definition[ :type ], value: value
|
247
|
-
)
|
248
|
-
block.call( error ) if block
|
249
|
-
@errors << error
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
else
|
255
|
-
|
256
|
-
if definition[ :type ] == :group
|
257
|
-
groups = ::Kernel.method( :Array ).call( value )
|
258
|
-
groups.each do | group |
|
259
|
-
group.__validate_values( "#{ ( path || '' ) + ( path ? '/' : '' ) + key.to_s }", &block )
|
260
|
-
@errors.concat( group.errors )
|
261
|
-
end
|
262
|
-
else
|
263
|
-
if definition[ :type ] && !definition[ :default_assigned ]
|
264
|
-
values = ::Kernel.method( :Array ).call( value )
|
265
|
-
values.each do | v |
|
266
|
-
unless is_of_matching_types.call( v, definition[ :type ] )
|
267
|
-
error = IncompatibleTypeError.new(
|
268
|
-
path: path, key: key, type: definition[ :type ], value: v
|
269
|
-
)
|
270
|
-
block.call( error ) if block
|
271
|
-
@errors << error
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
176
|
end
|
283
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.beta08
|
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-13 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
|