dry-validation 0.2.0 → 0.3.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -2
  3. data/Gemfile +4 -0
  4. data/README.md +131 -42
  5. data/config/errors.yml +36 -27
  6. data/examples/basic.rb +2 -4
  7. data/examples/each.rb +2 -2
  8. data/examples/form.rb +1 -2
  9. data/examples/nested.rb +2 -4
  10. data/examples/rule_ast.rb +0 -8
  11. data/lib/dry/validation.rb +0 -5
  12. data/lib/dry/validation/error.rb +2 -6
  13. data/lib/dry/validation/error_compiler.rb +19 -5
  14. data/lib/dry/validation/input_type_compiler.rb +2 -1
  15. data/lib/dry/validation/messages.rb +7 -58
  16. data/lib/dry/validation/messages/abstract.rb +75 -0
  17. data/lib/dry/validation/messages/i18n.rb +24 -0
  18. data/lib/dry/validation/messages/namespaced.rb +27 -0
  19. data/lib/dry/validation/messages/yaml.rb +50 -0
  20. data/lib/dry/validation/result.rb +19 -49
  21. data/lib/dry/validation/rule.rb +2 -2
  22. data/lib/dry/validation/rule/group.rb +21 -0
  23. data/lib/dry/validation/rule/result.rb +73 -0
  24. data/lib/dry/validation/rule_compiler.rb +5 -0
  25. data/lib/dry/validation/schema.rb +33 -14
  26. data/lib/dry/validation/schema/definition.rb +16 -0
  27. data/lib/dry/validation/schema/result.rb +21 -3
  28. data/lib/dry/validation/schema/rule.rb +1 -1
  29. data/lib/dry/validation/schema/value.rb +2 -1
  30. data/lib/dry/validation/version.rb +1 -1
  31. data/spec/fixtures/locales/en.yml +5 -0
  32. data/spec/fixtures/locales/pl.yml +14 -0
  33. data/spec/integration/custom_error_messages_spec.rb +4 -16
  34. data/spec/{unit → integration}/error_compiler_spec.rb +81 -39
  35. data/spec/integration/localized_error_messages_spec.rb +52 -0
  36. data/spec/integration/messages/i18n_spec.rb +71 -0
  37. data/spec/integration/rule_groups_spec.rb +35 -0
  38. data/spec/integration/schema_form_spec.rb +9 -9
  39. data/spec/integration/schema_spec.rb +2 -2
  40. data/spec/shared/predicates.rb +2 -0
  41. data/spec/spec_helper.rb +1 -0
  42. data/spec/unit/rule/group_spec.rb +12 -0
  43. data/spec/unit/schema_spec.rb +35 -0
  44. metadata +24 -6
  45. data/spec/fixtures/errors.yml +0 -4
