dry-validation 1.0.0 → 1.1.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 +23 -1
- data/lib/dry/validation.rb +3 -0
- data/lib/dry/validation/constants.rb +6 -0
- data/lib/dry/validation/contract.rb +5 -3
- data/lib/dry/validation/evaluator.rb +16 -0
- data/lib/dry/validation/messages/resolver.rb +3 -0
- data/lib/dry/validation/result.rb +2 -2
- data/lib/dry/validation/rule.rb +25 -4
- data/lib/dry/validation/values.rb +31 -8
- data/lib/dry/validation/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3821e92d2dced61bb892e20a5e5d69b596128fcdbd05596e41fff8716767b08c
|
4
|
+
data.tar.gz: f797d5e46604e777966cb3d9a7a4032265227684164224a8ff109fc8ba51d1c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7504498b77c794b9fe37e0384fba50a8fb6c99e3fecd3423e66fe018006288b3ba1a5a7a2232fb53dede256ba0a13630313748a0214b4a0d9865fc22c0b9edae
|
7
|
+
data.tar.gz: 654233d365e7844985f465e16335a234a2d5c2c240b97a485d286a52e6229e3ee80d8719e76d3ec95fe393d75f480617452b7813cb36b4b033021f9b98958461
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
# v1.1.1 2019-06-24
|
2
|
+
|
3
|
+
### Fixed
|
4
|
+
|
5
|
+
* `Rule#each` works with array values from nested hashes (@mustardnoise)
|
6
|
+
|
7
|
+
[Compare v1.1.0...v1.1.1](https://github.com/dry-rb/dry-validation/compare/v1.1.0...v1.1.1)
|
8
|
+
|
9
|
+
# v1.1.0 2019-06-14
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
* `key?` method available within rules, that can be used to check if there's a value under the rule's default key (refs #540) (@solnic)
|
14
|
+
* `value` supports hash-based path specifications now (refs #547) (@solnic)
|
15
|
+
* `value` can read multiple values when the key points to them, ie in case of `rule(geo: [:lat, :lon])` it would return an array with `lat` and `lon` (@solnic)
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
|
19
|
+
* Passing multiple macro names to `validate` or `each` works correctly (fixed #538 #541) (@jandudulski)
|
20
|
+
|
21
|
+
[Compare v1.0.0...v1.1.0](https://github.com/dry-rb/dry-validation/compare/v1.0.0...v1.1.0)
|
22
|
+
|
1
23
|
# v1.0.0 2019-06-10
|
2
24
|
|
3
25
|
This release is a complete rewrite on top of `dry-schema` that uses contract classes to define schema and validation rules. It's **not backward-compatible**. This release addressed over 150 known issues, including bugs and missing features.
|
@@ -12,7 +34,7 @@ See [the list of all addressed issues](https://github.com/dry-rb/dry-validation/
|
|
12
34
|
- Support for macros that encapsulate common rule logic
|
13
35
|
- Built-in `:acceptance` macro
|
14
36
|
|
15
|
-
[Compare v0.13.3...v1.0.0](https://github.com/dry-rb/dry-validation/compare/
|
37
|
+
[Compare v0.13.3...v1.0.0](https://github.com/dry-rb/dry-validation/compare/v0.13.3...v1.0.0)
|
16
38
|
|
17
39
|
# v1.0.0 2019-06-10 (compared to 1.0.0.rc3)
|
18
40
|
|
data/lib/dry/validation.rb
CHANGED
@@ -41,9 +41,12 @@ module Dry
|
|
41
41
|
# @return [Contract]
|
42
42
|
#
|
43
43
|
# @api public
|
44
|
+
#
|
45
|
+
# rubocop:disable Naming/MethodName
|
44
46
|
def self.Contract(options = EMPTY_HASH, &block)
|
45
47
|
Contract.build(options, &block)
|
46
48
|
end
|
49
|
+
# rubocop:enable Naming/MethodName
|
47
50
|
|
48
51
|
# This is needed by Macros::Registrar
|
49
52
|
#
|
@@ -11,6 +11,12 @@ module Dry
|
|
11
11
|
# Root path is used for base errors in hash representation of error messages
|
12
12
|
ROOT_PATH = [nil].freeze
|
13
13
|
|
14
|
+
# Path to the default errors locale file
|
15
|
+
DEFAULT_ERRORS_NAMESPACE = 'dry_validation'
|
16
|
+
|
17
|
+
# Path to the default errors locale file
|
18
|
+
DEFAULT_ERRORS_PATH = Pathname(__FILE__).join('../../../../config/errors.yml').realpath.freeze
|
19
|
+
|
14
20
|
# Mapping for block kwarg options used by block_options
|
15
21
|
#
|
16
22
|
# @see Rule#block_options
|
@@ -54,8 +54,8 @@ module Dry
|
|
54
54
|
extend Dry::Initializer
|
55
55
|
extend ClassInterface
|
56
56
|
|
57
|
-
config.messages.top_namespace =
|
58
|
-
config.messages.load_paths <<
|
57
|
+
config.messages.top_namespace = DEFAULT_ERRORS_NAMESPACE
|
58
|
+
config.messages.load_paths << DEFAULT_ERRORS_PATH
|
59
59
|
|
60
60
|
# @!attribute [r] config
|
61
61
|
# @return [Config] Contract's configuration object
|
@@ -118,7 +118,9 @@ module Dry
|
|
118
118
|
# @api private
|
119
119
|
def error?(result, key)
|
120
120
|
path = Schema::Path[key]
|
121
|
-
|
121
|
+
|
122
|
+
result.error?(path) ||
|
123
|
+
path.map.with_index { |_k, i| result.error?(path.keys[0..i - 2]) }.any?
|
122
124
|
end
|
123
125
|
|
124
126
|
# Get a registered macro
|
@@ -147,6 +147,22 @@ module Dry
|
|
147
147
|
values[key_name]
|
148
148
|
end
|
149
149
|
|
150
|
+
# Return if the value under the default key is available
|
151
|
+
#
|
152
|
+
# This is useful when dealing with rules for optional keys
|
153
|
+
#
|
154
|
+
# @example
|
155
|
+
# rule(:age) do
|
156
|
+
# key.failure(:invalid) if key? && value < 18
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# @return [Boolean]
|
160
|
+
#
|
161
|
+
# @api public
|
162
|
+
def key?
|
163
|
+
values.key?(key_name)
|
164
|
+
end
|
165
|
+
|
150
166
|
# Check if there are any errors under the provided path
|
151
167
|
#
|
152
168
|
# @param [Symbol, String, Array] A Path-compatible spec
|
@@ -49,6 +49,8 @@ module Dry
|
|
49
49
|
# @return [String]
|
50
50
|
#
|
51
51
|
# @api public
|
52
|
+
#
|
53
|
+
# rubocop:disable Metrics/AbcSize
|
52
54
|
def message(rule, tokens: EMPTY_HASH, locale: nil, full: false, path:)
|
53
55
|
keys = path.to_a.compact
|
54
56
|
msg_opts = tokens.merge(path: keys, locale: locale || messages.default_locale)
|
@@ -70,6 +72,7 @@ module Dry
|
|
70
72
|
|
71
73
|
[full ? "#{messages.rule(keys.last, msg_opts)} #{text}" : text, meta]
|
72
74
|
end
|
75
|
+
# rubocop:enable Metrics/AbcSize
|
73
76
|
end
|
74
77
|
end
|
75
78
|
end
|
@@ -148,9 +148,9 @@ module Dry
|
|
148
148
|
# @api public
|
149
149
|
def inspect
|
150
150
|
if context.empty?
|
151
|
-
"#<#{self.class}#{to_h
|
151
|
+
"#<#{self.class}#{to_h} errors=#{errors.to_h}>"
|
152
152
|
else
|
153
|
-
"#<#{self.class}#{to_h
|
153
|
+
"#<#{self.class}#{to_h} errors=#{errors.to_h} context=#{context.each.to_h}>"
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
data/lib/dry/validation/rule.rb
CHANGED
@@ -54,7 +54,7 @@ module Dry
|
|
54
54
|
#
|
55
55
|
# @api public
|
56
56
|
def validate(*macros, &block)
|
57
|
-
@macros = macros
|
57
|
+
@macros = parse_macros(*macros)
|
58
58
|
@block = block if block
|
59
59
|
self
|
60
60
|
end
|
@@ -68,17 +68,22 @@ module Dry
|
|
68
68
|
# rule(:nums).each do
|
69
69
|
# key.failure("must be greater than 0") if value < 0
|
70
70
|
# end
|
71
|
+
# rule(:nums).each(min: 3)
|
72
|
+
# rule(address: :city) do
|
73
|
+
# key.failure("oops") if value != 'Munich'
|
74
|
+
# end
|
71
75
|
#
|
72
76
|
# @return [Rule]
|
73
77
|
#
|
74
78
|
# @api public
|
75
79
|
def each(*macros, &block)
|
76
|
-
root = keys
|
80
|
+
root = keys[0]
|
81
|
+
macros = parse_macros(*macros)
|
77
82
|
@keys = []
|
78
83
|
|
79
84
|
@block = proc do
|
80
|
-
values[root].each_with_index do |_, idx|
|
81
|
-
path = [*root, idx]
|
85
|
+
(values[root] || []).each_with_index do |_, idx|
|
86
|
+
path = [*Schema::Path[root].to_a, idx]
|
82
87
|
|
83
88
|
next if result.error?(path)
|
84
89
|
|
@@ -99,6 +104,22 @@ module Dry
|
|
99
104
|
def inspect
|
100
105
|
%(#<#{self.class} keys=#{keys.inspect}>)
|
101
106
|
end
|
107
|
+
|
108
|
+
# Parse function arguments into macros structure
|
109
|
+
#
|
110
|
+
# @return [Array]
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
def parse_macros(*args)
|
114
|
+
args.each_with_object([]) do |spec, macros|
|
115
|
+
case spec
|
116
|
+
when Hash
|
117
|
+
spec.each { |k, v| macros << [k, Array(v)] }
|
118
|
+
else
|
119
|
+
macros << Array(spec)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
102
123
|
end
|
103
124
|
end
|
104
125
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/equalizer'
|
4
|
+
require 'dry/schema/path'
|
4
5
|
require 'dry/validation/constants'
|
5
6
|
|
6
7
|
module Dry
|
@@ -40,17 +41,39 @@ module Dry
|
|
40
41
|
#
|
41
42
|
# @api public
|
42
43
|
def [](*args)
|
43
|
-
if args.size
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
return data.dig(*args) if args.size > 1
|
45
|
+
|
46
|
+
case (key = args[0])
|
47
|
+
when Symbol, String, Array, Hash
|
48
|
+
path = Schema::Path[key]
|
49
|
+
keys = path.to_a
|
50
|
+
|
51
|
+
return data.dig(*keys) unless keys.last.is_a?(Array)
|
52
|
+
|
53
|
+
last = keys.pop
|
54
|
+
vals = self.class.new(data.dig(*keys))
|
55
|
+
|
56
|
+
last.map { |name| vals[name] }
|
57
|
+
else
|
58
|
+
raise ArgumentError, '+key+ must be a valid path specification'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @api public
|
63
|
+
def key?(key, hash = data)
|
64
|
+
return hash.key?(key) if key.is_a?(Symbol)
|
65
|
+
|
66
|
+
Schema::Path[key].reduce(hash) do |a, e|
|
67
|
+
if e.is_a?(Array)
|
68
|
+
result = e.all? { |k| key?(k, a) }
|
69
|
+
return result
|
48
70
|
else
|
49
|
-
|
71
|
+
return false unless a.is_a?(Array) ? (e >= 0 && e < a.size) : a.key?(e)
|
50
72
|
end
|
51
|
-
|
52
|
-
data.dig(*args)
|
73
|
+
a[e]
|
53
74
|
end
|
75
|
+
|
76
|
+
true
|
54
77
|
end
|
55
78
|
|
56
79
|
# @api private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-validation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|