dry-validation 0.12.0 → 1.6.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 (204) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +696 -239
  3. data/LICENSE +1 -1
  4. data/README.md +15 -12
  5. data/config/errors.yml +3 -88
  6. data/dry-validation.gemspec +31 -17
  7. data/lib/dry-validation.rb +3 -1
  8. data/lib/dry/validation.rb +45 -28
  9. data/lib/dry/validation/config.rb +24 -0
  10. data/lib/dry/validation/constants.rb +43 -0
  11. data/lib/dry/validation/contract.rb +171 -0
  12. data/lib/dry/validation/contract/class_interface.rb +230 -0
  13. data/lib/dry/validation/evaluator.rb +224 -0
  14. data/lib/dry/validation/extensions/hints.rb +67 -0
  15. data/lib/dry/validation/extensions/monads.rb +24 -8
  16. data/lib/dry/validation/extensions/predicates_as_macros.rb +75 -0
  17. data/lib/dry/validation/failures.rb +70 -0
  18. data/lib/dry/validation/function.rb +44 -0
  19. data/lib/dry/validation/macro.rb +38 -0
  20. data/lib/dry/validation/macros.rb +104 -0
  21. data/lib/dry/validation/message.rb +80 -80
  22. data/lib/dry/validation/message_set.rb +80 -105
  23. data/lib/dry/validation/messages/resolver.rb +131 -0
  24. data/lib/dry/validation/result.rb +183 -41
  25. data/lib/dry/validation/rule.rb +135 -0
  26. data/lib/dry/validation/schema_ext.rb +19 -0
  27. data/lib/dry/validation/values.rb +104 -0
  28. data/lib/dry/validation/version.rb +3 -1
  29. metadata +47 -336
  30. data/.codeclimate.yml +0 -17
  31. data/.gitignore +0 -9
  32. data/.rspec +0 -3
  33. data/.travis.yml +0 -26
  34. data/CONTRIBUTING.md +0 -31
  35. data/Gemfile +0 -33
  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.rb +0 -7
  56. data/lib/dry/validation/extensions/struct.rb +0 -32
  57. data/lib/dry/validation/input_processor_compiler.rb +0 -135
  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 -192
  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 -112
  65. data/lib/dry/validation/messages/i18n.rb +0 -35
  66. data/lib/dry/validation/messages/namespaced.rb +0 -32
  67. data/lib/dry/validation/messages/yaml.rb +0 -54
  68. data/lib/dry/validation/predicate_registry.rb +0 -115
  69. data/lib/dry/validation/schema.rb +0 -126
  70. data/lib/dry/validation/schema/check.rb +0 -37
  71. data/lib/dry/validation/schema/class_interface.rb +0 -189
  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_compiler.rb +0 -81
  81. data/lib/dry/validation/type_specs.rb +0 -70
  82. data/spec/extensions/monads/result_spec.rb +0 -40
  83. data/spec/extensions/struct/schema_spec.rb +0 -32
  84. data/spec/fixtures/locales/en.yml +0 -6
  85. data/spec/fixtures/locales/pl.yml +0 -18
  86. data/spec/integration/custom_error_messages_spec.rb +0 -48
  87. data/spec/integration/custom_predicates_spec.rb +0 -228
  88. data/spec/integration/hints_spec.rb +0 -170
  89. data/spec/integration/injecting_rules_spec.rb +0 -30
  90. data/spec/integration/json/defining_base_schema_spec.rb +0 -41
  91. data/spec/integration/localized_error_messages_spec.rb +0 -72
  92. data/spec/integration/message_compiler_spec.rb +0 -405
  93. data/spec/integration/messages/i18n_spec.rb +0 -94
  94. data/spec/integration/optional_keys_spec.rb +0 -28
  95. data/spec/integration/params/predicates/array_spec.rb +0 -287
  96. data/spec/integration/params/predicates/empty_spec.rb +0 -263
  97. data/spec/integration/params/predicates/eql_spec.rb +0 -327
  98. data/spec/integration/params/predicates/even_spec.rb +0 -455
  99. data/spec/integration/params/predicates/excluded_from_spec.rb +0 -455
  100. data/spec/integration/params/predicates/excludes_spec.rb +0 -391
  101. data/spec/integration/params/predicates/false_spec.rb +0 -455
  102. data/spec/integration/params/predicates/filled_spec.rb +0 -467
  103. data/spec/integration/params/predicates/format_spec.rb +0 -454
  104. data/spec/integration/params/predicates/gt_spec.rb +0 -519
  105. data/spec/integration/params/predicates/gteq_spec.rb +0 -519
  106. data/spec/integration/params/predicates/included_in_spec.rb +0 -455
  107. data/spec/integration/params/predicates/includes_spec.rb +0 -391
  108. data/spec/integration/params/predicates/key_spec.rb +0 -67
  109. data/spec/integration/params/predicates/lt_spec.rb +0 -519
  110. data/spec/integration/params/predicates/lteq_spec.rb +0 -519
  111. data/spec/integration/params/predicates/max_size_spec.rb +0 -391
  112. data/spec/integration/params/predicates/min_size_spec.rb +0 -391
  113. data/spec/integration/params/predicates/none_spec.rb +0 -265
  114. data/spec/integration/params/predicates/not_eql_spec.rb +0 -327
  115. data/spec/integration/params/predicates/odd_spec.rb +0 -455
  116. data/spec/integration/params/predicates/size/fixed_spec.rb +0 -393
  117. data/spec/integration/params/predicates/size/range_spec.rb +0 -396
  118. data/spec/integration/params/predicates/true_spec.rb +0 -455
  119. data/spec/integration/params/predicates/type_spec.rb +0 -391
  120. data/spec/integration/result_spec.rb +0 -81
  121. data/spec/integration/schema/array_schema_spec.rb +0 -59
  122. data/spec/integration/schema/check_rules_spec.rb +0 -119
  123. data/spec/integration/schema/check_with_nested_el_spec.rb +0 -37
  124. data/spec/integration/schema/check_with_nth_el_spec.rb +0 -25
  125. data/spec/integration/schema/default_settings_spec.rb +0 -11
  126. data/spec/integration/schema/defining_base_schema_spec.rb +0 -41
  127. data/spec/integration/schema/dynamic_predicate_args_spec.rb +0 -43
  128. data/spec/integration/schema/each_with_set_spec.rb +0 -70
  129. data/spec/integration/schema/extending_dsl_spec.rb +0 -27
  130. data/spec/integration/schema/form_spec.rb +0 -236
  131. data/spec/integration/schema/hash_schema_spec.rb +0 -47
  132. data/spec/integration/schema/inheriting_schema_spec.rb +0 -31
  133. data/spec/integration/schema/input_processor_spec.rb +0 -46
  134. data/spec/integration/schema/json/explicit_types_spec.rb +0 -157
  135. data/spec/integration/schema/json_spec.rb +0 -163
  136. data/spec/integration/schema/macros/confirmation_spec.rb +0 -35
  137. data/spec/integration/schema/macros/each_spec.rb +0 -268
  138. data/spec/integration/schema/macros/filled_spec.rb +0 -87
  139. data/spec/integration/schema/macros/input_spec.rb +0 -139
  140. data/spec/integration/schema/macros/maybe_spec.rb +0 -99
  141. data/spec/integration/schema/macros/rule_spec.rb +0 -75
  142. data/spec/integration/schema/macros/value_spec.rb +0 -119
  143. data/spec/integration/schema/macros/when_spec.rb +0 -62
  144. data/spec/integration/schema/nested_schemas_spec.rb +0 -236
  145. data/spec/integration/schema/nested_values_spec.rb +0 -46
  146. data/spec/integration/schema/not_spec.rb +0 -34
  147. data/spec/integration/schema/numbers_spec.rb +0 -19
  148. data/spec/integration/schema/option_with_default_spec.rb +0 -64
  149. data/spec/integration/schema/or_spec.rb +0 -87
  150. data/spec/integration/schema/params/defining_base_schema_spec.rb +0 -41
  151. data/spec/integration/schema/params/explicit_types_spec.rb +0 -195
  152. data/spec/integration/schema/params_spec.rb +0 -234
  153. data/spec/integration/schema/predicate_verification_spec.rb +0 -9
  154. data/spec/integration/schema/predicates/array_spec.rb +0 -295
  155. data/spec/integration/schema/predicates/custom_spec.rb +0 -103
  156. data/spec/integration/schema/predicates/empty_spec.rb +0 -263
  157. data/spec/integration/schema/predicates/eql_spec.rb +0 -327
  158. data/spec/integration/schema/predicates/even_spec.rb +0 -455
  159. data/spec/integration/schema/predicates/excluded_from/array_spec.rb +0 -459
  160. data/spec/integration/schema/predicates/excluded_from/range_spec.rb +0 -459
  161. data/spec/integration/schema/predicates/excludes_spec.rb +0 -391
  162. data/spec/integration/schema/predicates/filled_spec.rb +0 -467
  163. data/spec/integration/schema/predicates/format_spec.rb +0 -455
  164. data/spec/integration/schema/predicates/gt_spec.rb +0 -519
  165. data/spec/integration/schema/predicates/gteq_spec.rb +0 -519
  166. data/spec/integration/schema/predicates/hash_spec.rb +0 -69
  167. data/spec/integration/schema/predicates/included_in/array_spec.rb +0 -459
  168. data/spec/integration/schema/predicates/included_in/range_spec.rb +0 -459
  169. data/spec/integration/schema/predicates/includes_spec.rb +0 -391
  170. data/spec/integration/schema/predicates/key_spec.rb +0 -88
  171. data/spec/integration/schema/predicates/lt_spec.rb +0 -520
  172. data/spec/integration/schema/predicates/lteq_spec.rb +0 -519
  173. data/spec/integration/schema/predicates/max_size_spec.rb +0 -391
  174. data/spec/integration/schema/predicates/min_size_spec.rb +0 -391
  175. data/spec/integration/schema/predicates/none_spec.rb +0 -265
  176. data/spec/integration/schema/predicates/not_eql_spec.rb +0 -391
  177. data/spec/integration/schema/predicates/odd_spec.rb +0 -455
  178. data/spec/integration/schema/predicates/size/fixed_spec.rb +0 -398
  179. data/spec/integration/schema/predicates/size/range_spec.rb +0 -395
  180. data/spec/integration/schema/predicates/type_spec.rb +0 -413
  181. data/spec/integration/schema/reusing_schema_spec.rb +0 -33
  182. data/spec/integration/schema/using_types_spec.rb +0 -135
  183. data/spec/integration/schema/validate_spec.rb +0 -120
  184. data/spec/integration/schema/xor_spec.rb +0 -35
  185. data/spec/integration/schema_builders_spec.rb +0 -17
  186. data/spec/integration/schema_spec.rb +0 -173
  187. data/spec/shared/message_compiler.rb +0 -11
  188. data/spec/shared/predicate_helper.rb +0 -15
  189. data/spec/shared/rule_compiler.rb +0 -8
  190. data/spec/spec_helper.rb +0 -58
  191. data/spec/support/define_struct.rb +0 -25
  192. data/spec/support/matchers.rb +0 -38
  193. data/spec/support/mutant.rb +0 -9
  194. data/spec/support/predicates_integration.rb +0 -7
  195. data/spec/unit/input_processor_compiler/json_spec.rb +0 -283
  196. data/spec/unit/input_processor_compiler/params_spec.rb +0 -328
  197. data/spec/unit/message_compiler/visit_failure_spec.rb +0 -38
  198. data/spec/unit/message_compiler/visit_spec.rb +0 -16
  199. data/spec/unit/message_compiler_spec.rb +0 -7
  200. data/spec/unit/predicate_registry_spec.rb +0 -34
  201. data/spec/unit/schema/key_spec.rb +0 -38
  202. data/spec/unit/schema/rule_spec.rb +0 -42
  203. data/spec/unit/schema/value_spec.rb +0 -131
  204. data/spec/unit/schema_spec.rb +0 -35
