dry-schema 1.13.4 → 1.14.1
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 +20 -0
- data/README.md +1 -1
- data/config/errors.yml +9 -1
- data/dry-schema.gemspec +15 -17
- data/lib/dry/schema/config.rb +6 -6
- data/lib/dry/schema/constants.rb +2 -2
- data/lib/dry/schema/dsl.rb +18 -18
- data/lib/dry/schema/extensions/hints/message_compiler_methods.rb +1 -1
- data/lib/dry/schema/extensions/info/schema_compiler.rb +16 -7
- data/lib/dry/schema/extensions/json_schema/schema_compiler.rb +3 -3
- data/lib/dry/schema/extensions/monads.rb +1 -1
- data/lib/dry/schema/extensions/struct.rb +3 -3
- data/lib/dry/schema/key.rb +4 -4
- data/lib/dry/schema/key_coercer.rb +3 -3
- data/lib/dry/schema/key_map.rb +5 -5
- data/lib/dry/schema/key_validator.rb +19 -8
- data/lib/dry/schema/macros/dsl.rb +1 -1
- data/lib/dry/schema/macros/filled.rb +1 -2
- data/lib/dry/schema/macros/hash.rb +1 -1
- data/lib/dry/schema/macros/schema.rb +3 -3
- data/lib/dry/schema/macros/value.rb +12 -12
- data/lib/dry/schema/message.rb +4 -4
- data/lib/dry/schema/message_compiler.rb +8 -8
- data/lib/dry/schema/message_set.rb +8 -8
- data/lib/dry/schema/messages/abstract.rb +12 -12
- data/lib/dry/schema/messages/namespaced.rb +1 -1
- data/lib/dry/schema/messages/template.rb +2 -2
- data/lib/dry/schema/messages/yaml.rb +3 -3
- data/lib/dry/schema/path.rb +12 -12
- data/lib/dry/schema/predicate.rb +4 -4
- data/lib/dry/schema/predicate_registry.rb +2 -2
- data/lib/dry/schema/processor.rb +10 -10
- data/lib/dry/schema/processor_steps.rb +1 -1
- data/lib/dry/schema/result.rb +6 -6
- data/lib/dry/schema/rule_applier.rb +1 -1
- data/lib/dry/schema/trace.rb +1 -1
- data/lib/dry/schema/type_container.rb +2 -2
- data/lib/dry/schema/type_registry.rb +1 -1
- data/lib/dry/schema/types.rb +1 -1
- data/lib/dry/schema/types_merger.rb +18 -62
- data/lib/dry/schema/value_coercer.rb +1 -1
- data/lib/dry/schema/version.rb +1 -1
- data/lib/dry/schema.rb +11 -11
- metadata +20 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6967bfe7737c11a9df20fc846698f42a911e454cb8c1621d20bc69d93e53dca
|
4
|
+
data.tar.gz: 0a97d750986808ca32535839e779485018d9a7eba1d6a5f09f2128e93f8bbaef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b42eb4a52a991fdf5605d8dc69b6b7362578ef140e272a2cff4ef0fc3852e01797714dfbe2507f9aa05ef6885b738413bd8f93536e4aabb8cccbd1c8a23e7cf1
|
7
|
+
data.tar.gz: a59cc89f18b981031fc7df87e0c3df9692512617dc0bdc35a417a5dce55196788262969ea742da0957a0616a9a0f648c78b4905abb031977570da0751002572b
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
2
2
|
|
3
|
+
## 1.14.0 2025-01-06
|
4
|
+
|
5
|
+
|
6
|
+
### Added
|
7
|
+
|
8
|
+
- Better support for sets in `excluded_from?` and `included_in?` predicates (via #480) (@flash-gordon)
|
9
|
+
|
10
|
+
### Fixed
|
11
|
+
|
12
|
+
- Fix info extension for maybe macro (via #484) (@flash-gordon + @santiagodoldan)
|
13
|
+
- Missing message for :uri? predicate (via #477) (@timjnh)
|
14
|
+
- JSON schema output for `maybe(:array)` (via #463) (@tomgi)
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
|
18
|
+
- Set minimum Ruby version to 3.1 (@flash-gordon)
|
19
|
+
- `KeyValidator` works faster for large schemas (via #461) (@radarek)
|
20
|
+
|
21
|
+
[Compare v1.13.4...v1.14.0](https://github.com/dry-rb/dry-schema/compare/v1.13.4...v1.14.0)
|
22
|
+
|
3
23
|
## 1.13.4 2024-05-22
|
4
24
|
|
5
25
|
|
data/README.md
CHANGED
data/config/errors.yml
CHANGED
@@ -105,9 +105,17 @@ en:
|
|
105
105
|
default: "must be %{size} bytes long"
|
106
106
|
range: "must be within %{size_left} - %{size_right} bytes long"
|
107
107
|
|
108
|
+
uri?: "is not a valid URI"
|
109
|
+
|
110
|
+
uuid_v1?: "is not a valid UUID"
|
111
|
+
|
112
|
+
uuid_v2?: "is not a valid UUID"
|
113
|
+
|
114
|
+
uuid_v3?: "is not a valid UUID"
|
115
|
+
|
108
116
|
uuid_v4?: "is not a valid UUID"
|
109
117
|
|
110
|
-
|
118
|
+
uuid_v5?: "is not a valid UUID"
|
111
119
|
|
112
120
|
not:
|
113
121
|
empty?: "cannot be empty"
|
data/dry-schema.gemspec
CHANGED
@@ -21,28 +21,26 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
TEXT
|
23
23
|
spec.homepage = "https://dry-rb.org/gems/dry-schema"
|
24
|
-
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-schema.gemspec",
|
24
|
+
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-schema.gemspec",
|
25
|
+
"lib/**/*", "config/*.yml"]
|
25
26
|
spec.bindir = "bin"
|
26
27
|
spec.executables = []
|
27
28
|
spec.require_paths = ["lib"]
|
28
29
|
|
29
|
-
spec.metadata["allowed_push_host"]
|
30
|
-
spec.metadata["changelog_uri"]
|
31
|
-
spec.metadata["source_code_uri"]
|
32
|
-
spec.metadata["bug_tracker_uri"]
|
30
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
31
|
+
spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-schema/blob/main/CHANGELOG.md"
|
32
|
+
spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-schema"
|
33
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-schema/issues"
|
34
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
33
35
|
|
34
|
-
spec.required_ruby_version = ">=
|
36
|
+
spec.required_ruby_version = ">= 3.1"
|
35
37
|
|
36
38
|
# to update dependencies edit project.yml
|
37
|
-
spec.
|
38
|
-
spec.
|
39
|
-
spec.
|
40
|
-
spec.
|
41
|
-
spec.
|
42
|
-
spec.
|
43
|
-
spec.
|
44
|
-
|
45
|
-
spec.add_development_dependency "bundler"
|
46
|
-
spec.add_development_dependency "rake"
|
47
|
-
spec.add_development_dependency "rspec"
|
39
|
+
spec.add_dependency "concurrent-ruby", "~> 1.0"
|
40
|
+
spec.add_dependency "dry-configurable", "~> 1.0", ">= 1.0.1"
|
41
|
+
spec.add_dependency "dry-core", "~> 1.1"
|
42
|
+
spec.add_dependency "dry-initializer", "~> 3.2"
|
43
|
+
spec.add_dependency "dry-logic", "~> 1.5"
|
44
|
+
spec.add_dependency "dry-types", "~> 1.8"
|
45
|
+
spec.add_dependency "zeitwerk", "~> 2.6"
|
48
46
|
end
|
data/lib/dry/schema/config.rb
CHANGED
@@ -12,8 +12,8 @@ module Dry
|
|
12
12
|
#
|
13
13
|
# @api public
|
14
14
|
class Config
|
15
|
-
include Dry::Configurable
|
16
|
-
include Dry::Equalizer(:to_h, inspect: false)
|
15
|
+
include ::Dry::Configurable
|
16
|
+
include ::Dry::Equalizer(:to_h, inspect: false)
|
17
17
|
|
18
18
|
# @!method predicates
|
19
19
|
#
|
@@ -33,7 +33,7 @@ module Dry
|
|
33
33
|
# @return [Hash]
|
34
34
|
#
|
35
35
|
# @api public
|
36
|
-
setting :types, default: Dry::Types
|
36
|
+
setting :types, default: ::Dry::Types
|
37
37
|
|
38
38
|
# @!method messages
|
39
39
|
#
|
@@ -45,7 +45,7 @@ module Dry
|
|
45
45
|
setting :messages do
|
46
46
|
setting :backend, default: :yaml
|
47
47
|
setting :namespace
|
48
|
-
setting :load_paths, default: Set[DEFAULT_MESSAGES_PATH], constructor: :dup.to_proc
|
48
|
+
setting :load_paths, default: ::Set[DEFAULT_MESSAGES_PATH], constructor: :dup.to_proc
|
49
49
|
setting :top_namespace, default: DEFAULT_MESSAGES_ROOT
|
50
50
|
setting :default_locale
|
51
51
|
end
|
@@ -74,9 +74,9 @@ module Dry
|
|
74
74
|
# Forward to the underlying config object
|
75
75
|
#
|
76
76
|
# @api private
|
77
|
-
def method_missing(meth,
|
77
|
+
def method_missing(meth, ...)
|
78
78
|
super unless config.respond_to?(meth)
|
79
|
-
config.public_send(meth,
|
79
|
+
config.public_send(meth, ...)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
data/lib/dry/schema/constants.rb
CHANGED
@@ -30,10 +30,10 @@ module Dry
|
|
30
30
|
DEFAULT_MESSAGES_ROOT = "dry_schema"
|
31
31
|
|
32
32
|
# An error raised when DSL is used in an incorrect way
|
33
|
-
InvalidSchemaError = Class.new(StandardError)
|
33
|
+
InvalidSchemaError = ::Class.new(::StandardError)
|
34
34
|
|
35
35
|
# An error raised when a localized message cannot be found
|
36
|
-
MissingMessageError = Class.new(StandardError) do
|
36
|
+
MissingMessageError = ::Class.new(::StandardError) do
|
37
37
|
# @api private
|
38
38
|
def initialize(path, paths = [])
|
39
39
|
*rest, rule = path
|
data/lib/dry/schema/dsl.rb
CHANGED
@@ -37,7 +37,7 @@ module Dry
|
|
37
37
|
class DSL
|
38
38
|
Types = Schema::Types
|
39
39
|
|
40
|
-
extend Dry::Initializer
|
40
|
+
extend ::Dry::Initializer
|
41
41
|
|
42
42
|
# @return [Compiler] The type of the processor (Params, JSON, or a custom sub-class)
|
43
43
|
option :processor_type, default: -> { Processor }
|
@@ -78,9 +78,9 @@ module Dry
|
|
78
78
|
# @return [DSL]
|
79
79
|
#
|
80
80
|
# @api public
|
81
|
-
def self.new(**options, &
|
81
|
+
def self.new(**options, &)
|
82
82
|
dsl = super
|
83
|
-
dsl.instance_eval(&
|
83
|
+
dsl.instance_eval(&) if block_given?
|
84
84
|
dsl.instance_variable_set("@compiler", options[:compiler]) if options[:compiler]
|
85
85
|
dsl
|
86
86
|
end
|
@@ -99,8 +99,8 @@ module Dry
|
|
99
99
|
# @return [DSL]
|
100
100
|
#
|
101
101
|
# @api public
|
102
|
-
def configure(&
|
103
|
-
config.configure(&
|
102
|
+
def configure(&)
|
103
|
+
config.configure(&)
|
104
104
|
self
|
105
105
|
end
|
106
106
|
|
@@ -141,8 +141,8 @@ module Dry
|
|
141
141
|
# @return [Macros::Required]
|
142
142
|
#
|
143
143
|
# @api public
|
144
|
-
def required(name, &
|
145
|
-
key(name, macro: Macros::Required, &
|
144
|
+
def required(name, &)
|
145
|
+
key(name, macro: Macros::Required, &)
|
146
146
|
end
|
147
147
|
|
148
148
|
# Define an optional key
|
@@ -157,8 +157,8 @@ module Dry
|
|
157
157
|
# @return [Macros::Optional]
|
158
158
|
#
|
159
159
|
# @api public
|
160
|
-
def optional(name, &
|
161
|
-
key(name, macro: Macros::Optional, &
|
160
|
+
def optional(name, &)
|
161
|
+
key(name, macro: Macros::Optional, &)
|
162
162
|
end
|
163
163
|
|
164
164
|
# A generic method for defining keys
|
@@ -170,7 +170,7 @@ module Dry
|
|
170
170
|
# @return [Macros::Key]
|
171
171
|
#
|
172
172
|
# @api public
|
173
|
-
def key(name, macro:, &
|
173
|
+
def key(name, macro:, &)
|
174
174
|
raise ArgumentError, "Key +#{name}+ is not a symbol" unless name.is_a?(::Symbol)
|
175
175
|
|
176
176
|
set_type(name, Types::Any.meta(default: true))
|
@@ -182,7 +182,7 @@ module Dry
|
|
182
182
|
filter_schema_dsl: filter_schema_dsl
|
183
183
|
)
|
184
184
|
|
185
|
-
macro.value(&
|
185
|
+
macro.value(&) if block_given?
|
186
186
|
macros << macro
|
187
187
|
macro
|
188
188
|
end
|
@@ -249,8 +249,8 @@ module Dry
|
|
249
249
|
# @return [DSL]
|
250
250
|
#
|
251
251
|
# @api public
|
252
|
-
def before(key, &
|
253
|
-
steps.before(key, &
|
252
|
+
def before(key, &)
|
253
|
+
steps.before(key, &)
|
254
254
|
self
|
255
255
|
end
|
256
256
|
|
@@ -264,8 +264,8 @@ module Dry
|
|
264
264
|
# @return [DSL]
|
265
265
|
#
|
266
266
|
# @api public
|
267
|
-
def after(key, &
|
268
|
-
steps.after(key, &
|
267
|
+
def after(key, &)
|
268
|
+
steps.after(key, &)
|
269
269
|
self
|
270
270
|
end
|
271
271
|
|
@@ -301,8 +301,8 @@ module Dry
|
|
301
301
|
# @return [Dry::Types::Safe]
|
302
302
|
#
|
303
303
|
# @api private
|
304
|
-
def new(klass: self.class, **options, &
|
305
|
-
klass.new(**options, processor_type: processor_type, config: config, &
|
304
|
+
def new(klass: self.class, **options, &)
|
305
|
+
klass.new(**options, processor_type: processor_type, config: config, &)
|
306
306
|
end
|
307
307
|
|
308
308
|
# Set a type for the given key name
|
@@ -501,7 +501,7 @@ module Dry
|
|
501
501
|
def default_config
|
502
502
|
parents.each_cons(2) do |left, right|
|
503
503
|
unless left.config == right.config
|
504
|
-
raise ArgumentError,
|
504
|
+
raise ::ArgumentError,
|
505
505
|
"Parent configs differ, left=#{left.inspect}, right=#{right.inspect}"
|
506
506
|
end
|
507
507
|
end
|
@@ -70,20 +70,25 @@ module Dry
|
|
70
70
|
|
71
71
|
# @api private
|
72
72
|
def visit_implication(node, opts = EMPTY_HASH)
|
73
|
-
node
|
74
|
-
|
73
|
+
case node
|
74
|
+
in [:not, [:predicate, [:nil?, _]]], el
|
75
|
+
visit(el, {**opts, nullable: true})
|
76
|
+
else
|
77
|
+
node.each do |el|
|
78
|
+
visit(el, {**opts, required: false})
|
79
|
+
end
|
75
80
|
end
|
76
81
|
end
|
77
82
|
|
78
83
|
# @api private
|
79
84
|
def visit_each(node, opts = EMPTY_HASH)
|
80
|
-
visit(node, opts
|
85
|
+
visit(node, {**opts, member: true})
|
81
86
|
end
|
82
87
|
|
83
88
|
# @api private
|
84
89
|
def visit_key(node, opts = EMPTY_HASH)
|
85
90
|
name, rest = node
|
86
|
-
visit(rest, opts
|
91
|
+
visit(rest, {**opts, key: name, required: true})
|
87
92
|
end
|
88
93
|
|
89
94
|
# @api private
|
@@ -93,19 +98,23 @@ module Dry
|
|
93
98
|
key = opts[:key]
|
94
99
|
|
95
100
|
if name.equal?(:key?)
|
96
|
-
keys[rest[0][1]] = {
|
101
|
+
keys[rest[0][1]] = {
|
102
|
+
required: opts.fetch(:required, true)
|
103
|
+
}
|
97
104
|
else
|
98
105
|
type = PREDICATE_TO_TYPE[name]
|
99
|
-
|
106
|
+
nullable = opts.fetch(:nullable, false)
|
107
|
+
assign_type(key, type, nullable) if type
|
100
108
|
end
|
101
109
|
end
|
102
110
|
|
103
111
|
# @api private
|
104
|
-
def assign_type(key, type)
|
112
|
+
def assign_type(key, type, nullable)
|
105
113
|
if keys[key][:type]
|
106
114
|
keys[key][:member] = type
|
107
115
|
else
|
108
116
|
keys[key][:type] = type
|
117
|
+
keys[key][:nullable] = nullable
|
109
118
|
end
|
110
119
|
end
|
111
120
|
end
|
@@ -9,7 +9,7 @@ module Dry
|
|
9
9
|
# @api private
|
10
10
|
class SchemaCompiler
|
11
11
|
# An error raised when a predicate cannot be converted
|
12
|
-
UnknownConversionError = Class.new(StandardError)
|
12
|
+
UnknownConversionError = ::Class.new(::StandardError)
|
13
13
|
|
14
14
|
IDENTITY = ->(v, _) { v }.freeze
|
15
15
|
TO_INTEGER = ->(v, _) { v.to_i }.freeze
|
@@ -97,7 +97,7 @@ module Dry
|
|
97
97
|
target_info = opts[:member] ? {items: target.to_h} : target.to_h
|
98
98
|
type = opts[:member] ? "array" : "object"
|
99
99
|
|
100
|
-
|
100
|
+
merge_opts!(keys[key], {type: type, **target_info})
|
101
101
|
end
|
102
102
|
|
103
103
|
# @api private
|
@@ -210,7 +210,7 @@ module Dry
|
|
210
210
|
orig_type = orig_opts[:type]
|
211
211
|
|
212
212
|
if orig_type && new_type && orig_type != new_type
|
213
|
-
new_opts[:type] = [orig_type, new_type]
|
213
|
+
new_opts[:type] = [orig_type, new_type].flatten.uniq
|
214
214
|
end
|
215
215
|
|
216
216
|
orig_opts.merge!(new_opts)
|
@@ -23,7 +23,7 @@ module Dry
|
|
23
23
|
def call(*args)
|
24
24
|
if args.size >= 1 && struct?(args[0])
|
25
25
|
if block_given?
|
26
|
-
raise ArgumentError, "blocks are not supported when using "\
|
26
|
+
raise ArgumentError, "blocks are not supported when using " \
|
27
27
|
"a struct class (#{name.inspect} => #{args[0]})"
|
28
28
|
end
|
29
29
|
|
@@ -44,7 +44,7 @@ module Dry
|
|
44
44
|
})
|
45
45
|
end
|
46
46
|
|
47
|
-
PredicateInferrer::Compiler.
|
48
|
-
PrimitiveInferrer::Compiler.
|
47
|
+
PredicateInferrer::Compiler.alias_method(:visit_struct, :visit_hash)
|
48
|
+
PrimitiveInferrer::Compiler.alias_method(:visit_struct, :visit_hash)
|
49
49
|
end
|
50
50
|
end
|
data/lib/dry/schema/key.rb
CHANGED
@@ -6,11 +6,11 @@ module Dry
|
|
6
6
|
#
|
7
7
|
# @api public
|
8
8
|
class Key
|
9
|
-
extend Dry::Core::Cache
|
9
|
+
extend ::Dry::Core::Cache
|
10
10
|
|
11
11
|
DEFAULT_COERCER = :itself.to_proc.freeze
|
12
12
|
|
13
|
-
include Dry.Equalizer(:name, :coercer)
|
13
|
+
include ::Dry.Equalizer(:name, :coercer)
|
14
14
|
|
15
15
|
# @return [Symbol] The key identifier
|
16
16
|
attr_reader :id
|
@@ -90,7 +90,7 @@ module Dry
|
|
90
90
|
#
|
91
91
|
# @api private
|
92
92
|
class Hash < self
|
93
|
-
include Dry.Equalizer(:name, :members, :coercer)
|
93
|
+
include ::Dry.Equalizer(:name, :members, :coercer)
|
94
94
|
|
95
95
|
# @api private
|
96
96
|
attr_reader :members
|
@@ -137,7 +137,7 @@ module Dry
|
|
137
137
|
#
|
138
138
|
# @api private
|
139
139
|
class Array < self
|
140
|
-
include Dry.Equalizer(:name, :member, :coercer)
|
140
|
+
include ::Dry.Equalizer(:name, :member, :coercer)
|
141
141
|
|
142
142
|
attr_reader :member
|
143
143
|
|
@@ -9,7 +9,7 @@ module Dry
|
|
9
9
|
#
|
10
10
|
# @api private
|
11
11
|
class KeyCoercer
|
12
|
-
extend Dry::Core::Cache
|
12
|
+
extend ::Dry::Core::Cache
|
13
13
|
include ::Dry::Equalizer(:key_map, :coercer)
|
14
14
|
|
15
15
|
TO_SYM = :to_sym.to_proc.freeze
|
@@ -27,8 +27,8 @@ module Dry
|
|
27
27
|
end
|
28
28
|
|
29
29
|
# @api private
|
30
|
-
def initialize(key_map, &
|
31
|
-
@key_map = key_map.coercible(&
|
30
|
+
def initialize(key_map, &)
|
31
|
+
@key_map = key_map.coercible(&)
|
32
32
|
end
|
33
33
|
|
34
34
|
# @api private
|
data/lib/dry/schema/key_map.rb
CHANGED
@@ -13,10 +13,10 @@ module Dry
|
|
13
13
|
#
|
14
14
|
# @api public
|
15
15
|
class KeyMap
|
16
|
-
extend Dry::Core::Cache
|
16
|
+
extend ::Dry::Core::Cache
|
17
17
|
|
18
|
-
include Dry.Equalizer(:keys)
|
19
|
-
include Enumerable
|
18
|
+
include ::Dry.Equalizer(:keys)
|
19
|
+
include ::Enumerable
|
20
20
|
|
21
21
|
# @return [Array<Key>] A list of defined key objects
|
22
22
|
attr_reader :keys
|
@@ -105,8 +105,8 @@ module Dry
|
|
105
105
|
# Iterate over keys
|
106
106
|
#
|
107
107
|
# @api public
|
108
|
-
def each(&
|
109
|
-
keys.each(&
|
108
|
+
def each(&)
|
109
|
+
keys.each(&)
|
110
110
|
end
|
111
111
|
|
112
112
|
# Return a new key map merged with the provided one
|
@@ -7,7 +7,7 @@ module Dry
|
|
7
7
|
module Schema
|
8
8
|
# @api private
|
9
9
|
class KeyValidator
|
10
|
-
extend Dry::Initializer
|
10
|
+
extend ::Dry::Initializer
|
11
11
|
|
12
12
|
INDEX_REGEX = /\[\d+\]/
|
13
13
|
DIGIT_REGEX = /\A\d+\z/
|
@@ -21,7 +21,7 @@ module Dry
|
|
21
21
|
input = result.to_h
|
22
22
|
|
23
23
|
input_paths = key_paths(input)
|
24
|
-
key_paths = key_map.to_dot_notation
|
24
|
+
key_paths = key_map.to_dot_notation.sort
|
25
25
|
|
26
26
|
input_paths.each do |path|
|
27
27
|
error_path = validate_path(key_paths, path)
|
@@ -40,20 +40,31 @@ module Dry
|
|
40
40
|
def validate_path(key_paths, path)
|
41
41
|
if path[INDEX_REGEX]
|
42
42
|
key = path.gsub(INDEX_REGEX, BRACKETS)
|
43
|
-
|
44
|
-
if key_paths.none? { paths_match?(key, _1) }
|
43
|
+
if none_key_paths_match?(key_paths, key)
|
45
44
|
arr = path.gsub(INDEX_REGEX) { ".#{_1[1]}" }
|
46
45
|
arr.split(DOT).map { DIGIT_REGEX.match?(_1) ? Integer(_1, 10) : _1.to_sym }
|
47
46
|
end
|
48
|
-
elsif
|
47
|
+
elsif none_key_paths_match?(key_paths, path)
|
49
48
|
path
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
53
52
|
# @api private
|
54
|
-
def
|
55
|
-
|
56
|
-
|
53
|
+
def none_key_paths_match?(key_paths, path)
|
54
|
+
!any_key_paths_match?(key_paths, path)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @api private
|
58
|
+
def any_key_paths_match?(key_paths, path)
|
59
|
+
find_path(key_paths, path, false) ||
|
60
|
+
find_path(key_paths, path + DOT, true) ||
|
61
|
+
find_path(key_paths, path + BRACKETS, true)
|
62
|
+
end
|
63
|
+
|
64
|
+
# @api private
|
65
|
+
def find_path(key_paths, path, prefix_match)
|
66
|
+
key = key_paths.bsearch { |key_path| key_path >= path }
|
67
|
+
prefix_match ? key&.start_with?(path) : key == path
|
57
68
|
end
|
58
69
|
|
59
70
|
# @api private
|
@@ -13,8 +13,7 @@ module Dry
|
|
13
13
|
|
14
14
|
append_macro(Macros::Value) do |macro|
|
15
15
|
if opts[:type_spec] && !filter_empty_string?
|
16
|
-
macro.call(predicates[0], :filled?, *predicates
|
17
|
-
&block)
|
16
|
+
macro.call(predicates[0], :filled?, *predicates.drop(1), **opts, &block)
|
18
17
|
elsif opts[:type_rule]
|
19
18
|
macro.call(:filled?).value(*predicates, **opts, &block)
|
20
19
|
else
|
@@ -11,7 +11,7 @@ module Dry
|
|
11
11
|
def call(*args, &block)
|
12
12
|
super(*args, &nil) unless args.empty?
|
13
13
|
|
14
|
-
if args.size.equal?(1) && (op = args.first).is_a?(Dry::Logic::Operations::Abstract)
|
14
|
+
if args.size.equal?(1) && (op = args.first).is_a?(::Dry::Logic::Operations::Abstract)
|
15
15
|
process_operation(op)
|
16
16
|
end
|
17
17
|
|
@@ -55,8 +55,8 @@ module Dry
|
|
55
55
|
|
56
56
|
# @api private
|
57
57
|
# rubocop: disable Metrics/AbcSize
|
58
|
-
def define(*args, &
|
59
|
-
definition = schema_dsl.new(path: schema_dsl.path, &
|
58
|
+
def define(*args, &)
|
59
|
+
definition = schema_dsl.new(path: schema_dsl.path, &)
|
60
60
|
schema = definition.call
|
61
61
|
type_schema =
|
62
62
|
if array_type?(parent_type)
|
@@ -12,11 +12,11 @@ module Dry
|
|
12
12
|
# rubocop:disable Metrics/AbcSize
|
13
13
|
# rubocop:disable Metrics/CyclomaticComplexity
|
14
14
|
# rubocop:disable Metrics/PerceivedComplexity
|
15
|
-
def call(*args, **opts, &
|
16
|
-
types, predicates = args.partition {
|
15
|
+
def call(*args, **opts, &)
|
16
|
+
types, predicates = args.partition { _1.is_a?(::Dry::Types::Type) }
|
17
17
|
|
18
|
-
constructor = types.select {
|
19
|
-
schema = predicates.detect {
|
18
|
+
constructor = types.select { _1.is_a?(::Dry::Types::Constructor) }.reduce(:>>)
|
19
|
+
schema = predicates.detect { _1.is_a?(Processor) }
|
20
20
|
|
21
21
|
schema_dsl.set_type(name, constructor) if constructor
|
22
22
|
|
@@ -41,20 +41,20 @@ module Dry
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
trace_opts = opts.
|
44
|
+
trace_opts = opts.except(:type_spec, :type_rule)
|
45
45
|
|
46
46
|
if (type_rule = opts[:type_rule])
|
47
47
|
trace.append(type_rule).evaluate(*predicates, **trace_opts)
|
48
|
-
trace.append(new(chain: false).instance_exec(&
|
48
|
+
trace.append(new(chain: false).instance_exec(&)) if block_given?
|
49
49
|
else
|
50
50
|
trace.evaluate(*predicates, **trace_opts)
|
51
51
|
|
52
|
-
if
|
53
|
-
hash(&
|
52
|
+
if block_given? && type_spec.equal?(:hash)
|
53
|
+
hash(&)
|
54
54
|
elsif type_spec.is_a?(::Dry::Types::Type) && hash_type?(type_spec)
|
55
55
|
hash(type_spec)
|
56
|
-
elsif
|
57
|
-
trace.append(new(chain: false).instance_exec(&
|
56
|
+
elsif block_given?
|
57
|
+
trace.append(new(chain: false).instance_exec(&))
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -112,9 +112,9 @@ module Dry
|
|
112
112
|
private
|
113
113
|
|
114
114
|
# @api private
|
115
|
-
def method_missing(meth,
|
115
|
+
def method_missing(meth, ...)
|
116
116
|
if meth.to_s.end_with?(QUESTION_MARK)
|
117
|
-
trace.__send__(meth,
|
117
|
+
trace.__send__(meth, ...)
|
118
118
|
else
|
119
119
|
super
|
120
120
|
end
|