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,46 +0,0 @@
1
- RSpec.describe Schema, 'using nested values' do
2
- let(:schema) do
3
- Dry::Validation.Schema do
4
- required(:email).maybe
5
-
6
- required(:settings).schema do
7
- optional(:offers).filled(:bool?)
8
- required(:newsletter).filled(:bool?)
9
- end
10
-
11
- rule(newsletter: [[:settings, :newsletter], [:settings, :offers]]) do |newsletter, offers|
12
- offers.true?.then(newsletter.false?)
13
- end
14
-
15
- rule(email: [[:settings, :newsletter], :email]) do |newsletter, email|
16
- newsletter.true?.then(email.filled?)
17
- end
18
- end
19
- end
20
-
21
- it 'passes when newsletter setting is false' do
22
- expect(schema.(settings: { newsletter: false }, email: nil)).to be_success
23
- end
24
-
25
- it 'passes when newsletter setting is true and email is filled' do
26
- expect(schema.(settings: { newsletter: false }, email: 'jane@doe')).to be_success
27
- end
28
-
29
- it 'passes when offers is false and newsletter is true' do
30
- expect(schema.(settings: { offers: false, newsletter: true }, email: 'jane@doe')).to be_success
31
- end
32
-
33
- it 'fails when newsletter is true and email is not filled' do
34
- expect(schema.(settings: { newsletter: true }, email: nil).messages).to eql(
35
- email: ['must be filled']
36
- )
37
- end
38
-
39
- it 'fails when offers is true and newsletter is true' do
40
- input = { settings: { offers: true, newsletter: true }, email: 'jane@doe' }
41
-
42
- expect(schema.(input).messages).to eql(
43
- settings: { newsletter: ['must be false'] }
44
- )
45
- end
46
- end
@@ -1,34 +0,0 @@
1
- RSpec.describe 'Schema with negated rules' do
2
- subject(:schema) do
3
- Dry::Validation.Schema do
4
- configure do
5
- def self.messages
6
- Messages.default.merge(
7
- en: { errors: { be_reasonable: 'you cannot eat cake and have cake!' } }
8
- )
9
- end
10
- end
11
-
12
- optional(:eat_cake).filled
13
- optional(:have_cake).filled
14
-
15
- rule(:be_reasonable) do
16
- value(:eat_cake).eql?('yes!') & value(:have_cake).eql?('yes!').not
17
- end
18
- end
19
- end
20
-
21
- describe '#messages' do
22
- it 'passes when only one option is selected' do
23
- messages = schema.(eat_cake: 'yes!', have_cake: 'no!').messages[:be_reasonable]
24
-
25
- expect(messages).to be(nil)
26
- end
27
-
28
- it 'fails when both options are selected' do
29
- messages = schema.(eat_cake: 'yes!', have_cake: 'yes!').messages[:be_reasonable]
30
-
31
- expect(messages).to eql(['you cannot eat cake and have cake!'])
32
- end
33
- end
34
- end
@@ -1,19 +0,0 @@
1
- RSpec.describe Dry::Validation::Schema do
2
- subject(:schema) do
3
- Dry::Validation.Schema do
4
- required(:age).filled(:number?, :int?)
5
- end
6
- end
7
-
8
- it 'passes when value is a number and an int' do
9
- expect(schema.(age: 132)).to be_success
10
- end
11
-
12
- it 'fails when value is not a number' do
13
- expect(schema.(age: 'ops').messages).to eql(age: ['must be a number'])
14
- end
15
-
16
- it 'fails when value is not an integer' do
17
- expect(schema.(age: 1.0).messages).to eql(age: ['must be an integer'])
18
- end
19
- end
@@ -1,64 +0,0 @@
1
- RSpec.describe Dry::Validation::Schema, 'defining schema context with option API' do
2
- shared_context 'valid schema with :db option' do
3
- before do
4
- DB = [{ email: 'jane@doe' }]
5
- end
6
-
7
- after do
8
- Object.send(:remove_const, :DB)
9
- end
10
-
11
- it 'uses external dependency set by option with a default value' do
12
- expect(schema.db).to be(DB)
13
-
14
- expect(schema.(email: 'jade@doe', contact: { email: 'jade2@doe' })).to be_success
15
- expect(schema.(email: 'jane@doe', contact: { email: 'jane2@doe' })).to be_failure
16
- expect(schema.(email: 'jade@doe', contact: { email: 'jane@doe' })).to be_failure
17
- end
18
- end
19
-
20
-
21
- context 'with a default value' do
22
- subject(:schema) do
23
- Dry::Validation.Schema do
24
- configure do
25
- option :db, -> { DB }
26
-
27
- def unique?(name, value)
28
- db.none? { |item| item[name] == value }
29
- end
30
- end
31
-
32
- required(:email).filled(unique?: :email)
33
-
34
- required(:contact).schema do
35
- required(:email).filled(unique?: :email)
36
- end
37
- end
38
- end
39
-
40
- include_context 'valid schema with :db option'
41
- end
42
-
43
- context 'without a default value' do
44
- subject(:schema) do
45
- Dry::Validation.Schema do
46
- configure do
47
- option :db
48
-
49
- def unique?(name, value)
50
- db.none? { |item| item[name] == value }
51
- end
52
- end
53
-
54
- required(:email).filled(unique?: :email)
55
-
56
- required(:contact).schema do
57
- required(:email).filled(unique?: :email)
58
- end
59
- end.with(db: DB)
60
- end
61
-
62
- include_context 'valid schema with :db option'
63
- end
64
- end
@@ -1,87 +0,0 @@
1
- RSpec.describe Dry::Validation::Schema, 'OR messages' do
2
- context 'with two predicates' do
3
- subject(:schema) do
4
- Dry::Validation.Schema do
5
- required(:foo) { str? | int? }
6
- end
7
- end
8
-
9
- it 'returns success for valid input' do
10
- expect(schema.(foo: 'bar')).to be_success
11
- expect(schema.(foo: 321)).to be_success
12
- end
13
-
14
- it 'provides OR error message for invalid input where all both sides failed' do
15
- expect(schema.(foo: []).errors).to eql(foo: ['must be a string or must be an integer'])
16
- end
17
- end
18
-
19
- context 'with a predicate and a conjunction of predicates' do
20
- subject(:schema) do
21
- Dry::Validation.Schema do
22
- required(:foo) { str? | (int? & gt?(18)) }
23
- end
24
- end
25
-
26
- it 'returns success for valid input' do
27
- expect(schema.(foo: 'bar')).to be_success
28
- expect(schema.(foo: 321)).to be_success
29
- end
30
-
31
- it 'provides OR message for invalid input where both sides failed' do
32
- expect(schema.(foo: []).errors).to eql(foo: ['must be a string or must be an integer'])
33
- end
34
-
35
- it 'provides error messages for invalid input where right side failed' do
36
- expect(schema.(foo: 17).errors).to eql(foo: ['must be a string or must be greater than 18'])
37
- end
38
- end
39
-
40
- context 'with a predicate and an each operation' do
41
- subject(:schema) do
42
- Dry::Validation.Schema do
43
- required(:foo) { str? | each(:int?) }
44
- end
45
- end
46
-
47
- it 'returns success for valid input' do
48
- expect(schema.(foo: 'bar')).to be_success
49
- expect(schema.(foo: [1, 2, 3])).to be_success
50
- end
51
-
52
- it 'provides OR message for invalid input where both sides failed' do
53
- expect(schema.(foo: {}).errors).to eql(foo: ['must be a string or must be an array'])
54
- end
55
-
56
- it 'provides error messages for invalid input where right side failed' do
57
- expect(schema.(foo: %w(1 2 3)).errors).to eql(
58
- foo: {
59
- 0 => ['must be an integer'],
60
- 1 => ['must be an integer'],
61
- 2 => ['must be an integer']
62
- }
63
- )
64
- end
65
- end
66
-
67
- context 'with a predicate and a schema' do
68
- subject(:schema) do
69
- Dry::Validation.Schema do
70
- required(:foo) { str? | schema { required(:bar).filled } }
71
- end
72
- end
73
-
74
- it 'returns success for valid input' do
75
- expect(schema.(foo: 'bar')).to be_success
76
- expect(schema.(foo: { bar: 'baz' })).to be_success
77
- end
78
-
79
- it 'provides OR message for invalid input where both sides failed' do
80
- expect(schema.(foo: []).errors).to eql(foo: ['must be a string or must be a hash'])
81
- end
82
-
83
- it 'provides error messages for invalid input where right side rules failed' do
84
- expect(schema.(foo: { bar: '' }).errors).to eql(foo: { bar: ['must be filled'] })
85
- end
86
- end
87
- 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.Params(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
@@ -1,195 +0,0 @@
1
- RSpec.describe Dry::Validation::Schema::Params, 'explicit types' do
2
- context 'single type spec without rules' do
3
- subject(:schema) do
4
- Dry::Validation.Params do
5
- configure { config.type_specs = true }
6
- required(:age, :integer)
7
- end
8
- end
9
-
10
- it 'uses params coercion' do
11
- expect(schema.('age' => '19').to_h).to eql(age: 19)
12
- end
13
- end
14
-
15
- context 'integer' do
16
- subject(:schema) do
17
- Dry::Validation.Params do
18
- configure { config.type_specs = true }
19
- required(:age, :integer)
20
- end
21
- end
22
-
23
- it 'uses params coercion' do
24
- expect(schema.('age' => '19').to_h).to eql(age: 19)
25
- end
26
- end
27
-
28
- context 'single type spec with rules' do
29
- subject(:schema) do
30
- Dry::Validation.Params do
31
- configure { config.type_specs = true }
32
- required(:age, :integer).value(:int?, gt?: 18)
33
- end
34
- end
35
-
36
- it 'applies rules to coerced value' do
37
- expect(schema.(age: 19).messages).to be_empty
38
- expect(schema.(age: 18).messages).to eql(age: ['must be greater than 18'])
39
- end
40
- end
41
-
42
- context 'single type spec with an array' do
43
- subject(:schema) do
44
- Dry::Validation.Params do
45
- configure { config.type_specs = true }
46
- required(:nums, [:integer])
47
- end
48
- end
49
-
50
- it 'uses params coercion' do
51
- expect(schema.(nums: %w(1 2 3)).to_h).to eql(nums: [1, 2, 3])
52
- end
53
- end
54
-
55
- context 'sum type spec without rules' do
56
- subject(:schema) do
57
- Dry::Validation.Params do
58
- configure { config.type_specs = true }
59
- required(:age, [:nil, :integer])
60
- end
61
- end
62
-
63
- it 'uses params coercion' do
64
- expect(schema.('age' => '19').to_h).to eql(age: 19)
65
- expect(schema.('age' => '').to_h).to eql(age: nil)
66
- end
67
- end
68
-
69
- context 'sum type spec with rules' do
70
- subject(:schema) do
71
- Dry::Validation.Params do
72
- configure { config.type_specs = true }
73
- required(:age, [:nil, :integer]).maybe(:int?, gt?: 18)
74
- end
75
- end
76
-
77
- it 'applies rules to coerced value' do
78
- expect(schema.(age: nil).messages).to be_empty
79
- expect(schema.(age: 19).messages).to be_empty
80
- expect(schema.(age: 18).messages).to eql(age: ['must be greater than 18'])
81
- end
82
- end
83
-
84
- context 'using a type object' do
85
- subject(:schema) do
86
- Dry::Validation.Params do
87
- configure { config.type_specs = true }
88
- required(:age, Types::Params::Nil | Types::Params::Integer)
89
- end
90
- end
91
-
92
- it 'uses params coercion' do
93
- expect(schema.('age' => '').to_h).to eql(age: nil)
94
- expect(schema.('age' => '19').to_h).to eql(age: 19)
95
- end
96
- end
97
-
98
- context 'nested schema' do
99
- subject(:schema) do
100
- Dry::Validation.Params do
101
- configure { config.type_specs = true }
102
-
103
- required(:user).schema do
104
- required(:email, :string)
105
- required(:age, :integer)
106
-
107
- required(:address).schema do
108
- required(:street, :string)
109
- required(:city, :string)
110
- required(:zipcode, :string)
111
-
112
- required(:location).schema do
113
- required(:lat, :float)
114
- required(:lng, :float)
115
- end
116
- end
117
- end
118
- end
119
- end
120
-
121
- it 'uses params coercion for nested input' do
122
- input = {
123
- 'user' => {
124
- 'email' => 'jane@doe.org',
125
- 'age' => '21',
126
- 'address' => {
127
- 'street' => 'Street 1',
128
- 'city' => 'NYC',
129
- 'zipcode' => '1234',
130
- 'location' => { 'lat' => '1.23', 'lng' => '4.56' }
131
- }
132
- }
133
- }
134
-
135
- expect(schema.(input).to_h).to eql(
136
- user: {
137
- email: 'jane@doe.org',
138
- age: 21,
139
- address: {
140
- street: 'Street 1',
141
- city: 'NYC',
142
- zipcode: '1234',
143
- location: { lat: 1.23, lng: 4.56 }
144
- }
145
- }
146
- )
147
- end
148
- end
149
-
150
- context 'nested schema with arrays' do
151
- subject(:schema) do
152
- Dry::Validation.Params do
153
- configure { config.type_specs = true }
154
-
155
- required(:song).schema do
156
- required(:title, :string)
157
-
158
- required(:tags).each do
159
- schema do
160
- required(:name, :string)
161
- end
162
- end
163
- end
164
- end
165
- end
166
-
167
- it 'fails to coerce gracefuly' do
168
- result = schema.(song: nil)
169
-
170
- expect(result.messages).to eql(song: ['must be a hash'])
171
- expect(result.to_h).to eql(song: nil)
172
-
173
- result = schema.(song: { tags: nil })
174
-
175
- expect(result.messages).to eql(song: { tags: ['must be an array'] })
176
- expect(result.to_h).to eql(song: { tags: nil })
177
- end
178
-
179
- it 'uses params coercion for nested input' do
180
- input = {
181
- 'song' => {
182
- 'title' => 'dry-rb is awesome lala',
183
- 'tags' => [{ 'name' => 'red' }, { 'name' => 'blue' }]
184
- }
185
- }
186
-
187
- expect(schema.(input).to_h).to eql(
188
- song: {
189
- title: 'dry-rb is awesome lala',
190
- tags: [{ name: 'red' }, { name: 'blue' }]
191
- }
192
- )
193
- end
194
- end
195
- end