nxt_schema 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +80 -38
- data/lib/nxt_schema.rb +17 -17
- data/lib/nxt_schema/dsl.rb +7 -7
- data/lib/nxt_schema/{application.rb → node.rb} +1 -1
- data/lib/nxt_schema/node/any_of.rb +21 -33
- data/lib/nxt_schema/node/base.rb +70 -171
- data/lib/nxt_schema/node/collection.rb +43 -8
- data/lib/nxt_schema/{application → node}/error_store.rb +5 -5
- data/lib/nxt_schema/{application → node}/errors/schema_error.rb +1 -1
- data/lib/nxt_schema/{application → node}/errors/validation_error.rb +1 -1
- data/lib/nxt_schema/node/leaf.rb +7 -5
- data/lib/nxt_schema/node/schema.rb +101 -8
- data/lib/nxt_schema/template/any_of.rb +50 -0
- data/lib/nxt_schema/template/base.rb +218 -0
- data/lib/nxt_schema/template/collection.rb +23 -0
- data/lib/nxt_schema/{node → template}/has_sub_nodes.rb +16 -10
- data/lib/nxt_schema/template/leaf.rb +13 -0
- data/lib/nxt_schema/{node → template}/maybe_evaluator.rb +1 -1
- data/lib/nxt_schema/{node → template}/on_evaluator.rb +1 -1
- data/lib/nxt_schema/template/schema.rb +22 -0
- data/lib/nxt_schema/{node → template}/sub_nodes.rb +1 -1
- data/lib/nxt_schema/{node → template}/type_resolver.rb +2 -2
- data/lib/nxt_schema/{node → template}/type_system_resolver.rb +1 -1
- data/lib/nxt_schema/version.rb +1 -1
- metadata +17 -17
- data/lib/nxt_schema/application/any_of.rb +0 -40
- data/lib/nxt_schema/application/base.rb +0 -116
- data/lib/nxt_schema/application/collection.rb +0 -57
- data/lib/nxt_schema/application/leaf.rb +0 -15
- data/lib/nxt_schema/application/schema.rb +0 -114
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1aba2ccbd135921f48a84de3e51d11b0592522b8d9e9e9fd3a5ff188117ffae
|
4
|
+
data.tar.gz: 1c67ef1beda4a6e6a33bd67bc7a9294c7bfbc14ccf72be3b621748212192c8c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34cd6cdacddb969ac3532dc8f52150dc16e8be80b12bf8ceaec9cd147df93547cc02e655eaff1d05eee359b660e1143187adb704fbac91a3f09d4a18ebd28087
|
7
|
+
data.tar.gz: 5f77d02ed8b601aa255a4b9be082c48f1da0e7fa157561547e7c99a726c8a9d2f34a4c76be78cbd60ec529bce719e0b06e42d6645cbbe18e65facf7de9e7a1fc
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
nxt_schema (1.0.
|
4
|
+
nxt_schema (1.0.1)
|
5
5
|
activesupport
|
6
6
|
dry-types
|
7
7
|
nxt_init
|
@@ -50,7 +50,7 @@ GEM
|
|
50
50
|
minitest (5.14.2)
|
51
51
|
nxt_init (0.1.5)
|
52
52
|
activesupport
|
53
|
-
nxt_registry (0.3.
|
53
|
+
nxt_registry (0.3.3)
|
54
54
|
activesupport
|
55
55
|
pry (0.13.1)
|
56
56
|
coderay (~> 1.1)
|
@@ -72,7 +72,7 @@ GEM
|
|
72
72
|
thread_safe (0.3.6)
|
73
73
|
tzinfo (1.2.8)
|
74
74
|
thread_safe (~> 0.1)
|
75
|
-
zeitwerk (2.4.
|
75
|
+
zeitwerk (2.4.2)
|
76
76
|
|
77
77
|
PLATFORMS
|
78
78
|
ruby
|
data/README.md
CHANGED
@@ -16,10 +16,13 @@ Or install it yourself as:
|
|
16
16
|
|
17
17
|
$ gem install nxt_schema
|
18
18
|
|
19
|
-
## What it
|
19
|
+
## What is it for?
|
20
20
|
|
21
|
-
NxtSchema is a type
|
22
|
-
structures of data.
|
21
|
+
NxtSchema is a type coercion and validation framework that allows you to coerce and validate arbitrary nested
|
22
|
+
structures of data. The original idea is taken from https://dry-rb.org/gems/dry-schema and
|
23
|
+
https://dry-rb.org/gems/dry-validation from the amazing dry.rb eco system. In contrast to dry-schema,
|
24
|
+
NxtSchema aims to be a simpler solution that hopefully is easier to understand and debug.
|
25
|
+
It also ships with some handy features that dry-schema does not implement.
|
23
26
|
|
24
27
|
### Usage
|
25
28
|
|
@@ -31,7 +34,7 @@ PERSON = NxtSchema.schema(:person) do
|
|
31
34
|
end
|
32
35
|
|
33
36
|
input = {
|
34
|
-
first_name: '
|
37
|
+
first_name: 'Ändy',
|
35
38
|
last_name: 'Robecke',
|
36
39
|
email: 'andreas@robecke.de'
|
37
40
|
}
|
@@ -58,9 +61,9 @@ The kind of node dictates how the schema is applied to the input. On the root le
|
|
58
61
|
to create schemas:
|
59
62
|
|
60
63
|
```ruby
|
61
|
-
NxtSchema.schema { ... } # =>
|
62
|
-
NxtSchema.collection { ... } # =>
|
63
|
-
NxtSchema.any_of { ... } # =>
|
64
|
+
NxtSchema.schema { ... } # => Creates a schema node
|
65
|
+
NxtSchema.collection { ... } # => Creates an array of nodes
|
66
|
+
NxtSchema.any_of { ... } # => Creates a collection of allowed schemas
|
64
67
|
```
|
65
68
|
|
66
69
|
#### Node predicate aliases
|
@@ -85,6 +88,8 @@ into a schema you also have to combine the node predicates with default value me
|
|
85
88
|
check out the examples below:
|
86
89
|
|
87
90
|
```ruby
|
91
|
+
# Optional node without default value
|
92
|
+
|
88
93
|
schema = NxtSchema.schema(:person) do
|
89
94
|
optional(:email, :String)
|
90
95
|
end
|
@@ -99,19 +104,24 @@ result.output # => {}
|
|
99
104
|
```
|
100
105
|
|
101
106
|
```ruby
|
107
|
+
# Optional node with default value
|
108
|
+
|
102
109
|
schema = NxtSchema.schema(:person) do
|
103
110
|
optional(:email, :String).default('andreas@robecke.de')
|
104
111
|
end
|
105
112
|
|
106
113
|
result = schema.apply(input: { email: nil })
|
107
114
|
result.errors # => {}
|
115
|
+
result.output # => {:email=>"andreas@robecke.de"}
|
108
116
|
|
109
117
|
result = schema.apply(input: {})
|
110
118
|
result.errors # => {}
|
111
|
-
result.output # => {
|
119
|
+
result.output # => {}
|
112
120
|
```
|
113
121
|
|
114
122
|
```ruby
|
123
|
+
# Omnipresent node without default value
|
124
|
+
|
115
125
|
schema = NxtSchema.schema(:person) do
|
116
126
|
omnipresent(:email, :String)
|
117
127
|
end
|
@@ -122,8 +132,9 @@ result.output # => {:email=>NxtSchema::MissingInput}
|
|
122
132
|
```
|
123
133
|
|
124
134
|
```ruby
|
135
|
+
# Omnipresent node with default value and maybe expression to allow default value to break type contract.
|
136
|
+
|
125
137
|
schema = NxtSchema.schema(:person) do
|
126
|
-
# make sure a node is always present and at least nil even though the type is String
|
127
138
|
omnipresent(:email, :String).default(nil).maybe(:nil?)
|
128
139
|
end
|
129
140
|
|
@@ -131,15 +142,16 @@ result = schema.apply(input: {})
|
|
131
142
|
result.errors # => {}
|
132
143
|
result.output # => {:email=>nil}
|
133
144
|
|
134
|
-
result = schema.apply(input:
|
145
|
+
result = schema.apply(input: { email: 'andreas@robecke.de' })
|
135
146
|
result.errors # => {}
|
136
147
|
result.output # => {:email=>"andreas@robecke.de"}
|
137
148
|
```
|
138
149
|
|
139
150
|
##### Conditionally optional nodes
|
140
151
|
|
141
|
-
You can also pass a proc as the optional option. This
|
142
|
-
|
152
|
+
You can also pass a proc as the optional option. This is a shortcut for adding a validation to the parent node
|
153
|
+
that will result in a validation error in case the optional condition does not apply and the parent node does not
|
154
|
+
contain a sub node with that name (here contact schema not including an email node).
|
143
155
|
|
144
156
|
```ruby
|
145
157
|
schema = NxtSchema.schema(:contact) do
|
@@ -180,10 +192,6 @@ The type system is built with dry-types from the amazing https://dry-rb.org eco
|
|
180
192
|
offers features such as default values for types as well as maybe types, these features are built directly into
|
181
193
|
NxtSchema.
|
182
194
|
|
183
|
-
Please note that Dry.rb also has a gem for schemas: https://dry-rb.org/gems/dry-schema and another one dedicated to
|
184
|
-
validations explicitly https://dry-rb.org/gems/dry-validation. You should probably go and check those out! NxtSchema
|
185
|
-
is trying to implement a simpler solution that is easy to understand yet powerful enough for most tasks.
|
186
|
-
|
187
195
|
In NxtSchema every node has a type and you can either provide a symbol that will be resolved
|
188
196
|
through the type system of the schema or you can directly provide an instance of dry type and thus use your
|
189
197
|
custom types. This means you can basically build any kind of objects such as structs and models from your data and
|
@@ -197,11 +205,11 @@ type system that was specified NxtSchema will always fallback to nominal types.
|
|
197
205
|
a separate type system per node if that's what you need.
|
198
206
|
|
199
207
|
```ruby
|
200
|
-
NxtSchema.
|
208
|
+
NxtSchema.schema do
|
201
209
|
required(:test, :String) # The :String will resolve to NxtSchema::Types::Nominal::String
|
202
210
|
end
|
203
211
|
|
204
|
-
NxtSchema.
|
212
|
+
NxtSchema.schema(type_system: NxtSchema::Types::JSON) do
|
205
213
|
required(:test, :Date) # The :Date will resolve to NxtSchema::Types::JSON::Date
|
206
214
|
# When the type does not exist in the default type system (there is non JSON::String) we fallback to nominal types
|
207
215
|
required(:test, :String)
|
@@ -234,7 +242,7 @@ NxtSchema.register_type(
|
|
234
242
|
|
235
243
|
# once registered you can use the type in your schema
|
236
244
|
|
237
|
-
NxtSchema.
|
245
|
+
NxtSchema.schema(:company) do
|
238
246
|
required(:name, :MyCustomStrippedString)
|
239
247
|
end
|
240
248
|
```
|
@@ -244,21 +252,21 @@ end
|
|
244
252
|
#### Default values
|
245
253
|
|
246
254
|
```ruby
|
247
|
-
# Define default values
|
255
|
+
# Define default values with the default method
|
256
|
+
required(:test, :DateTime).default(nil)
|
248
257
|
required(:test, :DateTime).default(-> { Time.current })
|
249
|
-
required(:test, :String, default: 'Andy')
|
250
258
|
```
|
251
259
|
|
252
260
|
#### Maybe values
|
253
261
|
|
254
|
-
With maybe you can allow your values to
|
255
|
-
will simply be set to the input without coercing the value!**
|
262
|
+
With maybe expressions you can halt coercion and allow your values to break the type contract.
|
263
|
+
**Note: This means that your output will simply be set to the input without coercing the value!**
|
256
264
|
|
257
265
|
```ruby
|
258
266
|
# Define maybe values (values that do not match the type)
|
259
267
|
required(:test, :String).maybe(:nil?)
|
260
268
|
|
261
|
-
nodes(:tests).maybe(:empty?) do # will allow the collection to be empty
|
269
|
+
nodes(:tests).maybe(:empty?) do # will allow the collection to be empty and thus not contain strings
|
262
270
|
required(:test, :String)
|
263
271
|
end
|
264
272
|
|
@@ -272,6 +280,8 @@ based on some condition. When the node is yielded to your validation proc you ha
|
|
272
280
|
`node.input` and `node.index` when the node is within a collection of nodes as well as `node.name`. Furthermore you have
|
273
281
|
access to the context that was passed in when defining the schema or passed to the apply method later.
|
274
282
|
|
283
|
+
**NOTE: Validations only run when no maybe expression applies and the node input could be coerced successfully**
|
284
|
+
|
275
285
|
```ruby
|
276
286
|
# Simple custom validation
|
277
287
|
required(:test, :String).validate(-> (node) { node.add_error("#{node.input} is not valid") if node.input == 'not allowed' })
|
@@ -320,7 +330,7 @@ end
|
|
320
330
|
NxtSchema.register_validator(MyCustomExclusionValidator, :my_custom_exclusion_validator)
|
321
331
|
|
322
332
|
# and then simply reference it with the key you've registered it
|
323
|
-
schema = NxtSchema.
|
333
|
+
schema = NxtSchema.schema(:company) do
|
324
334
|
requires(:name, :String).validate(:my_custom_exclusion_validator, %w[lemonade])
|
325
335
|
end
|
326
336
|
|
@@ -333,25 +343,24 @@ schema.apply(name: 'lemonade').valid? # => false
|
|
333
343
|
- Add translated errors
|
334
344
|
- Interpolate with actual vs. expected
|
335
345
|
|
336
|
-
#### Combining validators
|
346
|
+
#### Combining validators
|
337
347
|
|
338
348
|
`node(:test, String).validate(...)` basically adds a validator to the node. Of course you can add multiple validators.
|
339
|
-
But that means that they will all be executed
|
349
|
+
But that means that they will all be executed. If you want your validator to only run in case
|
340
350
|
another was false, you can use `:validat_with do ... end` in order to combine validators based on custom logic.
|
341
351
|
|
342
352
|
```ruby
|
343
|
-
NxtSchema.
|
353
|
+
NxtSchema.schema do
|
344
354
|
required(:test, :Integer).validate_with do
|
345
355
|
validator(:greater_than, 5) &&
|
346
|
-
validator(:greater_than, 6)
|
356
|
+
validator(:greater_than, 6) ||
|
347
357
|
validator(:greater_than, 7)
|
348
358
|
end
|
349
359
|
end
|
350
360
|
```
|
351
361
|
|
352
|
-
|
353
|
-
|
354
|
-
means that you might not have the full validation errors when combining validations with `:validate_with`
|
362
|
+
Note that this will not run subsequent validators once one was valuated to false and thus might not contain all error
|
363
|
+
messages of all validators that would have failed.
|
355
364
|
|
356
365
|
|
357
366
|
### Schema options
|
@@ -363,17 +372,17 @@ You can change this behaviour by providing a strategy for the `:additional_keys`
|
|
363
372
|
|
364
373
|
```ruby
|
365
374
|
# This will simply ignore any other key except test
|
366
|
-
NxtSchema.
|
375
|
+
NxtSchema.schema(additional_keys: :ignore) do
|
367
376
|
required(:test, :String)
|
368
377
|
end
|
369
378
|
|
370
379
|
# This would give you an error in case you apply anything other than { test: '...' }
|
371
|
-
NxtSchema.
|
380
|
+
NxtSchema.schema(additional_keys: :restrict) do
|
372
381
|
required(:test, :String)
|
373
382
|
end
|
374
383
|
|
375
384
|
# This will merge other keys into your output
|
376
|
-
schema = NxtSchema.
|
385
|
+
schema = NxtSchema.schema(additional_keys: :allow) do
|
377
386
|
required(:test, :String)
|
378
387
|
end
|
379
388
|
|
@@ -388,7 +397,7 @@ You may want to transform the keys from your input. Therefore specify the transf
|
|
388
397
|
when you want your schema to return only symbolized keys for example.
|
389
398
|
|
390
399
|
```ruby
|
391
|
-
schema = NxtSchema.
|
400
|
+
schema = NxtSchema.schema(transform_keys: ->(key) { key.to_sym}) do
|
392
401
|
required(:test, :String)
|
393
402
|
end
|
394
403
|
|
@@ -402,7 +411,7 @@ You want to give nodes an ID or some other meta data? You can use the meta metho
|
|
402
411
|
information onto any node.
|
403
412
|
|
404
413
|
```ruby
|
405
|
-
schema = NxtSchema.
|
414
|
+
schema = NxtSchema.schema do
|
406
415
|
ERROR_MESSAGES = {
|
407
416
|
test: 'This is always broken'
|
408
417
|
}
|
@@ -416,12 +425,43 @@ schema.error # {"root.test"=>["This is always broken"]}
|
|
416
425
|
|
417
426
|
#### Contexts
|
418
427
|
|
419
|
-
|
428
|
+
When defining a schema it is possible to pass in a context option. This can be anything that you would like to access
|
429
|
+
during building your schema. A context could provide custom validators or default values depending of the name of your
|
430
|
+
nodes for instance.
|
420
431
|
|
421
432
|
##### Build time
|
422
433
|
|
434
|
+
```ruby
|
435
|
+
context = OpenStruct.new(email_validator: ->(node) { node.input && node.input.includes?('@') })
|
436
|
+
|
437
|
+
NxtSchema.schema(:developers, context: context) do
|
438
|
+
required(:first_name, :String)
|
439
|
+
required(:last_name, :String)
|
440
|
+
required(:email, :String).validate(context.email_validator)
|
441
|
+
end
|
442
|
+
```
|
443
|
+
|
423
444
|
##### Apply time
|
424
445
|
|
446
|
+
You can also pass in a context at apply time. If you do not pass in a specific
|
447
|
+
context at apply time you can still access the context passed in at build time.
|
448
|
+
Basically passing in a context at apply time will overwrite the context from before. You can access it simply through
|
449
|
+
the node.
|
450
|
+
|
451
|
+
```ruby
|
452
|
+
build_context = OpenStruct.new(email_validator: ->(node) { node.input.includes?('@') })
|
453
|
+
apply_context = OpenStruct.new(default_role: 'BOSS')
|
454
|
+
|
455
|
+
schema = NxtSchema.schema(:developers, context: build_context) do
|
456
|
+
# context at build time
|
457
|
+
required(:email, :String).validate(context.email_validator) #
|
458
|
+
# access the context at apply time through the node
|
459
|
+
required(:role, :String).default { |_, node| node.context.default_role }
|
460
|
+
end
|
461
|
+
|
462
|
+
schema.apply(input: input, context: apply_context)
|
463
|
+
```
|
464
|
+
|
425
465
|
## Development
|
426
466
|
|
427
467
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -438,6 +478,8 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
438
478
|
|
439
479
|
## TODO:
|
440
480
|
|
481
|
+
- Explain node interface
|
482
|
+
- Add apply! method to readme
|
441
483
|
- Allow to disable validation when applying
|
442
484
|
--> Are there attributes that should be moved to apply time?
|
443
485
|
- Should we have a global and a local registry for validators?
|
data/lib/nxt_schema.rb
CHANGED
@@ -7,7 +7,7 @@ require 'yaml'
|
|
7
7
|
|
8
8
|
require_relative 'nxt_schema/types'
|
9
9
|
require_relative 'nxt_schema/callable'
|
10
|
-
require_relative 'nxt_schema/
|
10
|
+
require_relative 'nxt_schema/node'
|
11
11
|
require_relative 'nxt_schema/missing_input'
|
12
12
|
require_relative 'nxt_schema/error'
|
13
13
|
require_relative 'nxt_schema/errors/invalid'
|
@@ -31,26 +31,26 @@ require_relative 'nxt_schema/validators/excluded_in'
|
|
31
31
|
require_relative 'nxt_schema/validators/excludes'
|
32
32
|
require_relative 'nxt_schema/validators/query'
|
33
33
|
|
34
|
-
require_relative 'nxt_schema/
|
35
|
-
require_relative 'nxt_schema/
|
36
|
-
require_relative 'nxt_schema/
|
37
|
-
require_relative 'nxt_schema/
|
34
|
+
require_relative 'nxt_schema/template/on_evaluator'
|
35
|
+
require_relative 'nxt_schema/template/maybe_evaluator'
|
36
|
+
require_relative 'nxt_schema/template/type_resolver'
|
37
|
+
require_relative 'nxt_schema/template/type_system_resolver'
|
38
|
+
require_relative 'nxt_schema/template/base'
|
39
|
+
require_relative 'nxt_schema/template/sub_nodes'
|
40
|
+
require_relative 'nxt_schema/template/has_sub_nodes'
|
41
|
+
require_relative 'nxt_schema/template/any_of'
|
42
|
+
require_relative 'nxt_schema/template/collection'
|
43
|
+
require_relative 'nxt_schema/template/schema'
|
44
|
+
require_relative 'nxt_schema/template/leaf'
|
45
|
+
|
46
|
+
require_relative 'nxt_schema/node/errors/schema_error'
|
47
|
+
require_relative 'nxt_schema/node/errors/validation_error'
|
48
|
+
require_relative 'nxt_schema/node/error_store'
|
38
49
|
require_relative 'nxt_schema/node/base'
|
39
|
-
require_relative 'nxt_schema/node/sub_nodes'
|
40
|
-
require_relative 'nxt_schema/node/has_sub_nodes'
|
41
50
|
require_relative 'nxt_schema/node/any_of'
|
51
|
+
require_relative 'nxt_schema/node/leaf'
|
42
52
|
require_relative 'nxt_schema/node/collection'
|
43
53
|
require_relative 'nxt_schema/node/schema'
|
44
|
-
require_relative 'nxt_schema/node/leaf'
|
45
|
-
|
46
|
-
require_relative 'nxt_schema/application/errors/schema_error'
|
47
|
-
require_relative 'nxt_schema/application/errors/validation_error'
|
48
|
-
require_relative 'nxt_schema/application/error_store'
|
49
|
-
require_relative 'nxt_schema/application/base'
|
50
|
-
require_relative 'nxt_schema/application/any_of'
|
51
|
-
require_relative 'nxt_schema/application/leaf'
|
52
|
-
require_relative 'nxt_schema/application/collection'
|
53
|
-
require_relative 'nxt_schema/application/schema'
|
54
54
|
require_relative 'nxt_schema/dsl'
|
55
55
|
|
56
56
|
module NxtSchema
|
data/lib/nxt_schema/dsl.rb
CHANGED
@@ -2,8 +2,8 @@ module NxtSchema
|
|
2
2
|
module Dsl
|
3
3
|
DEFAULT_OPTIONS = { type_system: NxtSchema::Types }.freeze
|
4
4
|
|
5
|
-
def collection(name = :root, type: NxtSchema::
|
6
|
-
NxtSchema::
|
5
|
+
def collection(name = :root, type: NxtSchema::Template::Collection::DEFAULT_TYPE, **options, &block)
|
6
|
+
NxtSchema::Template::Collection.new(
|
7
7
|
name: name,
|
8
8
|
type: type,
|
9
9
|
parent_node: nil,
|
@@ -14,8 +14,8 @@ module NxtSchema
|
|
14
14
|
|
15
15
|
alias nodes collection
|
16
16
|
|
17
|
-
def schema(name = :roots, type: NxtSchema::
|
18
|
-
NxtSchema::
|
17
|
+
def schema(name = :roots, type: NxtSchema::Template::Schema::DEFAULT_TYPE, **options, &block)
|
18
|
+
NxtSchema::Template::Schema.new(
|
19
19
|
name: name,
|
20
20
|
type: type,
|
21
21
|
parent_node: nil,
|
@@ -25,7 +25,7 @@ module NxtSchema
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def any_of(name = :roots, **options, &block)
|
28
|
-
NxtSchema::
|
28
|
+
NxtSchema::Template::AnyOf.new(
|
29
29
|
name: name,
|
30
30
|
parent_node: nil,
|
31
31
|
**DEFAULT_OPTIONS.merge(options),
|
@@ -35,8 +35,8 @@ module NxtSchema
|
|
35
35
|
|
36
36
|
# schema root with NxtSchema::Types::Params type system
|
37
37
|
|
38
|
-
def params(name = :params, type: NxtSchema::
|
39
|
-
NxtSchema::
|
38
|
+
def params(name = :params, type: NxtSchema::Template::Schema::DEFAULT_TYPE, **options, &block)
|
39
|
+
NxtSchema::Template::Schema.new(
|
40
40
|
name: name,
|
41
41
|
type: type,
|
42
42
|
parent_node: nil,
|
@@ -1,50 +1,38 @@
|
|
1
1
|
module NxtSchema
|
2
2
|
module Node
|
3
|
-
class AnyOf < Base
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(name:, type: nil, parent_node:, **options, &block)
|
7
|
-
super
|
8
|
-
end
|
9
|
-
|
10
|
-
def collection(name = sub_nodes.count, type = NxtSchema::Node::Collection::DEFAULT_TYPE, **options, &block)
|
11
|
-
super
|
3
|
+
class AnyOf < Node::Base
|
4
|
+
def valid?
|
5
|
+
valid_application.present?
|
12
6
|
end
|
13
7
|
|
14
|
-
def
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def node(name = sub_nodes.count, node_or_type_of_node = nil, **options, &block)
|
19
|
-
super
|
20
|
-
end
|
8
|
+
def call
|
9
|
+
child_applications.map(&:call)
|
21
10
|
|
22
|
-
|
11
|
+
if valid?
|
12
|
+
self.output = valid_application.output
|
13
|
+
else
|
14
|
+
child_applications.each do |application|
|
15
|
+
merge_errors(application)
|
16
|
+
end
|
17
|
+
end
|
23
18
|
|
24
|
-
|
25
|
-
raise NotImplementedError
|
26
|
-
end
|
27
|
-
|
28
|
-
def maybe(*args)
|
29
|
-
raise NotImplementedError
|
19
|
+
self
|
30
20
|
end
|
31
21
|
|
32
22
|
private
|
33
23
|
|
34
|
-
|
35
|
-
nil
|
36
|
-
end
|
24
|
+
delegate :[], to: :child_applications
|
37
25
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
raise InvalidOptions, "The optional option is not available for nodes of type #{self.class.name}"
|
26
|
+
def valid_application
|
27
|
+
child_applications.find(&:valid?)
|
42
28
|
end
|
43
29
|
|
44
|
-
def
|
45
|
-
|
30
|
+
def child_applications
|
31
|
+
@child_applications ||= nodes.map { |node| node.build_application(input: input, context: context, parent: self) }
|
32
|
+
end
|
46
33
|
|
47
|
-
|
34
|
+
def nodes
|
35
|
+
@nodes ||= node.sub_nodes.values
|
48
36
|
end
|
49
37
|
end
|
50
38
|
end
|