@@ -0,0 +1,52 @@
1
+ RSpec.describe Dry::Validation, 'with localized messages' do
2
+ subject(:validation) { schema.new }
3
+
4
+ before do
5
+ I18n.config.available_locales_set << :pl
6
+ I18n.load_path = %w(en pl).map { |l| SPEC_ROOT.join("fixtures/locales/#{l}.yml") }
7
+ I18n.backend.load_translations
8
+ end
9
+
10
+ describe 'defining schema' do
11
+ context 'without a namespace' do
12
+ let(:schema) do
13
+ Class.new(Dry::Validation::Schema) do
14
+ configure do |config|
15
+ config.messages = :i18n
16
+ end
17
+
18
+ key(:email) { |email| email.filled? }
19
+ end
20
+ end
21
+
22
+ describe '#messages' do
23
+ it 'returns localized error messages' do
24
+ expect(validation.(email: '').messages(locale: :pl)).to match_array([
25
+ [:email, [['Proszę podać adres email', '']]]
26
+ ])
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'with a namespace' do
32
+ let(:schema) do
33
+ Class.new(Dry::Validation::Schema) do
34
+ configure do |config|
35
+ config.messages = :i18n
36
+ config.namespace = :user
37
+ end
38
+
39
+ key(:email) { |email| email.filled? }
40
+ end
41
+ end
42
+
43
+ describe '#messages' do
44
+ it 'returns localized error messages' do
45
+ expect(validation.(email: '').messages(locale: :pl)).to match_array([
46
+ [:email, [['Hej user! Dawaj ten email no!', '']]]
47
+ ])
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,71 @@
1
+ require 'dry/validation/messages/i18n'
2
+
3
+ RSpec.describe Messages::I18n do
4
+ subject(:messages) { Messages::I18n.new }
5
+
6
+ before do
7
+ I18n.config.available_locales_set << :pl
8
+ I18n.load_path << %w(en pl).map { |l| SPEC_ROOT.join("fixtures/locales/#{l}.yml") }
9
+ I18n.backend.load_translations
10
+ end
11
+
12
+ describe '#[]' do
13
+ context 'with the default locale' do
14
+ it 'returns a message for a predicate' do
15
+ message = messages[:filled?, rule: :name]
16
+
17
+ expect(message).to eql("%{name} must be filled")
18
+ end
19
+
20
+ it 'returns a message for a specific rule' do
21
+ message = messages[:filled?, rule: :email]
22
+
23
+ expect(message).to eql("Please provide your email")
24
+ end
25
+
26
+ it 'returns a message for a specific val type' do
27
+ message = messages[:size?, rule: :pages, val_type: String]
28
+
29
+ expect(message).to eql("%{name} length must be %{num}")
30
+ end
31
+
32
+ it 'returns a message for a specific rule and its default arg type' do
33
+ message = messages[:size?, rule: :pages]
34
+
35
+ expect(message).to eql("%{name} size must be %{num}")
36
+ end
37
+
38
+ it 'returns a message for a specific rule and its arg type' do
39
+ message = messages[:size?, rule: :pages, arg_type: Range]
40
+
41
+ expect(message).to eql("%{name} size must be within %{left} - %{right}")
42
+ end
43
+ end
44
+
45
+ context 'with a different locale' do
46
+ it 'returns a message for a predicate' do
47
+ message = messages[:filled?, rule: :name, locale: :pl]
48
+
49
+ expect(message).to eql("%{name} nie może być pusty")
50
+ end
51
+
52
+ it 'returns a message for a specific rule' do
53
+ message = messages[:filled?, rule: :email, locale: :pl]
54
+
55
+ expect(message).to eql("Proszę podać adres email")
56
+ end
57
+
58
+ it 'returns a message for a specific rule and its default arg type' do
59
+ message = messages[:size?, rule: :pages, locale: :pl]
60
+
61
+ expect(message).to eql("wielkość musi być równa %{num}")
62
+ end
63
+
64
+ it 'returns a message for a specific rule and its arg type' do
65
+ message = messages[:size?, rule: :pages, arg_type: Range, locale: :pl]
66
+
67
+ expect(message).to eql("wielkość musi być między %{left} a %{right}")
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,35 @@
1
+ RSpec.describe Dry::Validation::Schema do
2
+ subject(:validation) { schema.new }
3
+
4
+ describe 'defining schema with rule groups' do
5
+ let(:schema) do
6
+ Class.new(Dry::Validation::Schema) do
7
+ confirmation(:password)
8
+ end
9
+ end
10
+
11
+ describe '#call' do
12
+ it 'returns empty errors when password matches confirmation' do
13
+ expect(validation.(password: 'foo', password_confirmation: 'foo')).to be_empty
14
+ end
15
+
16
+ it 'returns error for a failed group rule' do
17
+ expect(validation.(password: 'foo', password_confirmation: 'bar')).to match_array([
18
+ [:error, [
19
+ :input, [
20
+ :password_confirmation,
21
+ ["foo", "bar"],
22
+ [[:group, [:password_confirmation, [:predicate, [:eql?, []]]]]]]]
23
+ ]
24
+ ])
25
+ end
26
+
27
+ it 'returns errors for the dependent predicates, not the group rule, when any of the dependent predicates fail' do
28
+ expect(validation.(password: '', password_confirmation: '')).to match_array([
29
+ [:error, [:input, [:password, "", [[:val, [:password, [:predicate, [:filled?, []]]]]]]]],
30
+ [:error, [:input, [:password_confirmation, "", [[:val, [:password_confirmation, [:predicate, [:filled?, []]]]]]]]]
31
+ ])
32
+ end
33
+ end
34
+ end
35
+ end
@@ -22,17 +22,19 @@ RSpec.describe Dry::Validation::Schema::Form do
22
22
  end
23
23
  end
24
24
 
25
- optional(:phone_number) { |phone_number| phone_number.none? | phone_number.str? }
25
+ optional(:phone_number) do |phone_number|
26
+ phone_number.none? | (phone_number.int? & phone_number.gt?(0))
27
+ end
26
28
  end
27
29
  end
28
30
 
29
31
  describe '#messages' do
30
32
  it 'returns compiled error messages' do
31
- result = validation.messages('email' => '', 'age' => '19')
33
+ result = validation.('email' => '', 'age' => '19')
32
34
 
