dry-schema 1.9.3 → 1.10.3
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/CHANGELOG.md +49 -0
- data/LICENSE +1 -1
- data/dry-schema.gemspec +3 -3
- data/lib/dry/schema/compiler.rb +0 -1
- data/lib/dry/schema/config.rb +0 -3
- data/lib/dry/schema/constants.rb +0 -1
- data/lib/dry/schema/dsl.rb +31 -6
- data/lib/dry/schema/key_coercer.rb +0 -3
- data/lib/dry/schema/key_map.rb +0 -2
- data/lib/dry/schema/macros/array.rb +1 -1
- data/lib/dry/schema/macros/dsl.rb +29 -11
- data/lib/dry/schema/macros/each.rb +5 -4
- data/lib/dry/schema/macros/filled.rb +9 -6
- data/lib/dry/schema/macros/key.rb +0 -61
- data/lib/dry/schema/macros/maybe.rb +3 -1
- data/lib/dry/schema/macros/schema.rb +20 -9
- data/lib/dry/schema/macros/value.rb +2 -2
- data/lib/dry/schema/message/or/multi_path.rb +15 -11
- data/lib/dry/schema/message/or/single_path.rb +15 -5
- data/lib/dry/schema/message.rb +0 -1
- data/lib/dry/schema/message_set.rb +1 -3
- data/lib/dry/schema/messages/abstract.rb +0 -2
- data/lib/dry/schema/messages/template.rb +0 -1
- data/lib/dry/schema/messages/yaml.rb +0 -3
- data/lib/dry/schema/predicate.rb +0 -3
- data/lib/dry/schema/predicate_inferrer.rb +0 -2
- data/lib/dry/schema/predicate_registry.rb +0 -3
- data/lib/dry/schema/primitive_inferrer.rb +0 -2
- data/lib/dry/schema/processor.rb +17 -3
- data/lib/dry/schema/result.rb +0 -1
- data/lib/dry/schema/types_merger.rb +139 -0
- data/lib/dry/schema/value_coercer.rb +0 -1
- data/lib/dry/schema/version.rb +1 -1
- data/lib/dry/schema.rb +4 -1
- metadata +11 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 52498945533408be846a7c22b278471bb1e45fec87b9b3a994eee33034009fff
|
|
4
|
+
data.tar.gz: 1b5f542e5c07fb57a67cd7fa2062bf17a51bcc6acf2e9ba4955468f42a9c4b08
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d189171c08a31c3011ff9747890eb3286f019edd2a5ec6f8bb28c9dcfd1b623886d52cdd88715bac608c1adf58d0ffd139c68a228799d207d1353821f16f5dd9
|
|
7
|
+
data.tar.gz: 105ac239e814c3ce1b40641137c5b9bf01dbd3c077d3891606773e4825f92c90a37d1248f6b352f75b77bafc80b52b2a0c1d4b719ec3a4a5fde09c186f6dd4f5
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
|
2
2
|
|
|
3
|
+
## 1.10.3 2019-10-10
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
- Addressed regressions causing issues with handling sum types (see #419 and #423 fixed via #425) (@robhanlon22)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
[Compare v1.10.2...v1.10.3](https://github.com/dry-rb/dry-schema/compare/v1.10.2...v1.10.3)
|
|
12
|
+
|
|
13
|
+
## 1.10.2 2022-08-23
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Fix value coercion for composed schemas (via #421) (@robhanlon22)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
[Compare v1.10.1...v1.10.2](https://github.com/dry-rb/dry-schema/compare/v1.10.1...v1.10.2)
|
|
22
|
+
|
|
23
|
+
## 1.10.1 2022-08-22
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Reverted zeitwerk-related changes that were included in 1.10.0 by an accident (@solnic)
|
|
29
|
+
|
|
30
|
+
[Compare v1.10.0...v1.10.1](https://github.com/dry-rb/dry-schema/compare/v1.10.0...v1.10.1)
|
|
31
|
+
|
|
32
|
+
## 1.10.0 2022-08-16
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- Allow nested `filled` and `value` macro usage (via #412) (@robhanlon22)
|
|
38
|
+
- Support for more complex scenarios when composing schemas (via #420) (@robhanlon22)
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Fix `or` messages for complex schemas (via #413) (@robhanlon22)
|
|
43
|
+
- Using `filled` with a constrained constructor type works as expected (via #416) (@robhanlon22)
|
|
44
|
+
- Fix types and key maps for composed schemas (via #415) (@robhanlon22)
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- Freeze message hash (fixes #417 via #418) (@solnic)
|
|
49
|
+
|
|
50
|
+
[Compare v1.9.3...v1.10.0](https://github.com/dry-rb/dry-schema/compare/v1.9.3...v1.10.0)
|
|
51
|
+
|
|
3
52
|
## 1.9.3 2022-06-23
|
|
4
53
|
|
|
5
54
|
|
data/LICENSE
CHANGED
data/dry-schema.gemspec
CHANGED
|
@@ -36,10 +36,10 @@ Gem::Specification.new do |spec|
|
|
|
36
36
|
# to update dependencies edit project.yml
|
|
37
37
|
spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
|
38
38
|
spec.add_runtime_dependency "dry-configurable", "~> 0.13", ">= 0.13.0"
|
|
39
|
-
spec.add_runtime_dependency "dry-core", "~> 0.
|
|
39
|
+
spec.add_runtime_dependency "dry-core", "~> 0.9", ">= 0.9"
|
|
40
40
|
spec.add_runtime_dependency "dry-initializer", "~> 3.0"
|
|
41
|
-
spec.add_runtime_dependency "dry-logic", "~> 1.
|
|
42
|
-
spec.add_runtime_dependency "dry-types", "~> 1.
|
|
41
|
+
spec.add_runtime_dependency "dry-logic", "~> 1.3"
|
|
42
|
+
spec.add_runtime_dependency "dry-types", "~> 1.6"
|
|
43
43
|
|
|
44
44
|
spec.add_development_dependency "bundler"
|
|
45
45
|
spec.add_development_dependency "rake"
|
data/lib/dry/schema/compiler.rb
CHANGED
data/lib/dry/schema/config.rb
CHANGED
data/lib/dry/schema/constants.rb
CHANGED
data/lib/dry/schema/dsl.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "dry/initializer"
|
|
4
|
+
require "dry/logic"
|
|
4
5
|
|
|
5
6
|
require "dry/schema/constants"
|
|
6
7
|
require "dry/schema/path"
|
|
@@ -16,6 +17,7 @@ require "dry/schema/key_coercer"
|
|
|
16
17
|
require "dry/schema/key_validator"
|
|
17
18
|
require "dry/schema/value_coercer"
|
|
18
19
|
require "dry/schema/rule_applier"
|
|
20
|
+
require "dry/schema/types_merger"
|
|
19
21
|
|
|
20
22
|
module Dry
|
|
21
23
|
module Schema
|
|
@@ -286,13 +288,20 @@ module Dry
|
|
|
286
288
|
|
|
287
289
|
# Return type schema used by the value coercer
|
|
288
290
|
#
|
|
289
|
-
# @return [Dry::Types::
|
|
291
|
+
# @return [Dry::Types::Lax]
|
|
290
292
|
#
|
|
291
293
|
# @api private
|
|
292
294
|
def type_schema
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
295
|
+
strict_type_schema.lax
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# Return type schema used when composing subschemas
|
|
299
|
+
#
|
|
300
|
+
# @return [Dry::Types::Schema]
|
|
301
|
+
#
|
|
302
|
+
# @api private
|
|
303
|
+
def strict_type_schema
|
|
304
|
+
type_registry["hash"].schema(types)
|
|
296
305
|
end
|
|
297
306
|
|
|
298
307
|
# Return a new DSL instance using the same processor type
|
|
@@ -314,9 +323,9 @@ module Dry
|
|
|
314
323
|
# @api private
|
|
315
324
|
def set_type(name, spec)
|
|
316
325
|
type = resolve_type(spec)
|
|
317
|
-
meta = {required:
|
|
326
|
+
meta = {required: true, maybe: type.optional?}
|
|
318
327
|
|
|
319
|
-
types[name] = type.meta(meta)
|
|
328
|
+
@types[name] = type.meta(meta)
|
|
320
329
|
end
|
|
321
330
|
|
|
322
331
|
# Check if a custom type was set under provided key name
|
|
@@ -369,6 +378,18 @@ module Dry
|
|
|
369
378
|
parents.any?(&:filter_rules?)
|
|
370
379
|
end
|
|
371
380
|
|
|
381
|
+
# This DSL's type map merged with any parent type maps
|
|
382
|
+
#
|
|
383
|
+
# @api private
|
|
384
|
+
def types
|
|
385
|
+
[*parents.map(&:types), @types].reduce(:merge)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# @api private
|
|
389
|
+
def merge_types(op_class, lhs, rhs)
|
|
390
|
+
types_merger.(op_class, lhs, rhs)
|
|
391
|
+
end
|
|
392
|
+
|
|
372
393
|
protected
|
|
373
394
|
|
|
374
395
|
# Build a rule applier
|
|
@@ -495,6 +516,10 @@ module Dry
|
|
|
495
516
|
|
|
496
517
|
(parent || Schema).config.dup
|
|
497
518
|
end
|
|
519
|
+
|
|
520
|
+
def types_merger
|
|
521
|
+
@types_merger ||= TypesMerger.new(type_registry)
|
|
522
|
+
end
|
|
498
523
|
end
|
|
499
524
|
end
|
|
500
525
|
end
|
data/lib/dry/schema/key_map.rb
CHANGED
|
@@ -15,7 +15,7 @@ module Dry
|
|
|
15
15
|
def value(*args, **opts, &block)
|
|
16
16
|
type(:array)
|
|
17
17
|
|
|
18
|
-
extract_type_spec(
|
|
18
|
+
extract_type_spec(args, set_type: false) do |*predicates, type_spec:, type_rule:|
|
|
19
19
|
type(schema_dsl.array[type_spec]) if type_spec
|
|
20
20
|
|
|
21
21
|
is_hash_block = type_spec.equal?(:hash)
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "dry/logic/operators"
|
|
4
|
-
|
|
5
3
|
require "dry/schema/macros/core"
|
|
6
4
|
require "dry/schema/predicate_inferrer"
|
|
7
5
|
require "dry/schema/primitive_inferrer"
|
|
@@ -58,12 +56,13 @@ module Dry
|
|
|
58
56
|
# @return [Macros::Core]
|
|
59
57
|
#
|
|
60
58
|
# @api public
|
|
61
|
-
def value(
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
def value(*args, **opts, &block)
|
|
60
|
+
extract_type_spec(args) do |*predicates, type_spec:, type_rule:|
|
|
61
|
+
append_macro(Macros::Value) do |macro|
|
|
62
|
+
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
63
|
+
end
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
|
-
ruby2_keywords :value if respond_to?(:ruby2_keywords, true)
|
|
67
66
|
|
|
68
67
|
# Prepends `:filled?` predicate
|
|
69
68
|
#
|
|
@@ -76,12 +75,31 @@ module Dry
|
|
|
76
75
|
# @return [Macros::Core]
|
|
77
76
|
#
|
|
78
77
|
# @api public
|
|
79
|
-
def filled(
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
def filled(*args, **opts, &block)
|
|
79
|
+
extract_type_spec(args) do |*predicates, type_spec:, type_rule:|
|
|
80
|
+
append_macro(Macros::Filled) do |macro|
|
|
81
|
+
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Set type specification and predicates for a maybe value
|
|
87
|
+
#
|
|
88
|
+
# @example
|
|
89
|
+
# required(:name).maybe(:string)
|
|
90
|
+
#
|
|
91
|
+
# @see Macros::Key#value
|
|
92
|
+
#
|
|
93
|
+
# @return [Macros::Key]
|
|
94
|
+
#
|
|
95
|
+
# @api public
|
|
96
|
+
def maybe(*args, **opts, &block)
|
|
97
|
+
extract_type_spec(args, nullable: true) do |*predicates, type_spec:, type_rule:|
|
|
98
|
+
append_macro(Macros::Maybe) do |macro|
|
|
99
|
+
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
100
|
+
end
|
|
82
101
|
end
|
|
83
102
|
end
|
|
84
|
-
ruby2_keywords :filled if respond_to?(:ruby2_keywords, true)
|
|
85
103
|
|
|
86
104
|
# Specify a nested hash without enforced `hash?` type-check
|
|
87
105
|
#
|
|
@@ -201,7 +219,7 @@ module Dry
|
|
|
201
219
|
|
|
202
220
|
# @api private
|
|
203
221
|
# rubocop: disable Metrics/PerceivedComplexity
|
|
204
|
-
def extract_type_spec(
|
|
222
|
+
def extract_type_spec(args, nullable: false, set_type: true)
|
|
205
223
|
type_spec = args[0] unless schema_or_predicate?(args[0])
|
|
206
224
|
|
|
207
225
|
predicates = Array(type_spec ? args[1..] : args)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "dry/types/type"
|
|
4
3
|
require "dry/schema/macros/dsl"
|
|
5
4
|
|
|
6
5
|
module Dry
|
|
@@ -11,13 +10,15 @@ module Dry
|
|
|
11
10
|
# @api private
|
|
12
11
|
class Each < DSL
|
|
13
12
|
# @api private
|
|
14
|
-
def value(*args, **opts)
|
|
15
|
-
extract_type_spec(
|
|
13
|
+
def value(*args, **opts, &block)
|
|
14
|
+
extract_type_spec(args, set_type: false) do |*predicates, type_spec:, type_rule:|
|
|
16
15
|
if type_spec && !type_spec.is_a?(Dry::Types::Type)
|
|
17
16
|
type(schema_dsl.array[type_spec])
|
|
18
17
|
end
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
append_macro(Macros::Value) do |macro|
|
|
20
|
+
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
21
|
+
end
|
|
21
22
|
end
|
|
22
23
|
end
|
|
23
24
|
|
|
@@ -13,12 +13,15 @@ module Dry
|
|
|
13
13
|
def call(*predicates, **opts, &block)
|
|
14
14
|
ensure_valid_predicates(predicates)
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
append_macro(Macros::Value) do |macro|
|
|
17
|
+
if opts[:type_spec] && !filter_empty_string?
|
|
18
|
+
macro.call(predicates[0], :filled?, *predicates[1..predicates.size - 1], **opts,
|
|
19
|
+
&block)
|
|
20
|
+
elsif opts[:type_rule]
|
|
21
|
+
macro.call(:filled?).value(*predicates, **opts, &block)
|
|
22
|
+
else
|
|
23
|
+
macro.call(:filled?, *predicates, **opts, &block)
|
|
24
|
+
end
|
|
22
25
|
end
|
|
23
26
|
end
|
|
24
27
|
|
|
@@ -32,67 +32,6 @@ module Dry
|
|
|
32
32
|
end
|
|
33
33
|
ruby2_keywords(:filter) if respond_to?(:ruby2_keywords, true)
|
|
34
34
|
|
|
35
|
-
# @overload value(type_spec, *predicates, **predicate_opts)
|
|
36
|
-
# Set type specification and predicates
|
|
37
|
-
#
|
|
38
|
-
# @param [Symbol,Types::Type,Array] type_spec
|
|
39
|
-
# @param [Array<Symbol>] predicates
|
|
40
|
-
# @param [Hash] predicate_opts
|
|
41
|
-
#
|
|
42
|
-
# @example with a predicate
|
|
43
|
-
# required(:name).value(:string, :filled?)
|
|
44
|
-
#
|
|
45
|
-
# @example with a predicate with arguments
|
|
46
|
-
# required(:name).value(:string, min_size?: 2)
|
|
47
|
-
#
|
|
48
|
-
# @example with a block
|
|
49
|
-
# required(:name).value(:string) { filled? & min_size?(2) }
|
|
50
|
-
#
|
|
51
|
-
# @return [Macros::Key]
|
|
52
|
-
#
|
|
53
|
-
# @see Macros::DSL#value
|
|
54
|
-
#
|
|
55
|
-
# @api public
|
|
56
|
-
def value(*args, **opts, &block)
|
|
57
|
-
extract_type_spec(*args) do |*predicates, type_spec:, type_rule:|
|
|
58
|
-
super(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Set type specification and predicates for a filled value
|
|
63
|
-
#
|
|
64
|
-
# @example
|
|
65
|
-
# required(:name).filled(:string)
|
|
66
|
-
#
|
|
67
|
-
# @see Macros::Key#value
|
|
68
|
-
#
|
|
69
|
-
# @return [Macros::Key]
|
|
70
|
-
#
|
|
71
|
-
# @api public
|
|
72
|
-
def filled(*args, **opts, &block)
|
|
73
|
-
extract_type_spec(*args) do |*predicates, type_spec:, type_rule:|
|
|
74
|
-
super(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# Set type specification and predicates for a maybe value
|
|
79
|
-
#
|
|
80
|
-
# @example
|
|
81
|
-
# required(:name).maybe(:string)
|
|
82
|
-
#
|
|
83
|
-
# @see Macros::Key#value
|
|
84
|
-
#
|
|
85
|
-
# @return [Macros::Key]
|
|
86
|
-
#
|
|
87
|
-
# @api public
|
|
88
|
-
def maybe(*args, **opts, &block)
|
|
89
|
-
extract_type_spec(*args, nullable: true) do |*predicates, type_spec:, type_rule:|
|
|
90
|
-
append_macro(Macros::Maybe) do |macro|
|
|
91
|
-
macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block)
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
35
|
# Coerce macro to a rule
|
|
97
36
|
#
|
|
98
37
|
# @return [Dry::Logic::Rule]
|
|
@@ -30,13 +30,7 @@ module Dry
|
|
|
30
30
|
|
|
31
31
|
# @api private
|
|
32
32
|
def process_operation(op)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
hash_schema = hash_type.schema(
|
|
36
|
-
schemas.map(&:schema_dsl).map(&:types).reduce(:merge)
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
type(hash_schema)
|
|
33
|
+
type(hash_type.schema(merge_operation_types(op)))
|
|
40
34
|
end
|
|
41
35
|
|
|
42
36
|
# @api private
|
|
@@ -44,6 +38,23 @@ module Dry
|
|
|
44
38
|
schema_dsl.resolve_type(:hash)
|
|
45
39
|
end
|
|
46
40
|
|
|
41
|
+
# @api private
|
|
42
|
+
def merge_operation_types(op)
|
|
43
|
+
op.rules.reduce({}) do |acc, rule|
|
|
44
|
+
types =
|
|
45
|
+
case rule
|
|
46
|
+
when Dry::Logic::Operations::Abstract
|
|
47
|
+
merge_operation_types(rule)
|
|
48
|
+
when Processor
|
|
49
|
+
rule.types
|
|
50
|
+
else
|
|
51
|
+
EMPTY_HASH.dup
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
schema_dsl.merge_types(op.class, acc, types)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
47
58
|
# @api private
|
|
48
59
|
# rubocop: disable Metrics/AbcSize
|
|
49
60
|
def define(*args, &block)
|
|
@@ -51,11 +62,11 @@ module Dry
|
|
|
51
62
|
schema = definition.call
|
|
52
63
|
type_schema =
|
|
53
64
|
if array_type?(parent_type)
|
|
54
|
-
build_array_type(parent_type, definition.
|
|
65
|
+
build_array_type(parent_type, definition.strict_type_schema)
|
|
55
66
|
elsif redefined_schema?(args)
|
|
56
67
|
parent_type.schema(definition.types)
|
|
57
68
|
else
|
|
58
|
-
definition.
|
|
69
|
+
definition.strict_type_schema
|
|
59
70
|
end
|
|
60
71
|
final_type = optional? ? type_schema.optional : type_schema
|
|
61
72
|
|
|
@@ -30,9 +30,9 @@ module Dry
|
|
|
30
30
|
|
|
31
31
|
updated_type =
|
|
32
32
|
if array_type?(current_type)
|
|
33
|
-
build_array_type(current_type, schema.
|
|
33
|
+
build_array_type(current_type, schema.strict_type_schema)
|
|
34
34
|
else
|
|
35
|
-
schema.
|
|
35
|
+
schema.strict_type_schema
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
import_steps(schema)
|
|
@@ -34,17 +34,16 @@ module Dry
|
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
def self.handler(message)
|
|
39
|
-
handlers.find { |k,| message.is_a?(k) }&.last
|
|
40
|
-
end
|
|
37
|
+
MESSAGE_ARRAY_HANDLER = -> { MessageArray.new(_1) }
|
|
41
38
|
|
|
42
39
|
# @api private
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
def self.handler(message)
|
|
41
|
+
case message
|
|
42
|
+
when self
|
|
43
|
+
IDENTITY
|
|
44
|
+
when Array
|
|
45
|
+
MESSAGE_ARRAY_HANDLER
|
|
46
|
+
end
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
# @api public
|
|
@@ -59,7 +58,7 @@ module Dry
|
|
|
59
58
|
|
|
60
59
|
# @api private
|
|
61
60
|
def root
|
|
62
|
-
@root ||=
|
|
61
|
+
@root ||= _paths.reduce(:&)
|
|
63
62
|
end
|
|
64
63
|
|
|
65
64
|
# @api private
|
|
@@ -67,9 +66,14 @@ module Dry
|
|
|
67
66
|
root
|
|
68
67
|
end
|
|
69
68
|
|
|
69
|
+
# @api private
|
|
70
|
+
def _path
|
|
71
|
+
@_path ||= Path[root]
|
|
72
|
+
end
|
|
73
|
+
|
|
70
74
|
# @api private
|
|
71
75
|
def _paths
|
|
72
|
-
@paths ||=
|
|
76
|
+
@paths ||= _messages.flat_map(&:_paths)
|
|
73
77
|
end
|
|
74
78
|
|
|
75
79
|
# @api private
|
|
@@ -21,10 +21,11 @@ module Dry
|
|
|
21
21
|
|
|
22
22
|
# @api private
|
|
23
23
|
def initialize(*args, messages)
|
|
24
|
-
super(*args)
|
|
24
|
+
super(*args.map { [_1].flatten })
|
|
25
25
|
@messages = messages
|
|
26
|
-
|
|
27
|
-
@
|
|
26
|
+
message = left.first
|
|
27
|
+
@path = message.path
|
|
28
|
+
@_path = message._path
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
# Dump a message into a string
|
|
@@ -38,7 +39,7 @@ module Dry
|
|
|
38
39
|
#
|
|
39
40
|
# @api public
|
|
40
41
|
def dump
|
|
41
|
-
@dump ||=
|
|
42
|
+
@dump ||= [*left, *right].map(&:dump).join(" #{messages[:or]} ")
|
|
42
43
|
end
|
|
43
44
|
alias_method :to_s, :dump
|
|
44
45
|
|
|
@@ -55,7 +56,16 @@ module Dry
|
|
|
55
56
|
|
|
56
57
|
# @api private
|
|
57
58
|
def to_a
|
|
58
|
-
@to_a ||= [left, right]
|
|
59
|
+
@to_a ||= [*left, *right]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @api private
|
|
63
|
+
def to_or(root)
|
|
64
|
+
to_ored = [left, right].map do |msgs|
|
|
65
|
+
msgs.map { _1.to_or(root) }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
self.class.new(*to_ored, messages)
|
|
59
69
|
end
|
|
60
70
|
end
|
|
61
71
|
end
|
data/lib/dry/schema/message.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "dry/core/equalizer"
|
|
4
|
-
|
|
5
3
|
module Dry
|
|
6
4
|
module Schema
|
|
7
5
|
# A set of messages used to generate errors
|
|
@@ -105,7 +103,7 @@ module Dry
|
|
|
105
103
|
|
|
106
104
|
# @api private
|
|
107
105
|
def messages_map(messages = self.messages)
|
|
108
|
-
combine_message_hashes(messages.map(&:to_h))
|
|
106
|
+
combine_message_hashes(messages.map(&:to_h)).freeze
|
|
109
107
|
end
|
|
110
108
|
|
|
111
109
|
# @api private
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
require "yaml"
|
|
4
4
|
require "pathname"
|
|
5
5
|
|
|
6
|
-
require "dry/core/equalizer"
|
|
7
6
|
require "dry/schema/constants"
|
|
8
7
|
require "dry/schema/messages/abstract"
|
|
9
8
|
|
|
@@ -169,11 +168,9 @@ module Dry
|
|
|
169
168
|
text = input.gsub("%", "#")
|
|
170
169
|
|
|
171
170
|
# rubocop:disable Security/Eval
|
|
172
|
-
# rubocop:disable Style/DocumentDynamicEvalDefinition
|
|
173
171
|
evaluator = eval(<<~RUBY, EMPTY_CONTEXT, __FILE__, __LINE__ + 1)
|
|
174
172
|
-> (#{tokens.map { |token| "#{token}:" }.join(", ")}) { "#{text}" }
|
|
175
173
|
RUBY
|
|
176
|
-
# rubocop:enable Style/DocumentDynamicEvalDefinition
|
|
177
174
|
# rubocop:enable Security/Eval
|
|
178
175
|
|
|
179
176
|
{
|
data/lib/dry/schema/predicate.rb
CHANGED
data/lib/dry/schema/processor.rb
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "dry/configurable"
|
|
4
3
|
require "dry/initializer"
|
|
5
|
-
require "dry/logic/operators"
|
|
6
4
|
|
|
7
5
|
require "dry/schema/type_registry"
|
|
8
6
|
require "dry/schema/type_container"
|
|
@@ -138,13 +136,22 @@ module Dry
|
|
|
138
136
|
|
|
139
137
|
# Return the type schema
|
|
140
138
|
#
|
|
141
|
-
# @return [Dry::Types::
|
|
139
|
+
# @return [Dry::Types::Lax]
|
|
142
140
|
#
|
|
143
141
|
# @api private
|
|
144
142
|
def type_schema
|
|
145
143
|
steps.type_schema
|
|
146
144
|
end
|
|
147
145
|
|
|
146
|
+
# Return type schema used when composing subschemas
|
|
147
|
+
#
|
|
148
|
+
# @return [Dry::Types::Schema]
|
|
149
|
+
#
|
|
150
|
+
# @api private
|
|
151
|
+
def strict_type_schema
|
|
152
|
+
schema_dsl.strict_type_schema
|
|
153
|
+
end
|
|
154
|
+
|
|
148
155
|
# Return the rule applier
|
|
149
156
|
#
|
|
150
157
|
# @api private
|
|
@@ -188,6 +195,13 @@ module Dry
|
|
|
188
195
|
rule_applier.rules
|
|
189
196
|
end
|
|
190
197
|
|
|
198
|
+
# Return the types from the schema DSL
|
|
199
|
+
#
|
|
200
|
+
# @api private
|
|
201
|
+
def types
|
|
202
|
+
schema_dsl.types
|
|
203
|
+
end
|
|
204
|
+
|
|
191
205
|
# Check if there are filter rules
|
|
192
206
|
#
|
|
193
207
|
# @api private
|
data/lib/dry/schema/result.rb
CHANGED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dry
|
|
4
|
+
module Schema
|
|
5
|
+
# Combines multiple logical operations into a single type, taking into
|
|
6
|
+
# account the type of logical operation (or, and, implication) and the
|
|
7
|
+
# underlying types (schemas, nominals, etc.)
|
|
8
|
+
#
|
|
9
|
+
# @api private
|
|
10
|
+
class TypesMerger
|
|
11
|
+
attr_reader :type_registry
|
|
12
|
+
|
|
13
|
+
# @api private
|
|
14
|
+
class ValueMerger
|
|
15
|
+
attr_reader :types_merger
|
|
16
|
+
attr_reader :op_class
|
|
17
|
+
attr_reader :old
|
|
18
|
+
attr_reader :new
|
|
19
|
+
|
|
20
|
+
# @api private
|
|
21
|
+
def initialize(types_merger, op_class, old, new)
|
|
22
|
+
@types_merger = types_merger
|
|
23
|
+
@op_class = op_class
|
|
24
|
+
@old = old
|
|
25
|
+
@new = new
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @api private
|
|
29
|
+
def call
|
|
30
|
+
if op_class <= Dry::Logic::Operations::Or
|
|
31
|
+
merge_or
|
|
32
|
+
elsif op_class <= Dry::Logic::Operations::And
|
|
33
|
+
merge_and
|
|
34
|
+
elsif op_class <= Dry::Logic::Operations::Implication
|
|
35
|
+
merge_implication
|
|
36
|
+
else
|
|
37
|
+
raise ArgumentError, <<~MESSAGE
|
|
38
|
+
Can't merge operations, op_class=#{op_class}
|
|
39
|
+
MESSAGE
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
# @api private
|
|
46
|
+
def merge_or
|
|
47
|
+
old | new
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @api private
|
|
51
|
+
def merge_ordered
|
|
52
|
+
return old if old == new
|
|
53
|
+
|
|
54
|
+
unwrapped_old, old_rule = unwrap_type(old)
|
|
55
|
+
unwrapped_new, new_rule = unwrap_type(new)
|
|
56
|
+
|
|
57
|
+
type = merge_unwrapped_types(unwrapped_old, unwrapped_new)
|
|
58
|
+
|
|
59
|
+
rule = [old_rule, new_rule].compact.reduce { op_class.new(_1, _2) }
|
|
60
|
+
|
|
61
|
+
type = Dry::Types::Constrained.new(type, rule: rule) if rule
|
|
62
|
+
|
|
63
|
+
type
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
alias_method :merge_and, :merge_ordered
|
|
67
|
+
alias_method :merge_implication, :merge_ordered
|
|
68
|
+
|
|
69
|
+
# @api private
|
|
70
|
+
def merge_unwrapped_types(unwrapped_old, unwrapped_new)
|
|
71
|
+
case [unwrapped_old, unwrapped_new]
|
|
72
|
+
in Dry::Types::Schema, Dry::Types::Schema
|
|
73
|
+
merge_schemas(unwrapped_old, unwrapped_new)
|
|
74
|
+
in [Dry::Types::AnyClass, _] | [Dry::Types::Hash, Dry::Types::Schema]
|
|
75
|
+
unwrapped_new
|
|
76
|
+
in [Dry::Types::Schema, Dry::Types::Hash] | [_, Dry::Types::AnyClass]
|
|
77
|
+
unwrapped_old
|
|
78
|
+
else
|
|
79
|
+
merge_equivalent_types(unwrapped_old, unwrapped_new)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# @api private
|
|
84
|
+
def merge_schemas(unwrapped_old, unwrapped_new)
|
|
85
|
+
types_merger.type_registry["hash"].schema(
|
|
86
|
+
types_merger.call(
|
|
87
|
+
op_class,
|
|
88
|
+
unwrapped_old.name_key_map,
|
|
89
|
+
unwrapped_new.name_key_map
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @api private
|
|
95
|
+
def merge_equivalent_types(unwrapped_old, unwrapped_new)
|
|
96
|
+
if unwrapped_old.primitive <= unwrapped_new.primitive
|
|
97
|
+
unwrapped_new
|
|
98
|
+
elsif unwrapped_new.primitive <= unwrapped_old.primitive
|
|
99
|
+
unwrapped_old
|
|
100
|
+
else
|
|
101
|
+
raise ArgumentError, <<~MESSAGE
|
|
102
|
+
Can't merge types, unwrapped_old=#{unwrapped_old.inspect}, unwrapped_new=#{unwrapped_new.inspect}
|
|
103
|
+
MESSAGE
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# @api private
|
|
108
|
+
def unwrap_type(type)
|
|
109
|
+
rules = []
|
|
110
|
+
|
|
111
|
+
loop do
|
|
112
|
+
rules << type.rule if type.respond_to?(:rule)
|
|
113
|
+
|
|
114
|
+
if type.optional?
|
|
115
|
+
type = type.left.primitive?(nil) ? type.right : type.left
|
|
116
|
+
elsif type.is_a?(Dry::Types::Decorator)
|
|
117
|
+
type = type.type
|
|
118
|
+
else
|
|
119
|
+
break
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
[type, rules.reduce(:&)]
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def initialize(type_registry = TypeRegistry.new)
|
|
128
|
+
@type_registry = type_registry
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# @api private
|
|
132
|
+
def call(op_class, lhs, rhs)
|
|
133
|
+
lhs.merge(rhs) do |_k, old, new|
|
|
134
|
+
ValueMerger.new(self, op_class, old, new).call
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
data/lib/dry/schema/version.rb
CHANGED
data/lib/dry/schema.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dry-schema
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.10.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Piotr Solnica
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-09-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: concurrent-ruby
|
|
@@ -50,20 +50,20 @@ dependencies:
|
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '0.
|
|
53
|
+
version: '0.9'
|
|
54
54
|
- - ">="
|
|
55
55
|
- !ruby/object:Gem::Version
|
|
56
|
-
version: '0.
|
|
56
|
+
version: '0.9'
|
|
57
57
|
type: :runtime
|
|
58
58
|
prerelease: false
|
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
|
60
60
|
requirements:
|
|
61
61
|
- - "~>"
|
|
62
62
|
- !ruby/object:Gem::Version
|
|
63
|
-
version: '0.
|
|
63
|
+
version: '0.9'
|
|
64
64
|
- - ">="
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: '0.
|
|
66
|
+
version: '0.9'
|
|
67
67
|
- !ruby/object:Gem::Dependency
|
|
68
68
|
name: dry-initializer
|
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -84,28 +84,28 @@ dependencies:
|
|
|
84
84
|
requirements:
|
|
85
85
|
- - "~>"
|
|
86
86
|
- !ruby/object:Gem::Version
|
|
87
|
-
version: '1.
|
|
87
|
+
version: '1.3'
|
|
88
88
|
type: :runtime
|
|
89
89
|
prerelease: false
|
|
90
90
|
version_requirements: !ruby/object:Gem::Requirement
|
|
91
91
|
requirements:
|
|
92
92
|
- - "~>"
|
|
93
93
|
- !ruby/object:Gem::Version
|
|
94
|
-
version: '1.
|
|
94
|
+
version: '1.3'
|
|
95
95
|
- !ruby/object:Gem::Dependency
|
|
96
96
|
name: dry-types
|
|
97
97
|
requirement: !ruby/object:Gem::Requirement
|
|
98
98
|
requirements:
|
|
99
99
|
- - "~>"
|
|
100
100
|
- !ruby/object:Gem::Version
|
|
101
|
-
version: '1.
|
|
101
|
+
version: '1.6'
|
|
102
102
|
type: :runtime
|
|
103
103
|
prerelease: false
|
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
|
105
105
|
requirements:
|
|
106
106
|
- - "~>"
|
|
107
107
|
- !ruby/object:Gem::Version
|
|
108
|
-
version: '1.
|
|
108
|
+
version: '1.6'
|
|
109
109
|
- !ruby/object:Gem::Dependency
|
|
110
110
|
name: bundler
|
|
111
111
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -230,6 +230,7 @@ files:
|
|
|
230
230
|
- lib/dry/schema/type_container.rb
|
|
231
231
|
- lib/dry/schema/type_registry.rb
|
|
232
232
|
- lib/dry/schema/types.rb
|
|
233
|
+
- lib/dry/schema/types_merger.rb
|
|
233
234
|
- lib/dry/schema/value_coercer.rb
|
|
234
235
|
- lib/dry/schema/version.rb
|
|
235
236
|
homepage: https://dry-rb.org/gems/dry-schema
|