dry-validation 1.0.0.beta1 → 1.0.0.beta2
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 +28 -0
- data/README.md +2 -2
- data/lib/dry/validation/contract.rb +0 -1
- data/lib/dry/validation/extensions/monads.rb +1 -1
- data/lib/dry/validation/{error.rb → message.rb} +18 -9
- data/lib/dry/validation/{error_set.rb → message_set.rb} +22 -22
- data/lib/dry/validation/messages/resolver.rb +15 -9
- data/lib/dry/validation/result.rb +3 -3
- data/lib/dry/validation/version.rb +1 -1
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 705706b2bc77cae54a87647ce3d85d685aa2fe619e40950533e1d96a513d1ca0
|
4
|
+
data.tar.gz: a0ad40a08b44475bafa4510707870603517145602e5567bb10cd39f98a1895af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f2a5347e9b057d76cf9d99c0c313c7437133c1884e750a6c54d095e00f66eb600d7d79a033c2ba561a32c92b783c3153cbd8d88e62c715cd75e9d238f2a034a
|
7
|
+
data.tar.gz: 0a6312efffe80b0156da48da466a9c4384e0b636ef34a93587097592e72a9a2d72f9503e8aa6e556399fc8ad9a18399cc1e5fea2ddb9e66b6268509fcb796d4a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
# v1.0.0.beta2 2019-04-04
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
* Support for arbitrary meta-data in failures, ie:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
class NewUserContract < Dry::Validation::Contract
|
9
|
+
params do
|
10
|
+
required(:login).filled(:string)
|
11
|
+
end
|
12
|
+
|
13
|
+
rule(:login) do
|
14
|
+
key.failure(text: 'is taken', code: 123) unless db.unique?(values[:login])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
Now your error hash will include `{ login: [{ text: 'is taken', code: 123 }] }` (solnic + flash-gordon)
|
20
|
+
|
21
|
+
### Changed
|
22
|
+
|
23
|
+
* [BREAKING] `Error` was renamed to `Message` as it is a more generic concept (solnic)
|
24
|
+
* [BREAKING] `ErrorSet` was renamed to `MessageSet` for consistency (solnic)
|
25
|
+
* [BREAKING] `:monads` extension wraps entire result objects in `Success` or `Failure` (flash-gordon)
|
26
|
+
|
27
|
+
[Compare v1.0.0.beta1...v1.0.0.beta2](https://github.com/dry-rb/dry-validation/compare/v1.0.0.beta1...v1.0.0.beta2)
|
28
|
+
|
1
29
|
# v1.0.0.beta1 2019-03-26
|
2
30
|
|
3
31
|
### Added
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
[gem]: https://rubygems.org/gems/dry-validation
|
2
2
|
[travis]: https://travis-ci.org/dry-rb/dry-validation
|
3
3
|
[codeclimate]: https://codeclimate.com/github/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
|
-
# dry-validation [][chat]
|
8
8
|
|
9
9
|
[][gem]
|
10
10
|
[][travis]
|
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry/equalizer'
|
4
|
+
|
5
|
+
require 'dry/schema/constants'
|
4
6
|
require 'dry/schema/message'
|
5
7
|
|
6
8
|
module Dry
|
7
9
|
module Validation
|
8
|
-
#
|
10
|
+
# Message message
|
9
11
|
#
|
10
12
|
# @api public
|
11
|
-
class
|
12
|
-
include Dry::Equalizer(:text, :path)
|
13
|
+
class Message < Schema::Message
|
14
|
+
include Dry::Equalizer(:text, :path, :meta)
|
13
15
|
|
14
16
|
# @!attribute [r] text
|
15
17
|
# @return [String] text The error message text
|
@@ -19,29 +21,36 @@ module Dry
|
|
19
21
|
# @return [Array<Symbol, Integer>] path The path to the value with the error
|
20
22
|
attr_reader :path
|
21
23
|
|
24
|
+
# @!attribute [r] meta
|
25
|
+
# @return [Hash] meta Optional hash with meta-data
|
26
|
+
attr_reader :meta
|
27
|
+
|
22
28
|
# @api public
|
23
|
-
class Localized <
|
29
|
+
class Localized < Message
|
24
30
|
# @api public
|
25
31
|
def evaluate(**opts)
|
26
|
-
|
32
|
+
evaluated_text, rest = text.(opts)
|
33
|
+
Message.new(evaluated_text, path: path, meta: rest.merge(meta))
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
30
37
|
# Build an error
|
31
38
|
#
|
32
|
-
# @return [
|
39
|
+
# @return [Message, Message::Localized]
|
33
40
|
#
|
34
41
|
# @api public
|
35
|
-
def self.[](text, path)
|
36
|
-
text.respond_to?(:call) ? Localized
|
42
|
+
def self.[](text, path, meta)
|
43
|
+
klass = text.respond_to?(:call) ? Localized : Message
|
44
|
+
klass.new(text, path: path, meta: meta)
|
37
45
|
end
|
38
46
|
|
39
47
|
# Initialize a new error object
|
40
48
|
#
|
41
49
|
# @api private
|
42
|
-
def initialize(text, path:)
|
50
|
+
def initialize(text, path:, meta: EMPTY_HASH)
|
43
51
|
@text = text
|
44
52
|
@path = Array(path)
|
53
|
+
@meta = meta
|
45
54
|
end
|
46
55
|
|
47
56
|
# Check if this is a base error not associated with any key
|
@@ -3,17 +3,17 @@
|
|
3
3
|
require 'dry/schema/message_set'
|
4
4
|
|
5
5
|
require 'dry/validation/constants'
|
6
|
-
require 'dry/validation/
|
6
|
+
require 'dry/validation/message'
|
7
7
|
|
8
8
|
module Dry
|
9
9
|
module Validation
|
10
|
-
#
|
10
|
+
# MessageSet is a specialized message set for handling validation messages
|
11
11
|
#
|
12
12
|
# @api public
|
13
|
-
class
|
13
|
+
class MessageSet < Schema::MessageSet
|
14
14
|
# @!attribute [r] source
|
15
15
|
# Return the source set of messages used to produce final evaluated messages
|
16
|
-
# @return [Array<
|
16
|
+
# @return [Array<Message, Message::Localized, Schema::Message>]
|
17
17
|
# @api private
|
18
18
|
attr_reader :source_messages
|
19
19
|
|
@@ -29,54 +29,54 @@ module Dry
|
|
29
29
|
super
|
30
30
|
end
|
31
31
|
|
32
|
-
# Return a new
|
32
|
+
# Return a new message set using updated options
|
33
33
|
#
|
34
|
-
# @return [
|
34
|
+
# @return [MessageSet]
|
35
35
|
#
|
36
36
|
# @api private
|
37
37
|
def with(other, new_options = EMPTY_HASH)
|
38
38
|
return self if new_options.empty?
|
39
39
|
|
40
40
|
self.class.new(
|
41
|
-
other + select { |err| err.is_a?(
|
41
|
+
other + select { |err| err.is_a?(Message) },
|
42
42
|
options.merge(source: source_messages, **new_options)
|
43
43
|
).freeze
|
44
44
|
end
|
45
45
|
|
46
|
-
# Add a new
|
46
|
+
# Add a new message
|
47
47
|
#
|
48
48
|
# This is used when result is being prepared
|
49
49
|
#
|
50
|
-
# @return [
|
50
|
+
# @return [MessageSet]
|
51
51
|
#
|
52
52
|
# @api private
|
53
|
-
def add(
|
54
|
-
source_messages <<
|
55
|
-
messages <<
|
53
|
+
def add(message)
|
54
|
+
source_messages << message
|
55
|
+
messages << message
|
56
56
|
initialize_placeholders!
|
57
57
|
self
|
58
58
|
end
|
59
59
|
|
60
|
-
# Filter
|
60
|
+
# Filter message set using provided predicates
|
61
61
|
#
|
62
|
-
# This method is open to any predicate because
|
62
|
+
# This method is open to any predicate because messages can be anything that
|
63
63
|
# implements Message API, thus they can implement whatever predicates you
|
64
64
|
# may need.
|
65
65
|
#
|
66
|
-
# @example get a list of base
|
67
|
-
#
|
68
|
-
#
|
66
|
+
# @example get a list of base messages
|
67
|
+
# message_set = contract.(input).message_set
|
68
|
+
# message_set.filter(:base?)
|
69
69
|
#
|
70
70
|
# @param [Array<Symbol>] *predicates
|
71
71
|
#
|
72
|
-
# @return [
|
72
|
+
# @return [MessageSet]
|
73
73
|
#
|
74
74
|
# @api public
|
75
75
|
def filter(*predicates)
|
76
|
-
|
77
|
-
predicates.all? { |predicate|
|
76
|
+
messages = select { |msg|
|
77
|
+
predicates.all? { |predicate| msg.respond_to?(predicate) && msg.public_send(predicate) }
|
78
78
|
}
|
79
|
-
self.class.new(
|
79
|
+
self.class.new(messages)
|
80
80
|
end
|
81
81
|
|
82
82
|
# @api private
|
@@ -101,7 +101,7 @@ module Dry
|
|
101
101
|
def messages_map
|
102
102
|
@messages_map ||= reduce(placeholders) { |hash, msg|
|
103
103
|
node = msg.path.reduce(hash) { |a, e| a.is_a?(Hash) ? a[e] : a.last[e] }
|
104
|
-
(node.size > 1 ? node[0] : node) << msg.
|
104
|
+
(node.size > 1 ? node[0] : node) << msg.dump
|
105
105
|
hash
|
106
106
|
}
|
107
107
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'dry/validation/message'
|
4
|
+
|
3
5
|
module Dry
|
4
6
|
module Validation
|
5
7
|
module Messages
|
@@ -23,19 +25,23 @@ module Dry
|
|
23
25
|
@locale = locale
|
24
26
|
end
|
25
27
|
|
26
|
-
# Resolve
|
28
|
+
# Resolve Message object from provided args and path
|
27
29
|
#
|
28
30
|
# This is used internally by contracts when rules are applied
|
29
31
|
#
|
30
|
-
# @return [
|
32
|
+
# @return [Message, Message::Localized]
|
31
33
|
#
|
32
34
|
# @api public
|
33
|
-
def call(message:, tokens:, path:)
|
35
|
+
def call(message:, tokens:, path:, meta: EMPTY_HASH)
|
34
36
|
case message
|
35
37
|
when Symbol
|
36
|
-
|
38
|
+
Message[->(**opts) { message(message, path: path, tokens: tokens, **opts) }, path, meta]
|
37
39
|
when String
|
38
|
-
|
40
|
+
Message[message, path, meta]
|
41
|
+
when Hash
|
42
|
+
meta = message.dup
|
43
|
+
text = meta.delete(:text)
|
44
|
+
call(message: text, tokens: tokens, path: path, meta: meta)
|
39
45
|
end
|
40
46
|
end
|
41
47
|
alias_method :[], :call
|
@@ -50,10 +56,10 @@ module Dry
|
|
50
56
|
msg_opts = tokens.merge(path: keys, locale: locale)
|
51
57
|
|
52
58
|
if keys.empty?
|
53
|
-
template = messages["rules.#{rule}", msg_opts]
|
59
|
+
template, meta = messages["rules.#{rule}", msg_opts]
|
54
60
|
else
|
55
|
-
template = messages[rule, msg_opts.merge(path: keys.join(DOT))]
|
56
|
-
template
|
61
|
+
template, meta = messages[rule, msg_opts.merge(path: keys.join(DOT))]
|
62
|
+
template, meta = messages[rule, msg_opts.merge(path: keys.last)] unless template
|
57
63
|
end
|
58
64
|
|
59
65
|
unless template
|
@@ -64,7 +70,7 @@ module Dry
|
|
64
70
|
|
65
71
|
text = template.(template.data(tokens))
|
66
72
|
|
67
|
-
full ? "#{messages.rule(keys.last, msg_opts)} #{text}" : text
|
73
|
+
[full ? "#{messages.rule(keys.last, msg_opts)} #{text}" : text, meta]
|
68
74
|
end
|
69
75
|
end
|
70
76
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'dry/equalizer'
|
4
4
|
|
5
5
|
require 'dry/validation/constants'
|
6
|
-
require 'dry/validation/
|
6
|
+
require 'dry/validation/message_set'
|
7
7
|
|
8
8
|
module Dry
|
9
9
|
module Validation
|
@@ -45,7 +45,7 @@ module Dry
|
|
45
45
|
|
46
46
|
# Get error set
|
47
47
|
#
|
48
|
-
# @return [
|
48
|
+
# @return [MessageSet]
|
49
49
|
#
|
50
50
|
# @api public
|
51
51
|
def errors(new_options = EMPTY_HASH)
|
@@ -134,7 +134,7 @@ module Dry
|
|
134
134
|
|
135
135
|
# @api private
|
136
136
|
def initialize_errors(options = self.options)
|
137
|
-
|
137
|
+
MessageSet.new(schema_errors(options), options)
|
138
138
|
end
|
139
139
|
|
140
140
|
# @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.0.0.
|
4
|
+
version: 1.0.0.beta2
|
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-
|
11
|
+
date: 2019-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -76,22 +76,22 @@ dependencies:
|
|
76
76
|
name: dry-schema
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
|
-
- - "~>"
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
version: '0.3'
|
82
79
|
- - ">="
|
83
80
|
- !ruby/object:Gem::Version
|
84
|
-
version: '0.
|
81
|
+
version: '0.5'
|
82
|
+
- - "~>"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0.5'
|
85
85
|
type: :runtime
|
86
86
|
prerelease: false
|
87
87
|
version_requirements: !ruby/object:Gem::Requirement
|
88
88
|
requirements:
|
89
|
-
- - "~>"
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
version: '0.3'
|
92
89
|
- - ">="
|
93
90
|
- !ruby/object:Gem::Version
|
94
|
-
version: '0.
|
91
|
+
version: '0.5'
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0.5'
|
95
95
|
- !ruby/object:Gem::Dependency
|
96
96
|
name: bundler
|
97
97
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,10 +150,10 @@ files:
|
|
150
150
|
- lib/dry/validation/constants.rb
|
151
151
|
- lib/dry/validation/contract.rb
|
152
152
|
- lib/dry/validation/contract/class_interface.rb
|
153
|
-
- lib/dry/validation/error.rb
|
154
|
-
- lib/dry/validation/error_set.rb
|
155
153
|
- lib/dry/validation/evaluator.rb
|
156
154
|
- lib/dry/validation/extensions/monads.rb
|
155
|
+
- lib/dry/validation/message.rb
|
156
|
+
- lib/dry/validation/message_set.rb
|
157
157
|
- lib/dry/validation/messages/resolver.rb
|
158
158
|
- lib/dry/validation/result.rb
|
159
159
|
- lib/dry/validation/rule.rb
|