dry-validation 0.13.3 → 1.7.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 (207) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +506 -95
  3. data/LICENSE +1 -1
  4. data/README.md +16 -12
  5. data/config/errors.yml +3 -88
  6. data/dry-validation.gemspec +37 -24
  7. data/lib/dry/validation/config.rb +24 -0
  8. data/lib/dry/validation/constants.rb +43 -0
  9. data/lib/dry/validation/contract/class_interface.rb +230 -0
  10. data/lib/dry/validation/contract.rb +171 -0
  11. data/lib/dry/validation/evaluator.rb +224 -0
  12. data/lib/dry/validation/extensions/hints.rb +67 -0
  13. data/lib/dry/validation/extensions/monads.rb +24 -8
  14. data/lib/dry/validation/extensions/predicates_as_macros.rb +75 -0
  15. data/lib/dry/validation/failures.rb +70 -0
  16. data/lib/dry/validation/function.rb +44 -0
  17. data/lib/dry/validation/macro.rb +38 -0
  18. data/lib/dry/validation/macros.rb +104 -0
  19. data/lib/dry/validation/message.rb +80 -80
  20. data/lib/dry/validation/message_set.rb +80 -105
  21. data/lib/dry/validation/messages/resolver.rb +131 -0
  22. data/lib/dry/validation/result.rb +183 -41
  23. data/lib/dry/validation/rule.rb +135 -0
  24. data/lib/dry/validation/schema_ext.rb +19 -0
  25. data/lib/dry/validation/values.rb +104 -0
  26. data/lib/dry/validation/version.rb +3 -1
  27. data/lib/dry/validation.rb +45 -28
  28. data/lib/dry-validation.rb +3 -1
  29. metadata +46 -344
  30. data/.codeclimate.yml +0 -17
  31. data/.gitignore +0 -9
  32. data/.rspec +0 -3
  33. data/.travis.yml +0 -29
  34. data/CONTRIBUTING.md +0 -31
  35. data/Gemfile +0 -25
  36. data/Rakefile +0 -22
  37. data/benchmarks/benchmark_form_invalid.rb +0 -64
  38. data/benchmarks/benchmark_form_valid.rb +0 -64
  39. data/benchmarks/benchmark_schema_invalid_huge.rb +0 -52
  40. data/benchmarks/profile_schema_call_invalid.rb +0 -20
  41. data/benchmarks/profile_schema_call_valid.rb +0 -20
  42. data/benchmarks/profile_schema_definition.rb +0 -14
  43. data/benchmarks/profile_schema_huge_invalid.rb +0 -30
  44. data/benchmarks/profile_schema_messages_invalid.rb +0 -20
  45. data/benchmarks/suite.rb +0 -5
  46. data/examples/basic.rb +0 -15
  47. data/examples/each.rb +0 -14
  48. data/examples/json.rb +0 -12
  49. data/examples/multiple.rb +0 -27
  50. data/examples/nested.rb +0 -22
  51. data/examples/params.rb +0 -11
  52. data/lib/dry/validation/compat/form.rb +0 -67
  53. data/lib/dry/validation/deprecations.rb +0 -24
  54. data/lib/dry/validation/executor.rb +0 -91
  55. data/lib/dry/validation/extensions/struct.rb +0 -32
  56. data/lib/dry/validation/extensions.rb +0 -7
  57. data/lib/dry/validation/input_processor_compiler/json.rb +0 -45
  58. data/lib/dry/validation/input_processor_compiler/params.rb +0 -49
  59. data/lib/dry/validation/input_processor_compiler/sanitizer.rb +0 -47
  60. data/lib/dry/validation/input_processor_compiler.rb +0 -137
  61. data/lib/dry/validation/message_compiler/visitor_opts.rb +0 -37
  62. data/lib/dry/validation/message_compiler.rb +0 -188
  63. data/lib/dry/validation/messages/abstract.rb +0 -119
  64. data/lib/dry/validation/messages/i18n.rb +0 -47
  65. data/lib/dry/validation/messages/namespaced.rb +0 -39
  66. data/lib/dry/validation/messages/yaml.rb +0 -61
  67. data/lib/dry/validation/messages.rb +0 -14
  68. data/lib/dry/validation/predicate_registry.rb +0 -115
  69. data/lib/dry/validation/predicates.rb +0 -19
  70. data/lib/dry/validation/schema/check.rb +0 -37
  71. data/lib/dry/validation/schema/class_interface.rb +0 -190
  72. data/lib/dry/validation/schema/deprecated.rb +0 -30
  73. data/lib/dry/validation/schema/dsl.rb +0 -118
  74. data/lib/dry/validation/schema/form.rb +0 -9
  75. data/lib/dry/validation/schema/json.rb +0 -21
  76. data/lib/dry/validation/schema/key.rb +0 -71
  77. data/lib/dry/validation/schema/params.rb +0 -22
  78. data/lib/dry/validation/schema/rule.rb +0 -202
  79. data/lib/dry/validation/schema/value.rb +0 -211
  80. data/lib/dry/validation/schema.rb +0 -126
  81. data/lib/dry/validation/schema_compiler.rb +0 -81
  82. data/lib/dry/validation/template.rb +0 -66
  83. data/lib/dry/validation/type_specs.rb +0 -70
  84. data/log/.gitkeep +0 -0
  85. data/spec/extensions/monads/result_spec.rb +0 -40
  86. data/spec/extensions/struct/schema_spec.rb +0 -32
  87. data/spec/fixtures/locales/en.yml +0 -8
  88. data/spec/fixtures/locales/pl.yml +0 -22
  89. data/spec/integration/custom_error_messages_spec.rb +0 -54
  90. data/spec/integration/custom_predicates_spec.rb +0 -228
  91. data/spec/integration/hints_spec.rb +0 -170
  92. data/spec/integration/injecting_rules_spec.rb +0 -30
  93. data/spec/integration/json/defining_base_schema_spec.rb +0 -41
  94. data/spec/integration/localized_error_messages_spec.rb +0 -72
  95. data/spec/integration/message_compiler_spec.rb +0 -405
  96. data/spec/integration/messages/i18n_spec.rb +0 -104
  97. data/spec/integration/optional_keys_spec.rb +0 -28
  98. data/spec/integration/params/predicates/array_spec.rb +0 -287
  99. data/spec/integration/params/predicates/empty_spec.rb +0 -263
  100. data/spec/integration/params/predicates/eql_spec.rb +0 -327
  101. data/spec/integration/params/predicates/even_spec.rb +0 -455
  102. data/spec/integration/params/predicates/excluded_from_spec.rb +0 -455
  103. data/spec/integration/params/predicates/excludes_spec.rb +0 -391
  104. data/spec/integration/params/predicates/false_spec.rb +0 -455
  105. data/spec/integration/params/predicates/filled_spec.rb +0 -467
  106. data/spec/integration/params/predicates/format_spec.rb +0 -454
  107. data/spec/integration/params/predicates/gt_spec.rb +0 -519
  108. data/spec/integration/params/predicates/gteq_spec.rb +0 -519
  109. data/spec/integration/params/predicates/included_in_spec.rb +0 -455
  110. data/spec/integration/params/predicates/includes_spec.rb +0 -391
  111. data/spec/integration/params/predicates/key_spec.rb +0 -67
  112. data/spec/integration/params/predicates/lt_spec.rb +0 -519
  113. data/spec/integration/params/predicates/lteq_spec.rb +0 -519
  114. data/spec/integration/params/predicates/max_size_spec.rb +0 -391
  115. data/spec/integration/params/predicates/min_size_spec.rb +0 -391
  116. data/spec/integration/params/predicates/none_spec.rb +0 -265
  117. data/spec/integration/params/predicates/not_eql_spec.rb +0 -327
  118. data/spec/integration/params/predicates/odd_spec.rb +0 -455
  119. data/spec/integration/params/predicates/size/fixed_spec.rb +0 -393
  120. data/spec/integration/params/predicates/size/range_spec.rb +0 -396
  121. data/spec/integration/params/predicates/true_spec.rb +0 -455
  122. data/spec/integration/params/predicates/type_spec.rb +0 -391
  123. data/spec/integration/result_spec.rb +0 -81
  124. data/spec/integration/schema/array_schema_spec.rb +0 -59
  125. data/spec/integration/schema/check_rules_spec.rb +0 -119
  126. data/spec/integration/schema/check_with_nested_el_spec.rb +0 -37
  127. data/spec/integration/schema/check_with_nth_el_spec.rb +0 -25
  128. data/spec/integration/schema/default_settings_spec.rb +0 -11
  129. data/spec/integration/schema/defining_base_schema_spec.rb +0 -41
  130. data/spec/integration/schema/dynamic_predicate_args_spec.rb +0 -43
  131. data/spec/integration/schema/each_with_set_spec.rb +0 -70
  132. data/spec/integration/schema/extending_dsl_spec.rb +0 -27
  133. data/spec/integration/schema/form_spec.rb +0 -236
  134. data/spec/integration/schema/hash_schema_spec.rb +0 -47
  135. data/spec/integration/schema/inheriting_schema_spec.rb +0 -31
  136. data/spec/integration/schema/input_processor_spec.rb +0 -46
  137. data/spec/integration/schema/json/explicit_types_spec.rb +0 -157
  138. data/spec/integration/schema/json_spec.rb +0 -163
  139. data/spec/integration/schema/macros/confirmation_spec.rb +0 -35
  140. data/spec/integration/schema/macros/each_spec.rb +0 -268
  141. data/spec/integration/schema/macros/filled_spec.rb +0 -87
  142. data/spec/integration/schema/macros/input_spec.rb +0 -139
  143. data/spec/integration/schema/macros/maybe_spec.rb +0 -99
  144. data/spec/integration/schema/macros/rule_spec.rb +0 -75
  145. data/spec/integration/schema/macros/value_spec.rb +0 -119
  146. data/spec/integration/schema/macros/when_spec.rb +0 -62
  147. data/spec/integration/schema/nested_schemas_spec.rb +0 -236
  148. data/spec/integration/schema/nested_values_spec.rb +0 -46
  149. data/spec/integration/schema/not_spec.rb +0 -34
  150. data/spec/integration/schema/numbers_spec.rb +0 -19
  151. data/spec/integration/schema/option_with_default_spec.rb +0 -64
  152. data/spec/integration/schema/or_spec.rb +0 -87
  153. data/spec/integration/schema/params/defining_base_schema_spec.rb +0 -41
  154. data/spec/integration/schema/params/explicit_types_spec.rb +0 -195
  155. data/spec/integration/schema/params_spec.rb +0 -234
  156. data/spec/integration/schema/predicate_verification_spec.rb +0 -9
  157. data/spec/integration/schema/predicates/array_spec.rb +0 -295
  158. data/spec/integration/schema/predicates/custom_spec.rb +0 -103
  159. data/spec/integration/schema/predicates/empty_spec.rb +0 -263
  160. data/spec/integration/schema/predicates/eql_spec.rb +0 -327
  161. data/spec/integration/schema/predicates/even_spec.rb +0 -455
  162. data/spec/integration/schema/predicates/excluded_from/array_spec.rb +0 -459
  163. data/spec/integration/schema/predicates/excluded_from/range_spec.rb +0 -459
  164. data/spec/integration/schema/predicates/excludes_spec.rb +0 -391
  165. data/spec/integration/schema/predicates/filled_spec.rb +0 -467
  166. data/spec/integration/schema/predicates/format_spec.rb +0 -455
  167. data/spec/integration/schema/predicates/gt_spec.rb +0 -519
  168. data/spec/integration/schema/predicates/gteq_spec.rb +0 -519
  169. data/spec/integration/schema/predicates/hash_spec.rb +0 -69
  170. data/spec/integration/schema/predicates/included_in/array_spec.rb +0 -459
  171. data/spec/integration/schema/predicates/included_in/range_spec.rb +0 -459
  172. data/spec/integration/schema/predicates/includes_spec.rb +0 -391
  173. data/spec/integration/schema/predicates/key_spec.rb +0 -88
  174. data/spec/integration/schema/predicates/lt_spec.rb +0 -520
  175. data/spec/integration/schema/predicates/lteq_spec.rb +0 -519
  176. data/spec/integration/schema/predicates/max_size_spec.rb +0 -391
  177. data/spec/integration/schema/predicates/min_size_spec.rb +0 -391
  178. data/spec/integration/schema/predicates/none_spec.rb +0 -265
  179. data/spec/integration/schema/predicates/not_eql_spec.rb +0 -391
  180. data/spec/integration/schema/predicates/odd_spec.rb +0 -455
  181. data/spec/integration/schema/predicates/size/fixed_spec.rb +0 -398
  182. data/spec/integration/schema/predicates/size/range_spec.rb +0 -395
  183. data/spec/integration/schema/predicates/type_spec.rb +0 -413
  184. data/spec/integration/schema/reusing_schema_spec.rb +0 -33
  185. data/spec/integration/schema/using_types_spec.rb +0 -135
  186. data/spec/integration/schema/validate_spec.rb +0 -120
  187. data/spec/integration/schema/xor_spec.rb +0 -35
  188. data/spec/integration/schema_builders_spec.rb +0 -17
  189. data/spec/integration/schema_spec.rb +0 -173
  190. data/spec/shared/message_compiler.rb +0 -11
  191. data/spec/shared/predicate_helper.rb +0 -15
  192. data/spec/shared/rule_compiler.rb +0 -8
  193. data/spec/spec_helper.rb +0 -62
  194. data/spec/support/define_struct.rb +0 -25
  195. data/spec/support/matchers.rb +0 -38
  196. data/spec/support/mutant.rb +0 -9
  197. data/spec/support/predicates_integration.rb +0 -7
  198. data/spec/unit/input_processor_compiler/json_spec.rb +0 -283
  199. data/spec/unit/input_processor_compiler/params_spec.rb +0 -328
  200. data/spec/unit/message_compiler/visit_failure_spec.rb +0 -38
  201. data/spec/unit/message_compiler/visit_spec.rb +0 -16
  202. data/spec/unit/message_compiler_spec.rb +0 -7
  203. data/spec/unit/predicate_registry_spec.rb +0 -34
  204. data/spec/unit/schema/key_spec.rb +0 -38
  205. data/spec/unit/schema/rule_spec.rb +0 -42
  206. data/spec/unit/schema/value_spec.rb +0 -131
  207. data/spec/unit/schema_spec.rb +0 -35
