dry-validation 0.13.2 → 0.13.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/lib/dry/validation/message.rb +1 -1
- data/lib/dry/validation/message_compiler.rb +1 -5
- data/lib/dry/validation/messages/abstract.rb +8 -13
- data/lib/dry/validation/messages/i18n.rb +8 -1
- data/lib/dry/validation/messages/namespaced.rb +7 -0
- data/lib/dry/validation/messages/yaml.rb +7 -0
- data/lib/dry/validation/template.rb +66 -0
- data/lib/dry/validation/version.rb +1 -1
- data/spec/fixtures/locales/en.yml +2 -0
- data/spec/integration/custom_error_messages_spec.rb +10 -4
- data/spec/integration/messages/i18n_spec.rb +15 -15
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d569600e476b1c0830184bea7e9393f333693e11c1a9d8b074e2b2329deeba7a
|
4
|
+
data.tar.gz: 4811db9bc4e1cc3f398df8717333683355779116a72314532b10bc2d49a87333
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c497db70c2bf78e3355c685176361b06357ee9d9f17a2c867127d4d575865f0e6cb1f5bafae4b595e1db3af8748fc6122e6522177a152e17e8e6119006591b3c
|
7
|
+
data.tar.gz: 2b93c44b453e47f6a68ec05bedaec9d2f48d001a6dc9d0f62f2f2d7b70de5f8c1a7130bfc33c558fff1129fceb69d37f33f341d38c96549570a684d7279d24b0
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
# v0.13.3 2019-05-21
|
2
|
+
|
3
|
+
### Fixed
|
4
|
+
|
5
|
+
* Fixed regression with caching templates that rely on predicate arguments (solnic)
|
6
|
+
* Removed ugly workaround for template evaluation with extra tokens (solnic)
|
7
|
+
|
8
|
+
### Changed
|
9
|
+
|
10
|
+
* [internal] `Messages::Abstract#call` returns a `Template` object now, this was backported from dry-schema (solnic)
|
11
|
+
|
12
|
+
[Compare v0.13.2...v0.13.3](https://github.com/dry-rb/dry-validation/compare/v0.13.2...v0.13.3)
|
13
|
+
|
1
14
|
# v0.13.2 2019-05-12
|
2
15
|
|
3
16
|
### Fixed
|
@@ -160,9 +160,7 @@ module Dry
|
|
160
160
|
end
|
161
161
|
|
162
162
|
def message_text(rule, template, tokens, opts)
|
163
|
-
|
164
|
-
$VERBOSE = nil
|
165
|
-
text = template % tokens
|
163
|
+
text = template[template.data(tokens)]
|
166
164
|
|
167
165
|
if full?
|
168
166
|
rule_name = messages.rule(rule, opts) || rule
|
@@ -170,8 +168,6 @@ module Dry
|
|
170
168
|
else
|
171
169
|
text
|
172
170
|
end
|
173
|
-
ensure
|
174
|
-
$VERBOSE = original_verbosity
|
175
171
|
end
|
176
172
|
|
177
173
|
def message_tokens(args)
|
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'concurrent/map'
|
3
|
+
|
3
4
|
require 'dry/equalizer'
|
4
5
|
require 'dry/configurable'
|
5
6
|
|
7
|
+
require 'dry/validation/template'
|
8
|
+
|
6
9
|
module Dry
|
7
10
|
module Validation
|
8
11
|
module Messages
|
@@ -62,23 +65,15 @@ module Dry
|
|
62
65
|
end
|
63
66
|
|
64
67
|
def call(predicate, options = EMPTY_HASH)
|
65
|
-
cache.fetch_or_store(
|
68
|
+
cache.fetch_or_store([predicate, options.reject { |k,| k.equal?(:input) }]) do
|
66
69
|
path, opts = lookup(predicate, options)
|
67
|
-
|
70
|
+
return unless path
|
71
|
+
text = yield(path, opts)
|
72
|
+
Template[text]
|
68
73
|
end
|
69
74
|
end
|
70
75
|
alias_method :[], :call
|
71
76
|
|
72
|
-
if ::Hash.instance_methods.include?(:slice)
|
73
|
-
def cache_key(predicate, options)
|
74
|
-
[predicate, options.slice(*CACHE_KEYS)]
|
75
|
-
end
|
76
|
-
else
|
77
|
-
def cache_key(predicate, options)
|
78
|
-
[predicate, options.select { |key,| CACHE_KEYS.include?(key) }]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
77
|
def lookup(predicate, options = {})
|
83
78
|
tokens = options.merge(
|
84
79
|
root: root,
|
@@ -112,7 +107,7 @@ module Dry
|
|
112
107
|
end
|
113
108
|
|
114
109
|
def cache
|
115
|
-
@cache ||= self.class.cache[
|
110
|
+
@cache ||= self.class.cache[self]
|
116
111
|
end
|
117
112
|
|
118
113
|
def default_locale
|
@@ -13,8 +13,15 @@ module Dry
|
|
13
13
|
@t = I18n.method(:t)
|
14
14
|
end
|
15
15
|
|
16
|
+
def call(predicate, options = EMPTY_HASH)
|
17
|
+
super do |path, opts|
|
18
|
+
get(path, opts)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
alias_method :[], :call
|
22
|
+
|
16
23
|
def get(key, options = {})
|
17
|
-
t.(key, options) if key
|
24
|
+
t.(key, locale: options.fetch(:locale, default_locale)) if key
|
18
25
|
end
|
19
26
|
|
20
27
|
def rule(name, options = {})
|
@@ -34,6 +34,13 @@ module Dry
|
|
34
34
|
@data = data
|
35
35
|
end
|
36
36
|
|
37
|
+
def call(predicate, options = EMPTY_HASH)
|
38
|
+
super do |path, opts|
|
39
|
+
get(path, opts)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias_method :[], :call
|
43
|
+
|
37
44
|
def get(key, options = {})
|
38
45
|
data[key % { locale: options.fetch(:locale, default_locale) }]
|
39
46
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/equalizer'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Validation
|
7
|
+
module Messages
|
8
|
+
# Template wraps a string with interpolation tokens and defines evaluator function
|
9
|
+
# dynamically
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
class Template
|
13
|
+
include Dry::Equalizer(:text)
|
14
|
+
|
15
|
+
TOKEN_REGEXP = /%{(\w*)}/
|
16
|
+
|
17
|
+
# !@attribute [r] text
|
18
|
+
# @return [String]
|
19
|
+
attr_reader :text
|
20
|
+
|
21
|
+
# !@attribute [r] tokens
|
22
|
+
# @return [Hash]
|
23
|
+
attr_reader :tokens
|
24
|
+
|
25
|
+
# !@attribute [r] evaluator
|
26
|
+
# @return [Proc]
|
27
|
+
attr_reader :evaluator
|
28
|
+
|
29
|
+
# @api private
|
30
|
+
def self.[](input)
|
31
|
+
new(*parse(input))
|
32
|
+
end
|
33
|
+
|
34
|
+
# @api private
|
35
|
+
def self.parse(input)
|
36
|
+
tokens = input.scan(TOKEN_REGEXP).flatten(1).map(&:to_sym)
|
37
|
+
text = input.gsub('%', '#')
|
38
|
+
|
39
|
+
evaluator = <<-RUBY.strip
|
40
|
+
-> (#{tokens.map { |token| "#{token}:" }.join(", ")}) { "#{text}" }
|
41
|
+
RUBY
|
42
|
+
|
43
|
+
[text, tokens, eval(evaluator, binding, __FILE__, __LINE__ - 3)]
|
44
|
+
end
|
45
|
+
|
46
|
+
# @api private
|
47
|
+
def initialize(text, tokens, evaluator)
|
48
|
+
@text = text
|
49
|
+
@tokens = tokens
|
50
|
+
@evaluator = evaluator
|
51
|
+
end
|
52
|
+
|
53
|
+
# @api private
|
54
|
+
def data(input)
|
55
|
+
tokens.each_with_object({}) { |k, h| h[k] = input[k] }
|
56
|
+
end
|
57
|
+
|
58
|
+
# @api private
|
59
|
+
def call(data = EMPTY_HASH)
|
60
|
+
data.empty? ? evaluator.() : evaluator.(data)
|
61
|
+
end
|
62
|
+
alias_method :[], :call
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -4,8 +4,12 @@ RSpec.describe Dry::Validation do
|
|
4
4
|
shared_context 'schema with customized messages' do
|
5
5
|
describe '#messages' do
|
6
6
|
it 'returns compiled error messages' do
|
7
|
-
expect(schema.(email: '').messages).to eql(
|
8
|
-
email: ['Please provide your email']
|
7
|
+
expect(schema.(email: '', age: 12).messages).to eql(
|
8
|
+
email: ['Please provide your email'], age: ['12 must be greater than 18']
|
9
|
+
)
|
10
|
+
|
11
|
+
expect(schema.(email: '', age: 14).messages).to eql(
|
12
|
+
email: ['Please provide your email'], age: ['14 must be greater than 18']
|
9
13
|
)
|
10
14
|
end
|
11
15
|
end
|
@@ -18,7 +22,8 @@ RSpec.describe Dry::Validation do
|
|
18
22
|
config.messages_file = SPEC_ROOT.join('fixtures/locales/en.yml')
|
19
23
|
end
|
20
24
|
|
21
|
-
required(:email
|
25
|
+
required(:email).filled
|
26
|
+
required(:age).value(gt?: 18)
|
22
27
|
end
|
23
28
|
end
|
24
29
|
|
@@ -38,7 +43,8 @@ RSpec.describe Dry::Validation do
|
|
38
43
|
config.messages = :i18n
|
39
44
|
end
|
40
45
|
|
41
|
-
required(:email
|
46
|
+
required(:email).filled
|
47
|
+
required(:age).value(gt?: 18)
|
42
48
|
end
|
43
49
|
end
|
44
50
|
|
@@ -17,33 +17,33 @@ RSpec.describe Messages::I18n do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'returns a message for a predicate' do
|
20
|
-
message = messages[:filled?, rule: :name]
|
20
|
+
message = messages[:filled?, rule: :name].text
|
21
21
|
|
22
22
|
expect(message).to eql("nie może być pusty")
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'returns a message for a specific rule' do
|
26
|
-
message = messages[:filled?, rule: :email]
|
26
|
+
message = messages[:filled?, rule: :email].text
|
27
27
|
|
28
28
|
expect(message).to eql("Proszę podać adres email")
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'returns a message for a specific val type' do
|
32
|
-
message = messages[:size?, rule: :pages, val_type: String]
|
32
|
+
message = messages[:size?, rule: :pages, val_type: String].text
|
33
33
|
|
34
|
-
expect(message).to eql("wielkość musi być równa
|
34
|
+
expect(message).to eql("wielkość musi być równa \#{size}")
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'returns a message for a specific rule and its default arg type' do
|
38
|
-
message = messages[:size?, rule: :pages]
|
38
|
+
message = messages[:size?, rule: :pages].text
|
39
39
|
|
40
|
-
expect(message).to eql("wielkość musi być równa
|
40
|
+
expect(message).to eql("wielkość musi być równa \#{size}")
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'returns a message for a specific rule and its arg type' do
|
44
|
-
message = messages[:size?, rule: :pages, arg_type: Range]
|
44
|
+
message = messages[:size?, rule: :pages, arg_type: Range].text
|
45
45
|
|
46
|
-
expect(message).to eql("wielkość musi być między
|
46
|
+
expect(message).to eql("wielkość musi być między \#{size_left} a \#{size_right}")
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -57,27 +57,27 @@ RSpec.describe Messages::I18n do
|
|
57
57
|
|
58
58
|
context 'with a different locale' do
|
59
59
|
it 'returns a message for a predicate' do
|
60
|
-
message = messages[:filled?, rule: :name, locale: :en]
|
60
|
+
message = messages[:filled?, rule: :name, locale: :en].text
|
61
61
|
|
62
62
|
expect(message).to eql("must be filled")
|
63
63
|
end
|
64
64
|
|
65
65
|
it 'returns a message for a specific rule' do
|
66
|
-
message = messages[:filled?, rule: :email, locale: :en]
|
66
|
+
message = messages[:filled?, rule: :email, locale: :en].text
|
67
67
|
|
68
68
|
expect(message).to eql("Please provide your email")
|
69
69
|
end
|
70
70
|
|
71
71
|
it 'returns a message for a specific rule and its default arg type' do
|
72
|
-
message = messages[:size?, rule: :pages, locale: :en]
|
72
|
+
message = messages[:size?, rule: :pages, locale: :en].text
|
73
73
|
|
74
|
-
expect(message).to eql("size must be
|
74
|
+
expect(message).to eql("size must be \#{size}")
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'returns a message for a specific rule and its arg type' do
|
78
|
-
message = messages[:size?, rule: :pages, arg_type: Range, locale: :en]
|
78
|
+
message = messages[:size?, rule: :pages, arg_type: Range, locale: :en].text
|
79
79
|
|
80
|
-
expect(message).to eql("size must be within
|
80
|
+
expect(message).to eql("size must be within \#{size_left} - \#{size_right}")
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -90,7 +90,7 @@ RSpec.describe Messages::I18n do
|
|
90
90
|
it 'returns a message for a predicate in the default_locale' do
|
91
91
|
pending 'FIXME: this got broken for some reason, probably an I18n issue'
|
92
92
|
|
93
|
-
message = messages[:even?, rule: :some_number]
|
93
|
+
message = messages[:even?, rule: :some_number].text
|
94
94
|
|
95
95
|
expect(I18n.locale).to eql(:pl)
|
96
96
|
expect(message).to eql("must be even")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-validation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.13.
|
4
|
+
version: 0.13.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Holland
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-05-
|
12
|
+
date: 2019-05-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: concurrent-ruby
|
@@ -226,6 +226,7 @@ files:
|
|
226
226
|
- lib/dry/validation/schema/rule.rb
|
227
227
|
- lib/dry/validation/schema/value.rb
|
228
228
|
- lib/dry/validation/schema_compiler.rb
|
229
|
+
- lib/dry/validation/template.rb
|
229
230
|
- lib/dry/validation/type_specs.rb
|
230
231
|
- lib/dry/validation/version.rb
|
231
232
|
- log/.gitkeep
|