33
- expect(result).to match_array([
34
- [:email, ["email must be filled"]],
35
- [:address, ["address is missing"]]
35
+ expect(result.messages).to match_array([
36
+ [:email, [['email must be filled', '']]],
37
+ [:address, [['address is missing', nil]]]
36
38
  ])
37
39
 
38
40
  expect(result.params).to eql(email: '', age: 19)
@@ -74,7 +76,7 @@ RSpec.describe Dry::Validation::Schema::Form do
74
76
  result = validation.(
75
77
  'email' => 'jane@doe.org',
76
78
  'age' => '19',
77
- 'phone_number' => 12,
79
+ 'phone_number' => '12',
78
80
  'address' => {
79
81
  'city' => 'NYC',
80
82
  'street' => 'Street 1/2',
@@ -82,9 +84,7 @@ RSpec.describe Dry::Validation::Schema::Form do
82
84
  }
83
85
  )
84
86
 
85
- expect(result).to match_array([
86
- [:error, [:input, [:phone_number, 12, [[:val, [:phone_number, [:predicate, [:str?, []]]]]]]]],
87
- ])
87
+ expect(result).to be_empty
88
88
 
89
89
  expect(result.params).to eql(
90
90
  email: 'jane@doe.org', age: 19, phone_number: 12,
@@ -46,8 +46,8 @@ RSpec.describe Dry::Validation::Schema do
46
46
 
47
47
  describe '#messages' do
48
48
  it 'returns compiled error messages' do
49
- expect(validation.messages(attrs.merge(email: ''))).to match_array([
50
- [:email, ["email must be filled"]]
49
+ expect(validation.(attrs.merge(email: '')).messages).to match_array([
50
+ [:email, [['email must be filled', '']]]
51
51
  ])
52
52
  end
53
53
  end
@@ -8,6 +8,8 @@ RSpec.shared_examples 'predicates' do
8
8
  let(:min_size?) { Dry::Validation::Predicates[:min_size?] }
9
9
 
10
10
  let(:key?) { Dry::Validation::Predicates[:key?] }
11
+
12
+ let(:eql?) { Dry::Validation::Predicates[:eql?] }
11
13
  end
12
14
 
13
15
  RSpec.shared_examples 'a passing predicate' do
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'i18n'
3
4
  require 'dry-validation'
4
5
 
5
6
  begin
@@ -0,0 +1,12 @@
1
+ RSpec.describe Rule::Group do
2
+ include_context 'predicates'
3
+
4
+ subject(:rule) { Rule::Group.new([:pass, :pass_confirm], eql?) }
5
+
6
+ describe '#call' do
7
+ it 'calls predicate with result values' do
8
+ expect(rule.('foo', 'foo')).to be_success
9
+ expect(rule.('foo', 'bar')).to be_failure
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ require 'dry/validation/messages/i18n'
2
+
3
+ RSpec.describe Schema do
4
+ describe '.messages' do
5
+ context 'with default setting' do
6
+ let(:schema) do
7
+ Class.new(Schema)
8
+ end
9
+
10
+ it 'returns default yaml messages' do
11
+ expect(schema.messages).to be_instance_of(Messages::YAML)
12
+ end
13
+ end
14
+
15
+ context 'with i18n setting' do
16
+ let(:schema) do
17
+ Class.new(Schema) { configure { config.messages = :i18n } }
18
+ end
19
+
20
+ it 'returns default i18n messages' do
21
+ expect(schema.messages).to be_instance_of(Messages::I18n)
22
+ end
23
+ end
24
+
25
+ context 'with an invalid setting' do
26
+ let(:schema) do
27
+ Class.new(Schema) { configure { config.messages = :oops } }
28
+ end
29
+
30
+ it 'returns default i18n messages' do
31
+ expect { schema.messages }.to raise_error(RuntimeError, /oops/)
32
+ end
33
+ end
34
+ end
35
+ end
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.2.0
4
+ version: 0.3.0
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: 2015-11-30 00:00:00.000000000 Z
12
+ date: 2015-12-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dry-configurable
@@ -152,6 +152,10 @@ files:
152
152
  - lib/dry/validation/error_compiler.rb
153
153
  - lib/dry/validation/input_type_compiler.rb
154
154
  - lib/dry/validation/messages.rb
155
+ - lib/dry/validation/messages/abstract.rb
156
+ - lib/dry/validation/messages/i18n.rb
157
+ - lib/dry/validation/messages/namespaced.rb
158
+ - lib/dry/validation/messages/yaml.rb
155
159
  - lib/dry/validation/predicate.rb
156
160
  - lib/dry/validation/predicate_set.rb
157
161
  - lib/dry/validation/predicates.rb
@@ -159,7 +163,9 @@ files:
159
163
  - lib/dry/validation/rule.rb
160
164
  - lib/dry/validation/rule/composite.rb
161
165
  - lib/dry/validation/rule/each.rb
166
+ - lib/dry/validation/rule/group.rb
162
167
  - lib/dry/validation/rule/key.rb
168
+ - lib/dry/validation/rule/result.rb
163
169
  - lib/dry/validation/rule/set.rb
164
170
  - lib/dry/validation/rule/value.rb
165
171
  - lib/dry/validation/rule_compiler.rb
@@ -172,15 +178,19 @@ files:
172
178
  - lib/dry/validation/schema/value.rb
173
179
  - lib/dry/validation/version.rb
174
180
  - rakelib/rubocop.rake
175
- - spec/fixtures/errors.yml
181
+ - spec/fixtures/locales/en.yml
182
+ - spec/fixtures/locales/pl.yml
176
183
  - spec/integration/custom_error_messages_spec.rb
177
184
  - spec/integration/custom_predicates_spec.rb
185
+ - spec/integration/error_compiler_spec.rb
186
+ - spec/integration/localized_error_messages_spec.rb
187
+ - spec/integration/messages/i18n_spec.rb
178
188
  - spec/integration/optional_keys_spec.rb
189
+ - spec/integration/rule_groups_spec.rb
179
190
  - spec/integration/schema_form_spec.rb
180
191
  - spec/integration/schema_spec.rb
181
192
  - spec/shared/predicates.rb
182
193
  - spec/spec_helper.rb
183
- - spec/unit/error_compiler_spec.rb
184
194
  - spec/unit/input_type_compiler_spec.rb
185
195
  - spec/unit/predicate_spec.rb
186
196
  - spec/unit/predicates/bool_spec.rb
@@ -209,11 +219,13 @@ files:
209
219
  - spec/unit/rule/conjunction_spec.rb
210
220
  - spec/unit/rule/disjunction_spec.rb
211
221
  - spec/unit/rule/each_spec.rb
222
+ - spec/unit/rule/group_spec.rb
212
223
  - spec/unit/rule/implication_spec.rb
213
224
  - spec/unit/rule/key_spec.rb
214
225
  - spec/unit/rule/set_spec.rb
215
226
  - spec/unit/rule/value_spec.rb
216
227
  - spec/unit/rule_compiler_spec.rb
228
+ - spec/unit/schema_spec.rb
217
229
  homepage: https://github.com/dryrb/dry-validation
218
230
  licenses:
219
231
  - MIT
@@ -239,15 +251,19 @@ signing_key:
239
251
  specification_version: 4
240
252
  summary: A simple validation library
241
253
  test_files:
242
- - spec/fixtures/errors.yml
254
+ - spec/fixtures/locales/en.yml
255
+ - spec/fixtures/locales/pl.yml
243
256
  - spec/integration/custom_error_messages_spec.rb
244
257
  - spec/integration/custom_predicates_spec.rb
258
+ - spec/integration/error_compiler_spec.rb
259
+ - spec/integration/localized_error_messages_spec.rb
260
+ - spec/integration/messages/i18n_spec.rb
245
261
  - spec/integration/optional_keys_spec.rb
262
+ - spec/integration/rule_groups_spec.rb
246
263
  - spec/integration/schema_form_spec.rb
247
264
  - spec/integration/schema_spec.rb
248
265
  - spec/shared/predicates.rb
249
266
  - spec/spec_helper.rb
250
- - spec/unit/error_compiler_spec.rb
251
267
  - spec/unit/input_type_compiler_spec.rb
252
268
  - spec/unit/predicate_spec.rb
253
269
  - spec/unit/predicates/bool_spec.rb
@@ -276,9 +292,11 @@ test_files:
276
292
  - spec/unit/rule/conjunction_spec.rb
277
293
  - spec/unit/rule/disjunction_spec.rb
278
294
  - spec/unit/rule/each_spec.rb
295
+ - spec/unit/rule/group_spec.rb
279
296
  - spec/unit/rule/implication_spec.rb
280
297
  - spec/unit/rule/key_spec.rb
281
298
  - spec/unit/rule/set_spec.rb
282
299
  - spec/unit/rule/value_spec.rb
283
300
  - spec/unit/rule_compiler_spec.rb
301
+ - spec/unit/schema_spec.rb
284
302
  has_rdoc:
@@ -1,4 +0,0 @@
1
- user:
2
- attributes:
3
- email:
4
- filled?: "%{name} can't be blank"