@@ -1,25 +0,0 @@
1
- module DefineStruct
2
- def from_hash(hash = {})
3
- values = members.map do |attr|
4
- val = hash[attr]
5
- val.is_a?(Hash) ? define_struct(*val.keys).from_hash(val) : val
6
- end
7
- new(*values)
8
- end
9
-
10
- def define_struct(*attrs)
11
- Struct.new(*attrs) do
12
- extend DefineStruct
13
- end
14
- end
15
- end
16
-
17
- def def_struct(*attrs)
18
- Struct.new(*attrs) do
19
- extend DefineStruct
20
- end
21
- end
22
-
23
- def struct_from_hash(hash)
24
- def_struct(*hash.keys).from_hash(hash)
25
- end
@@ -1,38 +0,0 @@
1
- require 'rspec/expectations'
2
-
3
- RSpec::Matchers.define :be_successful do
4
- match do |actual|
5
- actual.success? &&
6
- actual.messages.empty?
7
- end
8
-
9
- failure_message do |actual|
10
- "expected that #{actual.inspect} would be successful"
11
- end
12
-
13
- failure_message_when_negated do |actual|
14
- "expected that #{actual.inspect} would NOT be successful"
15
- end
16
- end
17
-
18
- RSpec::Matchers.define :be_failing do |messages|
19
- match do |actual|
20
- messages = case messages
21
- when Hash
22
- messages
23
- else
24
- Array(messages)
25
- end
26
-
27
- !actual.success? &&
28
- actual.messages.fetch(:foo) == messages
29
- end
30
-
31
- failure_message do |actual|
32
- "expected that #{actual.inspect} would be failing (#{messages.inspect})"
33
- end
34
-
35
- failure_message_when_negated do |actual|
36
- "expected that #{actual.inspect} would NOT be failing"
37
- end
38
- end
@@ -1,9 +0,0 @@
1
- module Mutant
2
- class Selector
3
- class Expression < self
4
- def call(_subject)
5
- integration.all_tests
6
- end
7
- end
8
- end
9
- end
@@ -1,7 +0,0 @@
1
- module PredicatesIntegration
2
- private
3
-
4
- def result
5
- schema.(input)
6
- end
7
- end
@@ -1,283 +0,0 @@
1
- RSpec.describe Dry::Validation::InputProcessorCompiler::JSON, '#call' do
2
- subject(:compiler) { Dry::Validation::InputProcessorCompiler::JSON.new }
3
-
4
- include_context 'predicate helper'
5
-
6
- it 'supports arbitrary types via type?(const) => "json.const"' do
7
- rule_ast = [
8
- [
9
- :and,
10
- [
11
- [:val, p(:key?, :age)],
12
- [:key, [:age, p(:type?, Integer)]]
13
- ]
14
- ]
15
- ]
16
-
17
- input_type = compiler.(rule_ast)
18
-
19
- expect(input_type['age' => 21]).to eql(age: 21)
20
- end
21
-
22
- it 'supports arbitrary types via type?(conts)' do
23
- rule_ast = [
24
- [
25
- :and,
26
- [
27
- [:val, p(:key?, :admin)],
28
- [:key, [:admin, p(:type?, 'Bool')]]
29
- ]
30
- ]
31
- ]
32
-
33
- input_type = compiler.(rule_ast)
34
-
35
- expect(input_type['admin' => false]).to eql(admin: false)
36
- end
37
-
38
- it 'supports str? => "string"' do
39
- rule_ast = [
40
- [
41
- :and,
42
- [
43
- [:val, p(:key?, :email)],
44
- [
45
- :and, [
46
- [:key, [:email, p(:str?, [])]],
47
- [:key, [:email, p(:filled?, [])]]
48
- ]
49
- ]
50
- ]
51
- ]
52
- ]
53
-
54
- input_type = compiler.(rule_ast)
55
-
56
- expect(input_type['email' => 'jane@doe.org']).to eql(email: 'jane@doe.org')
57
- end
58
-
59
- it 'supports int? => "int"' do
60
- rule_ast = [
61
- [
62
- :and,
63
- [
64
- [:val, p(:key?, :age)],
65
- [:key, [:age, p(:int?, [])]],
66
- ]
67
- ]
68
- ]
69
-
70
- input_type = compiler.(rule_ast)
71
-
72
- expect(input_type['age' => 21]).to eql(age: 21)
73
- end
74
-
75
- it 'supports bool? => "bool"' do
76
- rule_ast = [
77
- [
78
- :and,
79
- [
80
- [:val, p(:key?, :admin)],
81
- [:key, [:admin, p(:bool?, [])]],
82
- ]
83
- ]
84
- ]
85
-
86
- input_type = compiler.(rule_ast)
87
-
88
- expect(input_type['admin' => true]).to eql(admin: true)
89
- expect(input_type['admin' => false]).to eql(admin: false)
90
- end
91
-
92
- it 'supports none? => "int"' do
93
- rule_ast = [
94
- [
95
- :and,
96
- [
97
- [:val, p(:key?, :age)],
98
- [
99
- :or, [
100
- [:key, [:age, p(:none?, [])]],
101
- [:key, [:age, p(:int?, [])]],
102
- ]
103
- ]
104
- ]
105
- ]
106
- ]
107
-
108
- input_type = compiler.(rule_ast)
109
-
110
- expect(input_type['age' => '']).to eql(age: nil)
111
- expect(input_type['age' => 21]).to eql(age: 21)
112
- end
113
-
114
- it 'supports float? => "float"' do
115
- rule_ast = [
116
- [
117
- :and,
118
- [
119
- [:val, p(:key?, :lat)],
120
- [:key, [:lat, p(:float?, [])]],
121
- ]
122
- ]
123
- ]
124
-
125
- input_type = compiler.(rule_ast)
126
-
127
- expect(input_type['lat' => 21.12]).to eql(lat: 21.12)
128
- end
129
-
130
- it 'supports decimal? => "json.decimal"' do
131
- rule_ast = [
132
- [
133
- :and,
134
- [
135
- [:val, p(:key?, :lat)],
136
- [:key, [:lat, p(:decimal?, [])]],
137
- ]
138
- ]
139
- ]
140
-
141
- input_type = compiler.(rule_ast)
142
-
143
- expect(input_type['lat' => 21.12]).to eql(lat: 21.12.to_d)
144
- end
145
-
146
- it 'supports date? => "json.date"' do
147
- rule_ast = [
148
- [
149
- :and,
150
- [
151
- [:val, p(:key?, :bday)],
152
- [:key, [:bday, p(:date?, [])]],
153
- ]
154
- ]
155
- ]
156
-
157
- input_type = compiler.(rule_ast)
158
-
159
- expect(input_type['bday' => '2012-01-23']).to eql(bday: Date.new(2012, 1, 23))
160
- end
161
-
162
- it 'supports date_time? => "json.date_time"' do
163
- rule_ast = [
164
- [
165
- :and,
166
- [
167
- [:val, p(:key?, :bday)],
168
- [:key, [:bday, p(:date_time?, [])]],
169
- ]
170
- ]
171
- ]
172
-
173
- input_type = compiler.(rule_ast)
174
-
175
- expect(input_type['bday' => '2012-01-23 11:07']).to eql(bday: DateTime.new(2012, 1, 23, 11, 7))
176
- end
177
-
178
- it 'supports time? => "json.time"' do
179
- rule_ast = [
180
- [
181
- :and,
182
- [
183
- [:val, p(:key?, :bday)],
184
- [:key, [:bday, p(:time?, [])]],
185
- ]
186
- ]
187
- ]
188
-
189
- input_type = compiler.(rule_ast)
190
-
191
- expect(input_type['bday' => '2012-01-23 11:07']).to eql(bday: Time.new(2012, 1, 23, 11, 7))
192
- end
193
-
194
- it 'supports each rule' do
195
- rule_ast = [
196
- [
197
- :and, [
198
- [:val, p(:key?, :author)],
199
- [:set, [
200
- [:and, [
201
- [:val, p(:key?, :books)],
202
- [
203
- :each, [
204
- :set, [
205
- [
206
- :and, [
207
- [:val, p(:key?, :published)],
208
- [:key, [:published, p(:bool?, [])]]
209
- ]
210
- ]
211
- ]
212
- ]
213
- ]
214
- ]]
215
- ]]
216
- ]
217
- ]
218
- ]
219
-
220
- input_type = compiler.(rule_ast)
221
-
222
- expect(input_type['author' => { 'books' => [{ 'published' => true }] }]).to eql(
223
- author: { books: [published: true] }
224
- )
225
-
226
- expect(input_type['author' => { 'books' => [{ 'published' => false }] }]).to eql(
227
- author: { books: [published: false] }
228
- )
229
- end
230
-
231
- it 'supports array? with an each rule' do
232
- rule_ast = [
233
- [
234
- :and, [
235
- [:val, p(:key?, :ids)],
236
- [:and, [
237
- [:key, [:ids, p(:array?, [])]],
238
- [:each, [:val, p(:int?, [])]]
239
- ]]
240
- ]
241
- ]
242
- ]
243
-
244
- input_type = compiler.(rule_ast)
245
-
246
- expect(input_type.('ids' => 'oops')).to eql(ids: 'oops')
247
-
248
- expect(input_type.('ids' => [1, 2, 3])).to eql(ids: [1, 2, 3])
249
- end
250
-
251
- it 'supports hash? with a set rule' do
252
- rule_ast = [
253
- [
254
- :and, [
255
- [:val, p(:key?, :address)],
256
- [
257
- :and, [
258
- [:key, [:address, p(:hash?, [])]],
259
- [
260
- :set, [
261
- [
262
- :and, [
263
- [:val, p(:key?, :street)],
264
- [:key, [:street, p(:filled?, [])]]
265
- ]
266
- ]
267
- ]
268
- ]
269
- ]
270
- ]
271
- ]
272
- ]
273
- ]
274
-
275
- input_type = compiler.(rule_ast)
276
-
277
- expect(input_type.('address' => 'oops')).to eql(address: 'oops')
278
-
279
- expect(input_type.('address' => { 'street' => 'ok' })).to eql(
280
- address: { street: 'ok' }
281
- )
282
- end
283
- end
@@ -1,328 +0,0 @@
1
- RSpec.describe Dry::Validation::InputProcessorCompiler::Params, '#call' do
2
- subject(:compiler) { Dry::Validation::InputProcessorCompiler::Params.new }
3
-
4
- include_context 'predicate helper'
5
-
6
- let(:rule_ast) do
7
- [
8
- [
9
- :and, [
10
- p(:key?, :email),
11
- [
12
- :and, [
13
- [:key, [:email, p(:str?)]],
14
- [:key, [:email, p(:filled?)]]
15
- ]
16
- ]
17
- ]
18
- ],
19
- [
20
- :and, [
21
- p(:key?, :age),
22
- [
23
- :or, [
24
- [:key, [:age, p(:none?)]],
25
- [
26
- :and, [
27
- [:key, [:age, p(:int?)]],
28
- [:key, [:age, p(:filled?)]]
29
- ]
30
- ]
31
- ]
32
- ]
33
- ]
34
- ],
35
- [
36
- :and, [
37
- p(:key?, :address),
38
- [:key, [:address, p(:str?)]]
39
- ]
40
- ]
41
- ]
42
- end
43
-
44
- let(:output) do
45
- { 'email' => 'jane@doe.org', 'age' => '20', 'address' => 'City, Street 1/2' }
46
- end
47
-
48
- it 'builds an input dry-data type' do
49
- input_type = compiler.(rule_ast)
50
-
51
- result = input_type[output]
52
-
53
- expect(result).to eql(email: 'jane@doe.org', age: 20, address: 'City, Street 1/2')
54
- end
55
-
56
- it 'supports arbitrary types via type?(const) => "params.const"' do
57
- rule_ast = [
58
- [
59
- :and,
60
- [
61
- [:val, p(:key?, :age)],
62
- [:key, [:age, p(:type?, Integer)]]
63
- ]
64
- ]
65
- ]
66
-
67
- input_type = compiler.(rule_ast)
68
-
69
- expect(input_type['age' => '21']).to eql(age: 21)
70
- end
71
-
72
- it 'supports arbitrary types via type?(conts)' do
73
- rule_ast = [
74
- [
75
- :and,
76
- [
77
- [:val, p(:key?, :admin)],
78
- [:key, [:admin, p(:type?, 'Params::Bool')]]
79
- ]
80
- ]
81
- ]
82
-
83
- input_type = compiler.(rule_ast)
84
-
85
- expect(input_type['admin' => '0']).to eql(admin: false)
86
- end
87
-
88
- it 'supports int? => "params.integer"' do
89
- rule_ast = [
90
- [
91
- :and,
92
- [
93
- [:val, p(:key?, :age)],
94
- [:key, [:age, p(:int?)]],
95
- ]
96
- ]
97
- ]
98
-
99
- input_type = compiler.(rule_ast)
100
-
101
- expect(input_type['age' => '21']).to eql(age: 21)
102
- end
103
-
104
- it 'supports none? => "params.integer"' do
105
- rule_ast = [
106
- [
107
- :and,
108
- [
109
- [:val, p(:key?, :age)],
110
- [
111
- :or, [
112
- [:key, [:age, p(:none?)]],
113
- [:key, [:age, p(:int?)]],
114
- ]
115
- ]
116
- ]
117
- ]
118
- ]
119
-
120
- input_type = compiler.(rule_ast)
121
-
122
- expect(input_type['age' => '']).to eql(age: nil)
123
- expect(input_type['age' => '21']).to eql(age: 21)
124
- end
125
-
126
- it 'supports float? => "params.float"' do
127
- rule_ast = [
128
- [
129
- :and,
130
- [
131
- [:val, p(:key?, :lat)],
132
- [:key, [:lat, p(:float?)]],
133
- ]
134
- ]
135
- ]
136
-
137
- input_type = compiler.(rule_ast)
138
-
139
- expect(input_type['lat' => '21.12']).to eql(lat: 21.12)
140
- end
141
-
142
- it 'supports decimal? => "params.decimal"' do
143
- rule_ast = [
144
- [
145
- :and,
146
- [
147
- [:val, p(:key?, :lat)],
148
- [:key, [:lat, p(:decimal?, [])]],
149
- ]
150
- ]
151
- ]
152
-
153
- input_type = compiler.(rule_ast)
154
-
155
- expect(input_type['lat' => '21.12']).to eql(lat: 21.12.to_d)
156
- end
157
-
158
- it 'supports date? => "params.date"' do
159
- rule_ast = [
160
- [
161
- :and,
162
- [
163
- [:val, p(:key?, :bday)],
164
- [:key, [:bday, p(:date?, [])]],
165
- ]
166
- ]
167
- ]
168
-
169
- input_type = compiler.(rule_ast)
170
-
171
- expect(input_type['bday' => '2012-01-23']).to eql(bday: Date.new(2012, 1, 23))
172
- end
173
-
174
- it 'supports date_time? => "params.date_time"' do
175
- rule_ast = [
176
- [
177
- :and,
178
- [
179
- [:val, p(:key?, :bday)],
180
- [:key, [:bday, p(:date_time?, [])]],
181
- ]
182
- ]
183
- ]
184
-
185
- input_type = compiler.(rule_ast)
186
-
187
- expect(input_type['bday' => '2012-01-23 11:07']).to eql(bday: DateTime.new(2012, 1, 23, 11, 7))
188
- end
189
-
190
- it 'supports time? => "params.time"' do
191
- rule_ast = [
192
- [
193
- :and,
194
- [
195
- [:val, p(:key?, :bday)],
196
- [:key, [:bday, p(:time?, [])]],
197
- ]
198
- ]
199
- ]
200
-
201
- input_type = compiler.(rule_ast)
202
-
203
- expect(input_type['bday' => '2012-01-23 11:07']).to eql(bday: Time.new(2012, 1, 23, 11, 7))
204
- end
205
-
206
- it 'supports time? => "params.time"' do
207
- rule_ast = [
208
- [
209
- :and,
210
- [
211
- [:val, p(:key?, :bday)],
212
- [:key, [:bday, p(:time?, [])]],
213
- ]
214
- ]
215
- ]
216
-
217
- input_type = compiler.(rule_ast)
218
-
219
- expect(input_type['bday' => '2012-01-23 11:07']).to eql(bday: Time.new(2012, 1, 23, 11, 7))
220
- end
221
-
222
- it 'supports bool? => "params.bool"' do
223
- rule_ast = [
224
- [
225
- :and,
226
- [
227
- [:val, p(:key?, :admin)],
228
- [:key, [:admin, p(:bool?, [])]],
229
- ]
230
- ]
231
- ]
232
-
233
- input_type = compiler.(rule_ast)
234
-
235
- expect(input_type['admin' => 'true']).to eql(admin: true)
236
- expect(input_type['admin' => 'false']).to eql(admin: false)
237
- end
238
-
239
- it 'supports each rule' do
240
- rule_ast = [
241
- [
242
- :and, [
243
- [:val, p(:key?, :author)],
244
- [:set, [
245
- [:and, [
246
- [:val, p(:key?, :books)],
247
- [
248
- :each, [
249
- :set, [
250
- [
251
- :and, [
252
- [:val, p(:key?, :published)],
253
- [:key, [:published, p(:bool?, [])]]
254
- ]
255
- ]
256
- ]
257
- ]
258
- ]
259
- ]]
260
- ]]
261
- ]
262
- ]
263
- ]
264
-
265
- input_type = compiler.(rule_ast)
266
-
267
- expect(input_type['author' => { 'books' => [{ 'published' => 'true' }] }]).to eql(
268
- author: { books: [published: true] }
269
- )
270
-
271
- expect(input_type['author' => { 'books' => [{ 'published' => 'false' }] }]).to eql(
272
- author: { books: [published: false] }
273
- )
274
- end
275
-
276
- it 'supports array? with an each rule' do
277
- rule_ast = [
278
- [
279
- :and, [
280
- [:val, p(:key?, :ids)],
281
- [:and, [
282
- [:key, [:ids, p(:array?, [])]],
283
- [:each, [:val, p(:int?, [])]]
284
- ]]
285
- ]
286
- ]
287
- ]
288
-
289
- input_type = compiler.(rule_ast)
290
-
291
- expect(input_type.('ids' => 'oops')).to eql(ids: 'oops')
292
-
293
- expect(input_type.('ids' => %w(1 2 3))).to eql(ids: [1, 2, 3])
294
- end
295
-
296
- it 'supports hash? with a set rule' do
297
- rule_ast = [
298
- [
299
- :and, [
300
- [:val, p(:key?, :address)],
301
- [
302
- :and, [
303
- [:key, [:address, p(:hash?, [])]],
304
- [
305
- :set, [
306
- [
307
- :and, [
308
- [:val, p(:key?, :street)],
309
- [:key, [:street, p(:filled?, [])]]
310
- ]
311
- ]
312
- ]
313
- ]
314
- ]
315
- ]
316
- ]
317
- ]
318
- ]
319
-
320
- input_type = compiler.(rule_ast)
321
-
322
- expect(input_type.('address' => 'oops')).to eql(address: 'oops')
323
-
324
- expect(input_type.('address' => { 'street' => 'ok' })).to eql(
325
- address: { street: 'ok' }
326
- )
327
- end
328
- end