dry-validation 0.13.3 → 1.3.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.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +233 -12
  3. data/LICENSE +1 -1
  4. data/README.md +13 -9
  5. data/config/errors.yml +3 -88
  6. data/lib/dry-validation.rb +2 -0
  7. data/lib/dry/validation.rb +47 -28
  8. data/lib/dry/validation/config.rb +24 -0
  9. data/lib/dry/validation/constants.rb +43 -0
  10. data/lib/dry/validation/contract.rb +160 -0
  11. data/lib/dry/validation/contract/class_interface.rb +223 -0
  12. data/lib/dry/validation/evaluator.rb +197 -0
  13. data/lib/dry/validation/extensions/hints.rb +69 -0
  14. data/lib/dry/validation/extensions/monads.rb +23 -7
  15. data/lib/dry/validation/extensions/predicates_as_macros.rb +75 -0
  16. data/lib/dry/validation/failures.rb +58 -0
  17. data/lib/dry/validation/function.rb +44 -0
  18. data/lib/dry/validation/macro.rb +38 -0
  19. data/lib/dry/validation/macros.rb +104 -0
  20. data/lib/dry/validation/message.rb +79 -79
  21. data/lib/dry/validation/message_set.rb +108 -88
  22. data/lib/dry/validation/messages/resolver.rb +79 -0
  23. data/lib/dry/validation/result.rb +154 -42
  24. data/lib/dry/validation/rule.rb +129 -0
  25. data/lib/dry/validation/schema_ext.rb +46 -0
  26. data/lib/dry/validation/values.rb +94 -0
  27. data/lib/dry/validation/version.rb +3 -1
  28. metadata +41 -336
  29. data/.codeclimate.yml +0 -17
  30. data/.gitignore +0 -9
  31. data/.rspec +0 -3
  32. data/.travis.yml +0 -29
  33. data/CONTRIBUTING.md +0 -31
  34. data/Gemfile +0 -25
  35. data/Rakefile +0 -22
  36. data/benchmarks/benchmark_form_invalid.rb +0 -64
  37. data/benchmarks/benchmark_form_valid.rb +0 -64
  38. data/benchmarks/benchmark_schema_invalid_huge.rb +0 -52
  39. data/benchmarks/profile_schema_call_invalid.rb +0 -20
  40. data/benchmarks/profile_schema_call_valid.rb +0 -20
  41. data/benchmarks/profile_schema_definition.rb +0 -14
  42. data/benchmarks/profile_schema_huge_invalid.rb +0 -30
  43. data/benchmarks/profile_schema_messages_invalid.rb +0 -20
  44. data/benchmarks/suite.rb +0 -5
  45. data/dry-validation.gemspec +0 -28
  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.rb +0 -7
  56. data/lib/dry/validation/extensions/struct.rb +0 -32
  57. data/lib/dry/validation/input_processor_compiler.rb +0 -137
  58. data/lib/dry/validation/input_processor_compiler/json.rb +0 -45
  59. data/lib/dry/validation/input_processor_compiler/params.rb +0 -49
  60. data/lib/dry/validation/input_processor_compiler/sanitizer.rb +0 -47
  61. data/lib/dry/validation/message_compiler.rb +0 -188
  62. data/lib/dry/validation/message_compiler/visitor_opts.rb +0 -37
  63. data/lib/dry/validation/messages.rb +0 -14
  64. data/lib/dry/validation/messages/abstract.rb +0 -119
  65. data/lib/dry/validation/messages/i18n.rb +0 -47
  66. data/lib/dry/validation/messages/namespaced.rb +0 -39
  67. data/lib/dry/validation/messages/yaml.rb +0 -61
  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.rb +0 -126
  71. data/lib/dry/validation/schema/check.rb +0 -37
  72. data/lib/dry/validation/schema/class_interface.rb +0 -190
  73. data/lib/dry/validation/schema/deprecated.rb +0 -30
  74. data/lib/dry/validation/schema/dsl.rb +0 -118
  75. data/lib/dry/validation/schema/form.rb +0 -9
  76. data/lib/dry/validation/schema/json.rb +0 -21
  77. data/lib/dry/validation/schema/key.rb +0 -71
  78. data/lib/dry/validation/schema/params.rb +0 -22
  79. data/lib/dry/validation/schema/rule.rb +0 -202
  80. data/lib/dry/validation/schema/value.rb +0 -211
  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/spec/extensions/monads/result_spec.rb +0 -40
  85. data/spec/extensions/struct/schema_spec.rb +0 -32
  86. data/spec/fixtures/locales/en.yml +0 -8
  87. data/spec/fixtures/locales/pl.yml +0 -22
  88. data/spec/integration/custom_error_messages_spec.rb +0 -54
  89. data/spec/integration/custom_predicates_spec.rb +0 -228
  90. data/spec/integration/hints_spec.rb +0 -170
  91. data/spec/integration/injecting_rules_spec.rb +0 -30
  92. data/spec/integration/json/defining_base_schema_spec.rb +0 -41
  93. data/spec/integration/localized_error_messages_spec.rb +0 -72
  94. data/spec/integration/message_compiler_spec.rb +0 -405
  95. data/spec/integration/messages/i18n_spec.rb +0 -104
  96. data/spec/integration/optional_keys_spec.rb +0 -28
  97. data/spec/integration/params/predicates/array_spec.rb +0 -287
  98. data/spec/integration/params/predicates/empty_spec.rb +0 -263
  99. data/spec/integration/params/predicates/eql_spec.rb +0 -327
  100. data/spec/integration/params/predicates/even_spec.rb +0 -455
  101. data/spec/integration/params/predicates/excluded_from_spec.rb +0 -455
  102. data/spec/integration/params/predicates/excludes_spec.rb +0 -391
  103. data/spec/integration/params/predicates/false_spec.rb +0 -455
  104. data/spec/integration/params/predicates/filled_spec.rb +0 -467
  105. data/spec/integration/params/predicates/format_spec.rb +0 -454
  106. data/spec/integration/params/predicates/gt_spec.rb +0 -519
  107. data/spec/integration/params/predicates/gteq_spec.rb +0 -519
  108. data/spec/integration/params/predicates/included_in_spec.rb +0 -455
  109. data/spec/integration/params/predicates/includes_spec.rb +0 -391
  110. data/spec/integration/params/predicates/key_spec.rb +0 -67
  111. data/spec/integration/params/predicates/lt_spec.rb +0 -519
  112. data/spec/integration/params/predicates/lteq_spec.rb +0 -519
  113. data/spec/integration/params/predicates/max_size_spec.rb +0 -391
  114. data/spec/integration/params/predicates/min_size_spec.rb +0 -391
  115. data/spec/integration/params/predicates/none_spec.rb +0 -265
  116. data/spec/integration/params/predicates/not_eql_spec.rb +0 -327
  117. data/spec/integration/params/predicates/odd_spec.rb +0 -455
  118. data/spec/integration/params/predicates/size/fixed_spec.rb +0 -393
  119. data/spec/integration/params/predicates/size/range_spec.rb +0 -396
  120. data/spec/integration/params/predicates/true_spec.rb +0 -455
  121. data/spec/integration/params/predicates/type_spec.rb +0 -391
  122. data/spec/integration/result_spec.rb +0 -81
  123. data/spec/integration/schema/array_schema_spec.rb +0 -59
  124. data/spec/integration/schema/check_rules_spec.rb +0 -119
  125. data/spec/integration/schema/check_with_nested_el_spec.rb +0 -37
  126. data/spec/integration/schema/check_with_nth_el_spec.rb +0 -25
  127. data/spec/integration/schema/default_settings_spec.rb +0 -11
  128. data/spec/integration/schema/defining_base_schema_spec.rb +0 -41
  129. data/spec/integration/schema/dynamic_predicate_args_spec.rb +0 -43
  130. data/spec/integration/schema/each_with_set_spec.rb +0 -70
  131. data/spec/integration/schema/extending_dsl_spec.rb +0 -27
  132. data/spec/integration/schema/form_spec.rb +0 -236
  133. data/spec/integration/schema/hash_schema_spec.rb +0 -47
  134. data/spec/integration/schema/inheriting_schema_spec.rb +0 -31
  135. data/spec/integration/schema/input_processor_spec.rb +0 -46
  136. data/spec/integration/schema/json/explicit_types_spec.rb +0 -157
  137. data/spec/integration/schema/json_spec.rb +0 -163
  138. data/spec/integration/schema/macros/confirmation_spec.rb +0 -35
  139. data/spec/integration/schema/macros/each_spec.rb +0 -268
  140. data/spec/integration/schema/macros/filled_spec.rb +0 -87
  141. data/spec/integration/schema/macros/input_spec.rb +0 -139
  142. data/spec/integration/schema/macros/maybe_spec.rb +0 -99
  143. data/spec/integration/schema/macros/rule_spec.rb +0 -75
  144. data/spec/integration/schema/macros/value_spec.rb +0 -119
  145. data/spec/integration/schema/macros/when_spec.rb +0 -62
  146. data/spec/integration/schema/nested_schemas_spec.rb +0 -236
  147. data/spec/integration/schema/nested_values_spec.rb +0 -46
  148. data/spec/integration/schema/not_spec.rb +0 -34
  149. data/spec/integration/schema/numbers_spec.rb +0 -19
  150. data/spec/integration/schema/option_with_default_spec.rb +0 -64
  151. data/spec/integration/schema/or_spec.rb +0 -87
  152. data/spec/integration/schema/params/defining_base_schema_spec.rb +0 -41
  153. data/spec/integration/schema/params/explicit_types_spec.rb +0 -195
  154. data/spec/integration/schema/params_spec.rb +0 -234
  155. data/spec/integration/schema/predicate_verification_spec.rb +0 -9
  156. data/spec/integration/schema/predicates/array_spec.rb +0 -295
  157. data/spec/integration/schema/predicates/custom_spec.rb +0 -103
  158. data/spec/integration/schema/predicates/empty_spec.rb +0 -263
  159. data/spec/integration/schema/predicates/eql_spec.rb +0 -327
  160. data/spec/integration/schema/predicates/even_spec.rb +0 -455
  161. data/spec/integration/schema/predicates/excluded_from/array_spec.rb +0 -459
  162. data/spec/integration/schema/predicates/excluded_from/range_spec.rb +0 -459
  163. data/spec/integration/schema/predicates/excludes_spec.rb +0 -391
  164. data/spec/integration/schema/predicates/filled_spec.rb +0 -467
  165. data/spec/integration/schema/predicates/format_spec.rb +0 -455
  166. data/spec/integration/schema/predicates/gt_spec.rb +0 -519
  167. data/spec/integration/schema/predicates/gteq_spec.rb +0 -519
  168. data/spec/integration/schema/predicates/hash_spec.rb +0 -69
  169. data/spec/integration/schema/predicates/included_in/array_spec.rb +0 -459
  170. data/spec/integration/schema/predicates/included_in/range_spec.rb +0 -459
  171. data/spec/integration/schema/predicates/includes_spec.rb +0 -391
  172. data/spec/integration/schema/predicates/key_spec.rb +0 -88
  173. data/spec/integration/schema/predicates/lt_spec.rb +0 -520
  174. data/spec/integration/schema/predicates/lteq_spec.rb +0 -519
  175. data/spec/integration/schema/predicates/max_size_spec.rb +0 -391
  176. data/spec/integration/schema/predicates/min_size_spec.rb +0 -391
  177. data/spec/integration/schema/predicates/none_spec.rb +0 -265
  178. data/spec/integration/schema/predicates/not_eql_spec.rb +0 -391
  179. data/spec/integration/schema/predicates/odd_spec.rb +0 -455
  180. data/spec/integration/schema/predicates/size/fixed_spec.rb +0 -398
  181. data/spec/integration/schema/predicates/size/range_spec.rb +0 -395
  182. data/spec/integration/schema/predicates/type_spec.rb +0 -413
  183. data/spec/integration/schema/reusing_schema_spec.rb +0 -33
  184. data/spec/integration/schema/using_types_spec.rb +0 -135
  185. data/spec/integration/schema/validate_spec.rb +0 -120
  186. data/spec/integration/schema/xor_spec.rb +0 -35
  187. data/spec/integration/schema_builders_spec.rb +0 -17
  188. data/spec/integration/schema_spec.rb +0 -173
  189. data/spec/shared/message_compiler.rb +0 -11
  190. data/spec/shared/predicate_helper.rb +0 -15
  191. data/spec/shared/rule_compiler.rb +0 -8
  192. data/spec/spec_helper.rb +0 -62
  193. data/spec/support/define_struct.rb +0 -25
  194. data/spec/support/matchers.rb +0 -38
  195. data/spec/support/mutant.rb +0 -9
  196. data/spec/support/predicates_integration.rb +0 -7
  197. data/spec/unit/input_processor_compiler/json_spec.rb +0 -283
  198. data/spec/unit/input_processor_compiler/params_spec.rb +0 -328
  199. data/spec/unit/message_compiler/visit_failure_spec.rb +0 -38
  200. data/spec/unit/message_compiler/visit_spec.rb +0 -16
  201. data/spec/unit/message_compiler_spec.rb +0 -7
  202. data/spec/unit/predicate_registry_spec.rb +0 -34
  203. data/spec/unit/schema/key_spec.rb +0 -38
  204. data/spec/unit/schema/rule_spec.rb +0 -42
  205. data/spec/unit/schema/value_spec.rb +0 -131
  206. data/spec/unit/schema_spec.rb +0 -35
@@ -1,66 +0,0 @@
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
@@ -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
@@ -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