dry-validation 1.2.0 → 1.5.0
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 +277 -153
- data/LICENSE +1 -1
- data/README.md +7 -8
- data/dry-validation.gemspec +41 -0
- data/lib/dry-validation.rb +1 -1
- data/lib/dry/validation.rb +6 -8
- data/lib/dry/validation/config.rb +2 -2
- data/lib/dry/validation/constants.rb +5 -4
- data/lib/dry/validation/contract.rb +19 -13
- data/lib/dry/validation/contract/class_interface.rb +63 -50
- data/lib/dry/validation/evaluator.rb +24 -10
- data/lib/dry/validation/extensions/hints.rb +1 -1
- data/lib/dry/validation/extensions/monads.rb +1 -1
- data/lib/dry/validation/extensions/predicates_as_macros.rb +3 -3
- data/lib/dry/validation/failures.rb +15 -3
- data/lib/dry/validation/function.rb +2 -2
- data/lib/dry/validation/macro.rb +2 -2
- data/lib/dry/validation/macros.rb +2 -2
- data/lib/dry/validation/message.rb +4 -4
- data/lib/dry/validation/message_set.rb +5 -50
- data/lib/dry/validation/messages/resolver.rb +30 -3
- data/lib/dry/validation/result.rb +37 -5
- data/lib/dry/validation/rule.rb +17 -9
- data/lib/dry/validation/schema_ext.rb +6 -21
- data/lib/dry/validation/values.rb +7 -8
- data/lib/dry/validation/version.rb +1 -1
- metadata +27 -28
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
[gem]: https://rubygems.org/gems/dry-validation
|
|
2
|
-
[
|
|
3
|
-
[
|
|
2
|
+
[actions]: https://github.com/dry-rb/dry-validation/actions
|
|
3
|
+
[codacy]: https://www.codacy.com/gh/dry-rb/dry-validation
|
|
4
4
|
[chat]: https://dry-rb.zulipchat.com
|
|
5
5
|
[inchpages]: http://inch-ci.org/github/dry-rb/dry-validation
|
|
6
6
|
|
|
7
7
|
# dry-validation [][chat]
|
|
8
8
|
|
|
9
9
|
[][gem]
|
|
10
|
-
[][actions]
|
|
11
|
+
[][codacy]
|
|
12
|
+
[][codacy]
|
|
13
13
|
[][inchpages]
|
|
14
14
|
|
|
15
15
|
## Links
|
|
16
16
|
|
|
17
|
-
* [User documentation](
|
|
17
|
+
* [User documentation](http://dry-rb.org/gems/dry-validation)
|
|
18
18
|
* [API documentation](http://rubydoc.info/gems/dry-validation)
|
|
19
|
-
* [Guidelines for contributing](CONTRIBUTING.md)
|
|
20
19
|
|
|
21
20
|
## Supported Ruby versions
|
|
22
21
|
|
|
23
|
-
This library officially supports following Ruby versions:
|
|
22
|
+
This library officially supports the following Ruby versions:
|
|
24
23
|
|
|
25
24
|
* MRI >= `2.4`
|
|
26
25
|
* jruby >= `9.2`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# this file is managed by dry-rb/devtools project
|
|
3
|
+
|
|
4
|
+
lib = File.expand_path('lib', __dir__)
|
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
6
|
+
require 'dry/validation/version'
|
|
7
|
+
|
|
8
|
+
Gem::Specification.new do |spec|
|
|
9
|
+
spec.name = 'dry-validation'
|
|
10
|
+
spec.authors = ["Piotr Solnica"]
|
|
11
|
+
spec.email = ["piotr.solnica@gmail.com"]
|
|
12
|
+
spec.license = 'MIT'
|
|
13
|
+
spec.version = Dry::Validation::VERSION.dup
|
|
14
|
+
|
|
15
|
+
spec.summary = "Validation library"
|
|
16
|
+
spec.description = spec.summary
|
|
17
|
+
spec.homepage = 'https://dry-rb.org/gems/dry-validation'
|
|
18
|
+
spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-validation.gemspec", "lib/**/*", "config/*.yml"]
|
|
19
|
+
spec.bindir = 'bin'
|
|
20
|
+
spec.executables = []
|
|
21
|
+
spec.require_paths = ['lib']
|
|
22
|
+
|
|
23
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
24
|
+
spec.metadata['changelog_uri'] = 'https://github.com/dry-rb/dry-validation/blob/master/CHANGELOG.md'
|
|
25
|
+
spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-validation'
|
|
26
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-validation/issues'
|
|
27
|
+
|
|
28
|
+
spec.required_ruby_version = ">= 2.4.0"
|
|
29
|
+
|
|
30
|
+
# to update dependencies edit project.yml
|
|
31
|
+
spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
|
32
|
+
spec.add_runtime_dependency "dry-container", "~> 0.7", ">= 0.7.1"
|
|
33
|
+
spec.add_runtime_dependency "dry-core", "~> 0.4"
|
|
34
|
+
spec.add_runtime_dependency "dry-equalizer", "~> 0.2"
|
|
35
|
+
spec.add_runtime_dependency "dry-initializer", "~> 3.0"
|
|
36
|
+
spec.add_runtime_dependency "dry-schema", "~> 1.5"
|
|
37
|
+
|
|
38
|
+
spec.add_development_dependency "bundler"
|
|
39
|
+
spec.add_development_dependency "rake"
|
|
40
|
+
spec.add_development_dependency "rspec"
|
|
41
|
+
end
|
data/lib/dry-validation.rb
CHANGED
data/lib/dry/validation.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
3
|
+
require "dry/validation/constants"
|
|
4
|
+
require "dry/validation/contract"
|
|
5
|
+
require "dry/validation/macros"
|
|
6
6
|
|
|
7
7
|
# Main namespace
|
|
8
8
|
#
|
|
@@ -16,15 +16,15 @@ module Dry
|
|
|
16
16
|
extend Macros::Registrar
|
|
17
17
|
|
|
18
18
|
register_extension(:monads) do
|
|
19
|
-
require
|
|
19
|
+
require "dry/validation/extensions/monads"
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
register_extension(:hints) do
|
|
23
|
-
require
|
|
23
|
+
require "dry/validation/extensions/hints"
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
register_extension(:predicates_as_macros) do
|
|
27
|
-
require
|
|
27
|
+
require "dry/validation/extensions/predicates_as_macros"
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Define a contract and build its instance
|
|
@@ -46,11 +46,9 @@ module Dry
|
|
|
46
46
|
#
|
|
47
47
|
# @api public
|
|
48
48
|
#
|
|
49
|
-
# rubocop:disable Naming/MethodName
|
|
50
49
|
def self.Contract(options = EMPTY_HASH, &block)
|
|
51
50
|
Contract.build(options, &block)
|
|
52
51
|
end
|
|
53
|
-
# rubocop:enable Naming/MethodName
|
|
54
52
|
|
|
55
53
|
# This is needed by Macros::Registrar
|
|
56
54
|
#
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "pathname"
|
|
4
|
+
require "dry/core/constants"
|
|
4
5
|
|
|
5
6
|
module Dry
|
|
6
7
|
module Validation
|
|
7
8
|
include Dry::Core::Constants
|
|
8
9
|
|
|
9
|
-
DOT =
|
|
10
|
+
DOT = "."
|
|
10
11
|
|
|
11
12
|
# Root path is used for base errors in hash representation of error messages
|
|
12
13
|
ROOT_PATH = [nil].freeze
|
|
13
14
|
|
|
14
15
|
# Path to the default errors locale file
|
|
15
|
-
DEFAULT_ERRORS_NAMESPACE =
|
|
16
|
+
DEFAULT_ERRORS_NAMESPACE = "dry_validation"
|
|
16
17
|
|
|
17
18
|
# Path to the default errors locale file
|
|
18
|
-
DEFAULT_ERRORS_PATH = Pathname(__FILE__).join(
|
|
19
|
+
DEFAULT_ERRORS_PATH = Pathname(__FILE__).join("../../../../config/errors.yml").realpath.freeze
|
|
19
20
|
|
|
20
21
|
# Mapping for block kwarg options used by block_options
|
|
21
22
|
#
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "concurrent/map"
|
|
4
4
|
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
5
|
+
require "dry/equalizer"
|
|
6
|
+
require "dry/initializer"
|
|
7
|
+
require "dry/schema/path"
|
|
8
8
|
|
|
9
|
-
require
|
|
10
|
-
require
|
|
11
|
-
require
|
|
12
|
-
require
|
|
13
|
-
require
|
|
14
|
-
require
|
|
15
|
-
require
|
|
9
|
+
require "dry/validation/config"
|
|
10
|
+
require "dry/validation/constants"
|
|
11
|
+
require "dry/validation/rule"
|
|
12
|
+
require "dry/validation/evaluator"
|
|
13
|
+
require "dry/validation/messages/resolver"
|
|
14
|
+
require "dry/validation/result"
|
|
15
|
+
require "dry/validation/contract/class_interface"
|
|
16
16
|
|
|
17
17
|
module Dry
|
|
18
18
|
module Validation
|
|
@@ -98,7 +98,7 @@ module Dry
|
|
|
98
98
|
rule_result = rule.(self, result)
|
|
99
99
|
|
|
100
100
|
rule_result.failures.each do |failure|
|
|
101
|
-
result.add_error(message_resolver
|
|
101
|
+
result.add_error(message_resolver.(**failure))
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
104
|
end
|
|
@@ -119,6 +119,10 @@ module Dry
|
|
|
119
119
|
def error?(result, spec)
|
|
120
120
|
path = Schema::Path[spec]
|
|
121
121
|
|
|
122
|
+
if path.multi_value?
|
|
123
|
+
return path.expand.any? { |nested_path| error?(result, nested_path) }
|
|
124
|
+
end
|
|
125
|
+
|
|
122
126
|
return true if result.error?(path)
|
|
123
127
|
|
|
124
128
|
path
|
|
@@ -128,7 +132,9 @@ module Dry
|
|
|
128
132
|
|
|
129
133
|
return false unless result.error?(curr_path)
|
|
130
134
|
|
|
131
|
-
result.errors.any? { |err|
|
|
135
|
+
result.errors.any? { |err|
|
|
136
|
+
(other = Schema::Path[err.path]).same_root?(curr_path) && other == curr_path
|
|
137
|
+
}
|
|
132
138
|
}
|
|
133
139
|
end
|
|
134
140
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
3
|
+
require "dry/schema"
|
|
4
|
+
require "dry/schema/messages"
|
|
5
|
+
require "dry/schema/path"
|
|
6
|
+
require "dry/schema/key_map"
|
|
7
7
|
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
require
|
|
8
|
+
require "dry/validation/constants"
|
|
9
|
+
require "dry/validation/macros"
|
|
10
|
+
require "dry/validation/schema_ext"
|
|
11
11
|
|
|
12
12
|
module Dry
|
|
13
13
|
module Validation
|
|
@@ -23,7 +23,7 @@ module Dry
|
|
|
23
23
|
# @api private
|
|
24
24
|
def inherited(klass)
|
|
25
25
|
super
|
|
26
|
-
klass.instance_variable_set(
|
|
26
|
+
klass.instance_variable_set("@config", config.dup)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
# Configuration
|
|
@@ -53,36 +53,36 @@ module Dry
|
|
|
53
53
|
#
|
|
54
54
|
# This type of schema is suitable for HTTP parameters
|
|
55
55
|
#
|
|
56
|
-
# @return [Dry::Schema::Params]
|
|
56
|
+
# @return [Dry::Schema::Params,NilClass]
|
|
57
57
|
# @see https://dry-rb.org/gems/dry-schema/params/
|
|
58
58
|
#
|
|
59
59
|
# @api public
|
|
60
|
-
def params(&block)
|
|
61
|
-
define(:Params, &block)
|
|
60
|
+
def params(*external_schemas, &block)
|
|
61
|
+
define(:Params, external_schemas, &block)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
# Define a JSON schema for your contract
|
|
65
65
|
#
|
|
66
66
|
# This type of schema is suitable for JSON data
|
|
67
67
|
#
|
|
68
|
-
# @return [Dry::Schema::JSON]
|
|
68
|
+
# @return [Dry::Schema::JSON,NilClass]
|
|
69
69
|
# @see https://dry-rb.org/gems/dry-schema/json/
|
|
70
70
|
#
|
|
71
71
|
# @api public
|
|
72
|
-
def json(&block)
|
|
73
|
-
define(:JSON, &block)
|
|
72
|
+
def json(*external_schemas, &block)
|
|
73
|
+
define(:JSON, external_schemas, &block)
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
# Define a plain schema for your contract
|
|
77
77
|
#
|
|
78
78
|
# This type of schema does not offer coercion out of the box
|
|
79
79
|
#
|
|
80
|
-
# @return [Dry::Schema::Processor]
|
|
80
|
+
# @return [Dry::Schema::Processor,NilClass]
|
|
81
81
|
# @see https://dry-rb.org/gems/dry-schema/
|
|
82
82
|
#
|
|
83
83
|
# @api public
|
|
84
|
-
def schema(&block)
|
|
85
|
-
define(:schema, &block)
|
|
84
|
+
def schema(*external_schemas, &block)
|
|
85
|
+
define(:schema, external_schemas, &block)
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
# Define a rule for your contract
|
|
@@ -101,7 +101,7 @@ module Dry
|
|
|
101
101
|
#
|
|
102
102
|
# @api public
|
|
103
103
|
def rule(*keys, &block)
|
|
104
|
-
ensure_valid_keys(*keys)
|
|
104
|
+
ensure_valid_keys(*keys) if __schema__
|
|
105
105
|
|
|
106
106
|
Rule.new(keys: keys, block: block).tap do |rule|
|
|
107
107
|
rules << rule
|
|
@@ -123,7 +123,7 @@ module Dry
|
|
|
123
123
|
#
|
|
124
124
|
# @api public
|
|
125
125
|
def build(options = EMPTY_HASH, &block)
|
|
126
|
-
Class.new(self, &block).new(options)
|
|
126
|
+
Class.new(self, &block).new(**options)
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
# @api private
|
|
@@ -154,29 +154,15 @@ module Dry
|
|
|
154
154
|
private
|
|
155
155
|
|
|
156
156
|
# @api private
|
|
157
|
-
# rubocop:disable Metrics/AbcSize
|
|
158
157
|
def ensure_valid_keys(*keys)
|
|
159
|
-
valid_paths = key_map.to_dot_notation
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
last.map { |last_key|
|
|
168
|
-
path_key = [*path.to_a[0..-2], last_key]
|
|
169
|
-
[path_key, Schema::Path[path_key]]
|
|
170
|
-
}
|
|
171
|
-
else
|
|
172
|
-
[[key, path]]
|
|
173
|
-
end
|
|
174
|
-
}
|
|
175
|
-
.flatten(1)
|
|
176
|
-
.reject { |(_, path)|
|
|
177
|
-
valid_paths.any? { |valid_path| valid_path.include?(path) }
|
|
178
|
-
}
|
|
179
|
-
.map(&:first)
|
|
158
|
+
valid_paths = key_map.to_dot_notation
|
|
159
|
+
key_paths = key_paths(keys)
|
|
160
|
+
|
|
161
|
+
invalid_keys = key_paths.map { |(key, path)|
|
|
162
|
+
unless valid_paths.any? { |vp| vp.include?(path) || vp.include?("#{path}[]") }
|
|
163
|
+
key
|
|
164
|
+
end
|
|
165
|
+
}.compact.uniq
|
|
180
166
|
|
|
181
167
|
return if invalid_keys.empty?
|
|
182
168
|
|
|
@@ -184,7 +170,28 @@ module Dry
|
|
|
184
170
|
#{name}.rule specifies keys that are not defined by the schema: #{invalid_keys.inspect}
|
|
185
171
|
STR
|
|
186
172
|
end
|
|
187
|
-
|
|
173
|
+
|
|
174
|
+
# @api private
|
|
175
|
+
def key_paths(keys)
|
|
176
|
+
keys.map { |key|
|
|
177
|
+
case key
|
|
178
|
+
when Hash
|
|
179
|
+
path = Schema::Path[key]
|
|
180
|
+
if path.multi_value?
|
|
181
|
+
*head, tail = Array(path)
|
|
182
|
+
[key].product(
|
|
183
|
+
tail.map { |el| [*head, *el] }.map { |parts| parts.join(DOT) }
|
|
184
|
+
)
|
|
185
|
+
else
|
|
186
|
+
[[key, path.to_a.join(DOT)]]
|
|
187
|
+
end
|
|
188
|
+
when Array
|
|
189
|
+
[[key, Schema::Path[key].to_a.join(DOT)]]
|
|
190
|
+
else
|
|
191
|
+
[[key, key.to_s]]
|
|
192
|
+
end
|
|
193
|
+
}.flatten(1)
|
|
194
|
+
end
|
|
188
195
|
|
|
189
196
|
# @api private
|
|
190
197
|
def key_map
|
|
@@ -192,23 +199,29 @@ module Dry
|
|
|
192
199
|
end
|
|
193
200
|
|
|
194
201
|
# @api private
|
|
195
|
-
def
|
|
196
|
-
{
|
|
202
|
+
def core_schema_opts
|
|
203
|
+
{parent: superclass&.__schema__, config: config}
|
|
197
204
|
end
|
|
198
205
|
|
|
199
206
|
# @api private
|
|
200
|
-
def define(method_name, &block)
|
|
201
|
-
if
|
|
202
|
-
|
|
207
|
+
def define(method_name, external_schemas, &block)
|
|
208
|
+
return __schema__ if external_schemas.empty? && block.nil?
|
|
209
|
+
|
|
210
|
+
unless __schema__.nil?
|
|
211
|
+
raise ::Dry::Validation::DuplicateSchemaError, "Schema has already been defined"
|
|
203
212
|
end
|
|
204
213
|
|
|
214
|
+
schema_opts = core_schema_opts
|
|
215
|
+
|
|
216
|
+
schema_opts.update(parent: external_schemas) if external_schemas.any?
|
|
217
|
+
|
|
205
218
|
case method_name
|
|
206
219
|
when :schema
|
|
207
|
-
@__schema__ = Schema.define(schema_opts, &block)
|
|
220
|
+
@__schema__ = Schema.define(**schema_opts, &block)
|
|
208
221
|
when :Params
|
|
209
|
-
@__schema__ = Schema.Params(schema_opts, &block)
|
|
222
|
+
@__schema__ = Schema.Params(**schema_opts, &block)
|
|
210
223
|
when :JSON
|
|
211
|
-
@__schema__ = Schema.JSON(schema_opts, &block)
|
|
224
|
+
@__schema__ = Schema.JSON(**schema_opts, &block)
|
|
212
225
|
end
|
|
213
226
|
end
|
|
214
227
|
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "dry/initializer"
|
|
4
|
+
require "dry/core/deprecations"
|
|
4
5
|
|
|
5
|
-
require
|
|
6
|
-
require
|
|
6
|
+
require "dry/validation/constants"
|
|
7
|
+
require "dry/validation/failures"
|
|
7
8
|
|
|
8
9
|
module Dry
|
|
9
10
|
module Validation
|
|
@@ -16,6 +17,9 @@ module Dry
|
|
|
16
17
|
# @api public
|
|
17
18
|
class Evaluator
|
|
18
19
|
extend Dry::Initializer
|
|
20
|
+
extend Dry::Core::Deprecations[:'dry-validation']
|
|
21
|
+
|
|
22
|
+
deprecate :error?, :schema_error?
|
|
19
23
|
|
|
20
24
|
# @!attribute [r] _contract
|
|
21
25
|
# @return [Contract]
|
|
@@ -63,19 +67,19 @@ module Dry
|
|
|
63
67
|
# Initialize a new evaluator
|
|
64
68
|
#
|
|
65
69
|
# @api private
|
|
66
|
-
def initialize(contract, options, &block)
|
|
67
|
-
super(contract, options)
|
|
70
|
+
def initialize(contract, **options, &block)
|
|
71
|
+
super(contract, **options)
|
|
68
72
|
|
|
69
73
|
@_options = options
|
|
70
74
|
|
|
71
75
|
if block
|
|
72
76
|
exec_opts = block_options.map { |key, value| [key, _options[value]] }.to_h
|
|
73
|
-
instance_exec(exec_opts, &block)
|
|
77
|
+
instance_exec(**exec_opts, &block)
|
|
74
78
|
end
|
|
75
79
|
|
|
76
80
|
macros.each do |args|
|
|
77
81
|
macro = macro(*args.flatten(1))
|
|
78
|
-
instance_exec(macro.extract_block_options(_options.merge(macro: macro)), ¯o.block)
|
|
82
|
+
instance_exec(**macro.extract_block_options(_options.merge(macro: macro)), ¯o.block)
|
|
79
83
|
end
|
|
80
84
|
end
|
|
81
85
|
|
|
@@ -117,7 +121,7 @@ module Dry
|
|
|
117
121
|
|
|
118
122
|
# @api private
|
|
119
123
|
def with(new_opts, &block)
|
|
120
|
-
self.class.new(_contract, _options
|
|
124
|
+
self.class.new(_contract, **_options, **new_opts, &block)
|
|
121
125
|
end
|
|
122
126
|
|
|
123
127
|
# Return default (first) key name
|
|
@@ -163,17 +167,26 @@ module Dry
|
|
|
163
167
|
values.key?(key_name)
|
|
164
168
|
end
|
|
165
169
|
|
|
166
|
-
# Check if there are any errors under the provided path
|
|
170
|
+
# Check if there are any errors on the schema under the provided path
|
|
167
171
|
#
|
|
168
172
|
# @param [Symbol, String, Array] A Path-compatible spec
|
|
169
173
|
#
|
|
170
174
|
# @return [Boolean]
|
|
171
175
|
#
|
|
172
176
|
# @api public
|
|
173
|
-
def
|
|
177
|
+
def schema_error?(path)
|
|
174
178
|
result.error?(path)
|
|
175
179
|
end
|
|
176
180
|
|
|
181
|
+
# Check if there are any errors on the current rule
|
|
182
|
+
#
|
|
183
|
+
# @return [Boolean]
|
|
184
|
+
#
|
|
185
|
+
# @api public
|
|
186
|
+
def rule_error?
|
|
187
|
+
!key(path).empty?
|
|
188
|
+
end
|
|
189
|
+
|
|
177
190
|
# @api private
|
|
178
191
|
def respond_to_missing?(meth, include_private = false)
|
|
179
192
|
super || _contract.respond_to?(meth, true)
|
|
@@ -192,6 +205,7 @@ module Dry
|
|
|
192
205
|
super
|
|
193
206
|
end
|
|
194
207
|
end
|
|
208
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
|
195
209
|
end
|
|
196
210
|
end
|
|
197
211
|
end
|