@@ -1,70 +0,0 @@
1
- module Dry
2
- module Validation
3
- module TypeSpecs
4
- def self.extended(klass)
5
- super
6
- klass.class_eval do
7
- setting :input_processor, :noop
8
- setting :hash_type, :weak
9
- setting :type_map, {}
10
- end
11
- end
12
-
13
- def build_type_map(type_specs, category = config.input_processor)
14
- if type_specs.is_a?(Array)
15
- build_array_type(type_specs[0], category)
16
- else
17
- type_specs.reduce({}) { |res, (name, spec)|
18
- res.update(name => resolve_spec(spec, category))
19
- }
20
- end
21
- end
22
-
23
- def build_hash_type(spec = type_map)
24
- lookup_type("hash", config.input_processor)
25
- .public_send(config.hash_type, spec)
26
- end
27
-
28
- def build_array_type(spec, category)
29
- member_schema = build_type_map(spec, category)
30
- member_type = lookup_type("hash", category)
31
- .public_send(config.hash_type, member_schema)
32
-
33
- lookup_type("array", category).of(member_type)
34
- end
35
-
36
- def build_sum_type(spec, category)
37
- spec
38
- .map { |id| id.is_a?(Symbol) ? lookup_type(id, category) : id }
39
- .reduce(:|)
40
- end
41
-
42
- def resolve_spec(spec, category)
43
- case spec
44
- when Symbol
45
- lookup_type(spec, category)
46
- when Hash
47
- build_hash_type(spec)
48
- when Array
49
- if spec.size == 1
50
- if spec[0].is_a?(Hash)
51
- build_array_type(spec[0], category)
52
- else
53
- array_member = lookup_type(spec[0], category)
54
- lookup_type("array", category).of(array_member)
55
- end
56
- else
57
- build_sum_type(spec, category)
58
- end
59
- else
60
- spec
61
- end
62
- end
63
-
64
- def lookup_type(name, category)
65
- id = "#{category}.#{name}"
66
- Types.type_keys.include?(id) ? Types[id] : Types[name.to_s]
67
- end
68
- end
69
- end
70
- end
data/log/.gitkeep DELETED
File without changes
@@ -1,40 +0,0 @@
1
- RSpec.describe Dry::Validation::Result do
2
- before { Dry::Validation.load_extensions(:monads) }
3
-
4
- let(:schema) { Dry::Validation.Schema { required(:name).filled(:str?, size?: 2..4) } }
5
-
6
- context 'with valid input' do
7
- let(:input) { { name: 'Jane' } }
8
-
9
- describe '#to_monad' do
10
- it 'returns a Success value' do
11
- monad = result.to_monad
12
-
13
- expect(monad).to be_a Dry::Monads::Result
14
- expect(monad).to be_a_success
15
- expect(monad.value!).to eql(name: 'Jane')
16
- end
17
- end
18
- end
19
-
20
- context 'with invalid input' do
21
- let(:input) { { name: '' } }
22
-
23
- describe '#to_monad' do
24
- it 'returns a Failure value' do
25
- monad = result.to_monad
26
-
27
- expect(monad).to be_a_failure
28
- expect(monad.failure).to eql(name: ['must be filled', 'length must be within 2 - 4'])
29
- end
30
-
31
- it 'returns full messages' do
32
- monad = result.to_monad(full: true)
33
-
34
- expect(monad).to be_a Dry::Monads::Result
35
- expect(monad).to be_a_failure
36
- expect(monad.failure).to eql(name: ['name must be filled', 'name length must be within 2 - 4'])
37
- end
38
- end
39
- end
40
- end
@@ -1,32 +0,0 @@
1
- RSpec.describe Dry::Validation::Schema, 'defining schema using dry struct' do
2
- before do
3
- Dry::Validation.load_extensions(:struct)
4
- end
5
-
6
- subject(:schema) do
7
- Dry::Validation.Schema do
8
- required(:person).filled(Test::Person)
9
- end
10
- end
11
-
12
- before do
13
- class Test::Name < Dry::Struct::Value
14
- attribute :given_name, Dry::Types['strict.string']
15
- attribute :family_name, Dry::Types['strict.string']
16
- end
17
-
18
- class Test::Person < Dry::Struct::Value
19
- attribute :name, Test::Name
20
- end
21
- end
22
-
23
- it 'handles nested structs' do
24
- expect(schema.call(person: { name: { given_name: 'Tim', family_name: 'Cooper' } })).to be_success
25
- end
26
-
27
- it 'fails when input is not valid' do
28
- expect(schema.call(person: { name: { given_name: 'Tim' } }).messages).to eq(
29
- person: { name: { family_name: ['is missing', 'must be String'] } }
30
- )
31
- end
32
- end
@@ -1,8 +0,0 @@
1
- en:
2
- errors:
3
- rules:
4
- email:
5
- filled?: "Please provide your email"
6
- age:
7
- gt?: "%{input} must be greater than %{num}"
8
- email?: "must be an email"
@@ -1,22 +0,0 @@
1
- pl:
2
- errors:
3
- filled?: "nie może być pusty"
4
- size?:
5
- arg:
6
- default: "wielkość musi być równa %{size}"
7
- range: "wielkość musi być między %{size_left} a %{size_right}"
8
- value:
9
- string:
10
- arg:
11
- default: "wielkość musi być równa %{size}"
12
- rules:
13
- email:
14
- filled?: "Proszę podać adres email"
15
- user:
16
- rules:
17
- email:
18
- filled?: "Hej user! Dawaj ten email no!"
19
-
20
- rules:
21
- email:
22
- 'Adres email'
@@ -1,54 +0,0 @@
1
- require 'dry/validation/messages/i18n'
2
-
3
- RSpec.describe Dry::Validation do
4
- shared_context 'schema with customized messages' do
5
- describe '#messages' do
6
- it 'returns compiled error messages' do
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']
13
- )
14
- end
15
- end
16
- end
17
-
18
- context 'yaml' do
19
- subject(:schema) do
20
- Dry::Validation.Schema do
21
- configure do
22
- config.messages_file = SPEC_ROOT.join('fixtures/locales/en.yml')
23
- end
24
-
25
- required(:email).filled
26
- required(:age).value(gt?: 18)
27
- end
28
- end
29
-
30
- include_context 'schema with customized messages'
31
- end
32
-
33
- context 'i18n' do
34
- context 'with custom messages set globally' do
35
- before do
36
- I18n.load_path << SPEC_ROOT.join('fixtures/locales/en.yml')
37
- I18n.backend.load_translations
38
- end
39
-
40
- subject(:schema) do
41
- Dry::Validation.Schema do
42
- configure do
43
- config.messages = :i18n
44
- end
45
-
46
- required(:email).filled
47
- required(:age).value(gt?: 18)
48
- end
49
- end
50
-
51
- include_context 'schema with customized messages'
52
- end
53
- end
54
- end
@@ -1,228 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- RSpec.describe Dry::Validation do
3
- shared_context 'uses custom predicates' do
4
- it 'uses provided custom predicates' do
5
- expect(schema.(email: 'jane@doe')).to be_success
6
-
7
- expect(schema.(email: nil).messages).to eql(
8
- email: ['must be filled', 'must be a valid email']
9
- )
10
-
11
- expect(schema.(email: 'jane').messages).to eql(
12
- email: ['must be a valid email']
13
- )
14
- end
15
- end
16
-
17
- let(:base_class) do
18
- Class.new(Dry::Validation::Schema) do
19
- def self.messages
20
- Dry::Validation::Messages.default.merge(
21
- en: { errors: { email?: 'must be a valid email' } }
22
- )
23
- end
24
- end
25
- end
26
-
27
- describe 'defining schema with custom predicates container' do
28
- before do
29
- module Test
30
- module Predicates
31
- include Dry::Logic::Predicates
32
-
33
- def self.email?(input)
34
- input.include?('@') # for the lols
35
- end
36
- end
37
- end
38
- end
39
-
40
- context 'when configured globally' do
41
- subject(:schema) do
42
- Dry::Validation.Schema(base_class) do
43
- required(:email) { filled? & email? }
44
- end
45
- end
46
-
47
- before do
48
- Dry::Validation::Schema.predicates(Test::Predicates)
49
- end
50
-
51
- after do
52
- # HACK: reset global predicates configuration
53
- Dry::Validation::Schema.configure do |config|
54
- config.predicates = Dry::Logic::Predicates
55
- end
56
- end
57
-
58
- include_context 'uses custom predicates'
59
- end
60
-
61
- context 'when configured locally' do
62
- subject(:schema) do
63
- Dry::Validation.Schema(base_class) do
64
- configure do
65
- predicates(Test::Predicates)
66
- end
67
-
68
- required(:email) { filled? & email? }
69
- end
70
- end
71
-
72
- include_context 'uses custom predicates'
73
- end
74
- end
75
-
76
- describe 'defining schema with custom predicate methods' do
77
- subject(:schema) do
78
- Dry::Validation.Schema(base_class) do
79
- configure do
80
- def email?(value)
81
- value.include?('@')
82
- end
83
- end
84
-
85
- required(:email) { filled? & email? }
86
- end
87
- end
88
-
89
- include_context 'uses custom predicates'
90
- end
91
-
92
- describe 'custom predicate which requires an arbitrary dependency' do
93
- subject(:schema) do
94
- Dry::Validation.Schema(base_class) do
95
- configure do
96
- option :email_check
97
-
98
- def email?(value)
99
- email_check.(value)
100
- end
101
- end
102
-
103
- required(:email).filled(:email?)
104
- end
105
- end
106
-
107
- it 'uses injected dependency for the custom predicate' do
108
- email_check = -> input { input.include?('@') }
109
-
110
- expect(schema.with(email_check: email_check).(email: 'foo').messages).to eql(
111
- email: ['must be a valid email']
112
- )
113
- end
114
- end
115
-
116
- it 'raises an error when message is missing' do
117
- schema = Dry::Validation.Schema do
118
- configure do
119
- def email?(value)
120
- false
121
- end
122
- end
123
-
124
- required(:email).filled(:email?)
125
- end
126
-
127
- expect { schema.(email: 'foo').messages }.to raise_error(
128
- Dry::Validation::MissingMessageError, /email/
129
- )
130
- end
131
-
132
- it 'works with custom predicate args' do
133
- schema = Dry::Validation.Schema do
134
- configure do
135
- def self.messages
136
- Dry::Validation::Messages.default.merge(
137
- en: { errors: { fav_number?: 'must be %{expected}' } }
138
- )
139
- end
140
- def fav_number?(expected, current)
141
- current == expected
142
- end
143
- end
144
-
145
- required(:foo) { fav_number?(23) }
146
- end
147
-
148
- expect(schema.(foo: 20).messages).to eql(
149
- foo: ['must be 23']
150
- )
151
-
152
- end
153
-
154
- it 'works when no predicate args' do
155
- schema = Dry::Validation.Schema do
156
- configure do
157
- def self.messages
158
- Dry::Validation::Messages.default.merge(
159
- en: { errors: { with_no_args?: 'is always false' } }
160
- )
161
- end
162
-
163
- def with_no_args?
164
- false
165
- end
166
- end
167
-
168
- required(:email).filled(:with_no_args?)
169
- end
170
-
171
- expect(schema.(email: 'foo').messages).to eql(
172
- email: ['is always false']
173
- )
174
- end
175
-
176
- it 'works with nested schemas' do
177
- schema = Dry::Validation.Schema do
178
- configure do
179
- def ok?(_value)
180
- true
181
- end
182
- end
183
-
184
- required(:foo).schema do
185
- required(:bar).value(:ok?)
186
- end
187
- end
188
-
189
- expect(schema.(foo: { bar: "1" })).to be_success
190
- end
191
-
192
- it 'works with interpolation of messages' do
193
- schema = Dry::Validation.Schema do
194
- configure do
195
- option :categories, []
196
-
197
- def self.messages
198
- Dry::Validation::Messages.default.merge(
199
- en: {
200
- errors: {
201
- valid_category?: 'must be one of the categories: %{categories}'
202
- }
203
- },
204
- pl: {
205
- errors: {
206
- valid_category?: 'musi być jedną z: %{categories}'
207
- }
208
- }
209
- )
210
- end
211
-
212
- def valid_category?(categories, value)
213
- categories.include?(value)
214
- end
215
- end
216
-
217
- required(:category).filled(valid_category?: categories)
218
- end.with(categories: %w(foo bar))
219
-
220
- expect(schema.(category: 'baz').messages).to eql(
221
- category: ['must be one of the categories: foo, bar']
222
- )
223
-
224
- expect(schema.(category: 'baz').messages(locale: :pl)).to eql(
225
- category: ['musi być jedną z: foo, bar']
226
- )
227
- end
228
- end
@@ -1,170 +0,0 @@
1
- require 'dry/validation/messages/i18n'
2
-
3
- RSpec.describe 'Validation hints' do
4
- shared_context '#messages' do
5
- it 'provides hints for additional rules that were not checked' do
6
- expect(schema.(age: '17').messages).to eql(
7
- age: ['must be an integer', 'must be greater than 18']
8
- )
9
- end
10
-
11
- it 'skips type-check rules' do
12
- expect(schema.(age: 17).messages).to eql(
13
- age: ['must be greater than 18']
14
- )
15
- end
16
- end
17
-
18
- context 'with yaml messages' do
19
- subject(:schema) do
20
- Dry::Validation.Schema do
21
- required(:age).maybe(:int?, gt?: 18)
22
- end
23
- end
24
-
25
- include_context '#messages'
26
- end
27
-
28
- context 'with i18n messages' do
29
- subject(:schema) do
30
- Dry::Validation.Schema do
31
- configure { configure { |c| c.messages = :i18n } }
32
-
33
- required(:age).maybe(:int?, gt?: 18)
34
- end
35
- end
36
-
37
- include_context '#messages'
38
- end
39
-
40
- context 'when type expectation is specified' do
41
- subject(:schema) do
42
- Dry::Validation.Schema do
43
- required(:email).filled
44
- required(:name).filled(:str?, size?: 5..25)
45
- end
46
- end
47
-
48
- it 'infers message for specific type' do
49
- expect(schema.(email: 'jane@doe', name: 'HN').messages).to eql(
50
- name: ['length must be within 5 - 25']
51
- )
52
- end
53
- end
54
-
55
- context 'when predicate failed and there is a corresponding hint generated' do
56
- subject(:schema) do
57
- Dry::Validation.Schema do
58
- required(:age).value(lt?: 23)
59
- end
60
- end
61
-
62
- it 'provides only failure error message' do
63
- result = schema.call(age: 23)
64
- expect(result.messages).to eql(age: ['must be less than 23'])
65
- end
66
- end
67
-
68
- context 'with a nested schema with same rule names' do
69
- subject(:schema) do
70
- Dry::Validation.Schema do
71
- required(:code).filled(:str?, eql?: 'foo')
72
-
73
- required(:nested).schema do
74
- required(:code).filled(:str?, eql?: 'bar')
75
- end
76
- end
77
- end
78
-
79
- it 'provides error messages' do
80
- result = schema.call(code: 'x', nested: { code: 'y' })
81
-
82
- expect(result.messages).to eql(
83
- code: ['must be equal to foo'],
84
- nested: {
85
- code: ['must be equal to bar']
86
- }
87
- )
88
- end
89
-
90
- it 'provides hints' do
91
- result = schema.call(code: '', nested: { code: '' })
92
-
93
- expect(result.messages).to eql(
94
- code: ['must be filled', 'must be equal to foo'],
95
- nested: {
96
- code: ['must be filled', 'must be equal to bar']
97
- }
98
- )
99
- end
100
- end
101
-
102
- context 'with an each rule' do
103
- subject(:schema) do
104
- Dry::Validation.Schema do
105
- required(:nums).each(:int?, gt?: 0)
106
- end
107
- end
108
-
109
- it 'provides hints for each element' do
110
- expect(schema.(nums: [1, 'foo', 0]).messages).to eql(
111
- nums: {
112
- 1 => ['must be an integer', 'must be greater than 0'],
113
- 2 => ['must be greater than 0']
114
- }
115
- )
116
- end
117
- end
118
-
119
- context 'with a format? predicate' do
120
- subject(:schema) do
121
- Dry::Validation.Schema do
122
- required(:name).value(size?: 2, format?: /xy/)
123
- end
124
- end
125
-
126
- it 'skips hints' do
127
- expect(schema.(name: 'x').messages[:name]).to_not include('is in invalid format')
128
- expect(schema.(name: 'ab').messages[:name]).to include('is in invalid format')
129
- end
130
- end
131
-
132
- context 'when the message uses input value' do
133
- subject(:schema) do
134
- Dry::Validation.Schema do
135
- configure do
136
- def self.messages
137
- Messages.default.merge(
138
- en: {
139
- errors: {
140
- blue?: {
141
- failure: '%{value} is not equal to blue',
142
- hint: 'must be equal to blue'
143
- }
144
- }
145
- }
146
- )
147
- end
148
-
149
- def blue?(value)
150
- value == 'blue'
151
- end
152
- end
153
-
154
- required(:pill).filled(:blue?)
155
- end
156
- end
157
-
158
- it 'provides a correct failure message' do
159
- expect(schema.(pill: 'red').messages).to eql(
160
- pill: ['red is not equal to blue']
161
- )
162
- end
163
-
164
- it 'provides a correct hint' do
165
- expect(schema.(pill: nil).messages).to eql(
166
- pill: ['must be filled', 'must be equal to blue']
167
- )
168
- end
169
- end
170
- end
@@ -1,30 +0,0 @@
1
- RSpec.describe 'Schema / Injecting Rules' do
2
- subject(:schema) do
3
- Dry::Validation.Schema(rules: other.class.rules) do
4
- required(:email).maybe
5
-
6
- rule(:email) { value(:login).true? > value(:email).filled? }
7
- end
8
- end
9
-
10
- let(:other) do
11
- Dry::Validation.Schema do
12
- required(:login) { |value| value.bool? }
13
- end
14
- end
15
-
16
- it 'appends rules from another schema' do
17
- expect(schema.(login: true, email: 'jane@doe')).to be_success
18
- expect(schema.(login: false, email: nil)).to be_success
19
- expect(schema.(login: true, email: nil)).to_not be_success
20
- expect(schema.(login: nil, email: 'jane@doe')).to_not be_success
21
- end
22
-
23
- it 'keeps the original schema rules intact' do
24
- expect(other.class.rules.size).to eq(1)
25
-
26
- schema.(login: true, email: 'jane@doe')
27
-
28
- expect(other.class.rules.size).to eq(1)
29
- end
30
- end
@@ -1,41 +0,0 @@
1
- require 'dry/validation/messages/i18n'
2
- require 'i18n'
3
-
4
- RSpec.describe 'Defining base schema class' do
5
- subject(:schema) do
6
- Dry::Validation.JSON(BaseSchema) do
7
- required(:email).filled(:email?)
8
- end
9
- end
10
-
11
- before do
12
- class BaseSchema < Dry::Validation::Schema
13
- configure do |config|
14
- config.messages_file = SPEC_ROOT.join('fixtures/locales/en.yml')
15
- config.messages = :i18n
16
- end
17
-
18
- def email?(value)
19
- true
20
- end
21
-
22
- define! do
23
- required(:name).filled
24
- end
25
- end
26
- end
27
-
28
- after do
29
- Object.send(:remove_const, :BaseSchema)
30
- end
31
-
32
- it 'inherits predicates' do
33
- expect(schema).to respond_to(:email?)
34
- end
35
-
36
- it 'inherits rules' do
37
- expect(schema.('name' => '').messages).to eql(
38
- name: ['must be filled'], email: ['is missing', 'must be an email']
39
- )
40
- end
41
- end