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,22 +0,0 @@
1
- require 'dry/validation/schema'
2
- require 'dry/types/params'
3
-
4
- module Dry
5
- module Validation
6
- class Schema::Params < Schema
7
- def self.configure(klass = nil, &block)
8
- if klass
9
- klass.configure do |config|
10
- config.input_processor = :params
11
- config.hash_type = :symbolized
12
- end
13
- klass
14
- else
15
- super(&block)
16
- end
17
- end
18
-
19
- configure(self)
20
- end
21
- end
22
- end
@@ -1,202 +0,0 @@
1
- require 'dry/validation/deprecations'
2
-
3
- module Dry
4
- module Validation
5
- class Schema
6
- class Rule < BasicObject
7
- include ::Dry::Validation::Deprecations
8
-
9
- INVALID_PREDICATES = {
10
- value: [],
11
- maybe: [:empty?, :none?],
12
- filled: [:empty?, :filled?],
13
- }.freeze
14
-
15
- attr_reader :name, :node, :type, :target, :deps, :options
16
-
17
- def initialize(node, options = {})
18
- @node = node
19
- @type = options.fetch(:type, :and)
20
- @deps = options.fetch(:deps, [])
21
- @name = options.fetch(:name)
22
- @target = options.fetch(:target)
23
- @options = options
24
- end
25
-
26
- def inspect
27
- to_ast.inspect
28
- end
29
- alias_method :to_s, :inspect
30
-
31
- def schema(other = nil, &block)
32
- schema = Schema.create_class(target, other, &block)
33
-
34
- if schema.config.type_specs
35
- target.type_map[name] = schema.type_map
36
- end
37
-
38
- rule = __send__(type, key(:hash?).and(key(schema)))
39
- add_rule(rule)
40
- end
41
-
42
- def schema?
43
- target.schema?
44
- end
45
-
46
- def registry
47
- target.registry
48
- end
49
-
50
- def type_map
51
- target.type_map
52
- end
53
-
54
- def type_map?
55
- target.type_map?
56
- end
57
-
58
- def required(*predicates)
59
- warn 'required is deprecated - use filled instead.'
60
-
61
- filled(*predicates)
62
- end
63
-
64
- def filled(*predicates, &block)
65
- left = ([key(:filled?)] + infer_predicates(predicates, :filled)).reduce(:and)
66
-
67
- rule =
68
- if block
69
- left.and(Key[name, registry: registry].instance_eval(&block))
70
- else
71
- left
72
- end
73
-
74
- add_rule(__send__(type, rule))
75
- end
76
-
77
- def value(*predicates, &block)
78
- if predicates.empty? && !block
79
- ::Kernel.raise ::ArgumentError, "wrong number of arguments (given 0, expected at least 1)"
80
- end
81
-
82
- from_predicates = infer_predicates(predicates, :value).reduce(:and)
83
- from_block = block ? Key[name, registry: registry].instance_eval(&block) : nil
84
-
85
- rule = [from_predicates, from_block].compact.reduce(:and)
86
-
87
- add_rule(__send__(type, rule))
88
- end
89
-
90
- def maybe(*predicates, &block)
91
- left = key(:none?).not
92
-
93
- from_predicates = infer_predicates(predicates, :maybe).reduce(:and)
94
- from_block = block ? Key[name, registry: registry].instance_eval(&block) : nil
95
-
96
- right = [from_predicates, from_block].compact.reduce(:and) || key(:filled?)
97
-
98
- rule = left.then(right)
99
-
100
- add_rule(__send__(type, rule))
101
- end
102
-
103
- def each(*predicates, &block)
104
- rule = target.each(*predicates, &block)
105
- add_rule(__send__(type, new([target.type, [name, rule.to_ast]])))
106
- end
107
-
108
- def add_rule(rule)
109
- target.add_rule(rule)
110
- end
111
-
112
- def rules
113
- target.rules
114
- end
115
-
116
- def checks
117
- target.checks
118
- end
119
-
120
- def rule_ast
121
- rules.size > 0 ? target.rule_ast : [to_ast]
122
- end
123
-
124
- def to_ast
125
- rule_node = name ? [:rule, [name, node]] : node
126
-
127
- if deps.empty?
128
- rule_node
129
- else
130
- [:guard, [deps, rule_node]]
131
- end
132
- end
133
-
134
- def class
135
- Schema::Rule
136
- end
137
-
138
- def not
139
- new([:not, node])
140
- end
141
-
142
- def and(other)
143
- new([:and, [to_ast, other.to_ast]])
144
- end
145
- alias_method :&, :and
146
-
147
- def or(other)
148
- new([:or, [to_ast, other.to_ast]])
149
- end
150
- alias_method :|, :or
151
-
152
- def xor(other)
153
- new([:xor, [to_ast, other.to_ast]])
154
- end
155
- alias_method :^, :xor
156
-
157
- def then(other)
158
- new([:implication, [to_ast, other.to_ast]])
159
- end
160
- alias_method :>, :then
161
-
162
- def infer_predicates(predicates, macro = nil)
163
- predicates.flat_map(&::Kernel.method(:Array)).map do |predicate|
164
- name, *args = ::Kernel.Array(predicate)
165
-
166
- if macro && INVALID_PREDICATES[macro].include?(name)
167
- ::Kernel.raise InvalidSchemaError, "you can't use #{name} predicate with #{macro} macro"
168
- else
169
- key(name, args)
170
- end
171
- end
172
- end
173
-
174
- def with(new_options)
175
- self.class.new(node, options.merge(new_options))
176
- end
177
-
178
- def to_rule
179
- self
180
- end
181
-
182
- private
183
-
184
- def method_missing(meth, *args, &block)
185
- if target.predicate?(meth)
186
- target.__send__(meth, *args, &block)
187
- else
188
- super
189
- end
190
- end
191
-
192
- def key(predicate, args = [])
193
- new(target.node(predicate, *args))
194
- end
195
-
196
- def new(node)
197
- self.class.new(node, options)
198
- end
199
- end
200
- end
201
- end
202
- end
@@ -1,211 +0,0 @@
1
- require 'dry/validation/schema/dsl'
2
-
3
- module Dry
4
- module Validation
5
- class Schema
6
- class Value < DSL
7
- attr_reader :type, :schema_class, :type_map
8
-
9
- def initialize(options = {})
10
- super
11
- @type = options.fetch(:type, :key)
12
- @schema_class = options.fetch(:schema_class, ::Class.new(Schema))
13
- @options = options.merge(type: @type, schema_class: @schema_class)
14
- @type_map = parent && parent.root? ? parent.type_map : {}
15
- end
16
-
17
- def predicates(mod)
18
- @registry = options[:registry] = schema_class.predicates(mod)
19
- end
20
-
21
- def input(*predicates)
22
- schema_class.config.input = predicates
23
- self
24
- end
25
-
26
- def key(name, &block)
27
- warn 'key is deprecated - use required instead.'
28
-
29
- required(name, &block)
30
- end
31
-
32
- def required(name, type_spec = nil, &block)
33
- rule = define(name, Key, &block)
34
-
35
- if type_spec
36
- type_map[name] = type_spec
37
- end
38
-
39
- rule
40
- end
41
-
42
- def schema(other = nil, &block)
43
- @schema = Schema.create_class(self, other, &block)
44
- type_map.update(@schema.type_map)
45
- hash?.and(@schema)
46
- end
47
-
48
- def each(*predicates, &block)
49
- left = array?
50
-
51
- right =
52
- if predicates.size > 0
53
- create_rule([:each, infer_predicates(predicates, new).to_ast])
54
- else
55
- val = Value[
56
- name, registry: registry, schema_class: schema_class.clone
57
- ].instance_eval(&block)
58
-
59
- if val.type_map?
60
- if root?
61
- @type_map = [val.type_map]
62
- else
63
- type_map[name] = [val.type_map]
64
- end
65
- end
66
-
67
- create_rule([:each, val.to_ast])
68
- end
69
-
70
- rule = left.and(right)
71
-
72
- add_rule(rule) if root?
73
-
74
- rule
75
- end
76
-
77
- def when(*predicates, &block)
78
- left = infer_predicates(predicates, Check[path, type: type, registry: registry])
79
- right = Value.new(type: type, registry: registry).instance_eval(&block)
80
-
81
- add_check(left.then(right.to_rule))
82
-
83
- self
84
- end
85
-
86
- def rule(id = nil, **options, &block)
87
- if id
88
- val = Value[id, registry: registry, schema_class: schema_class]
89
- res = val.instance_exec(&block)
90
- else
91
- id, deps = options.to_a.first
92
- val = Value[id, registry: registry, schema_class: schema_class]
93
- res = val.instance_exec(*deps.map { |path| val.value(id, path: path) }, &block)
94
- end
95
-
96
- add_check(val.with(rules: [res.with(name: id, deps: deps || [])]))
97
- end
98
-
99
- def confirmation
100
- conf = :"#{name}_confirmation"
101
-
102
- parent.optional(conf).maybe
103
-
104
- rule(conf => [conf, name]) do |left, right|
105
- left.eql?(right)
106
- end
107
- end
108
-
109
- def value(path, opts = {})
110
- check(name || path, { registry: registry, rules: rules, path: path }.merge(opts))
111
- end
112
-
113
- def check(name, options = {})
114
- Check[name, options.merge(type: type)]
115
- end
116
-
117
- def validate(**opts, &block)
118
- id, *deps = opts.to_a.flatten
119
- name = deps.size > 1 ? id : deps.first
120
- rule = create_rule([:check, [deps, [:custom, [id, block]]]], name).with(deps: deps)
121
- add_check(rule)
122
- end
123
-
124
- def configure(&block)
125
- schema_class.class_eval(&block)
126
- @registry = schema_class.registry
127
- self
128
- end
129
-
130
- def root?
131
- name.nil?
132
- end
133
-
134
- def type_map?
135
- ! type_map.empty?
136
- end
137
-
138
- def schema?
139
- ! @schema.nil?
140
- end
141
-
142
- def class
143
- Value
144
- end
145
-
146
- def new
147
- self.class.new(registry: registry, schema_class: schema_class.clone)
148
- end
149
-
150
- def key?(name)
151
- create_rule(predicate(:key?, name))
152
- end
153
-
154
- def node(input, *args)
155
- if input.is_a?(::Symbol)
156
- registry.ensure_valid_predicate(input, args, schema_class)
157
- [type, [name, predicate(input, args)]]
158
- elsif input.respond_to?(:rule)
159
- [type, [name, [:type, input]]]
160
- elsif input.is_a?(Schema)
161
- [type, [name, schema(input).to_ast]]
162
- else
163
- [type, [name, input.to_ast]]
164
- end
165
- end
166
-
167
- def dyn_arg?(name)
168
- !name.to_s.end_with?('?') && schema_class.instance_methods.include?(name)
169
- end
170
-
171
- def respond_to?(name)
172
- self.class.public_methods.include?(name)
173
- end
174
-
175
- def infer_predicates(predicates, infer_on = self)
176
- predicates.flat_map(&::Kernel.method(:Array)).map { |predicate|
177
- name, *args = ::Kernel.Array(predicate)
178
-
179
- if name.is_a?(Schema)
180
- infer_on.schema(name)
181
- elsif name.respond_to?(:rule)
182
- create_rule(name.rule.to_ast)
183
- else
184
- infer_on.__send__(name, *args)
185
- end
186
- }.reduce(:and)
187
- end
188
-
189
- private
190
-
191
- def method_missing(meth, *args, &block)
192
- return schema_class.instance_method(meth) if dyn_arg?(meth)
193
-
194
- val_rule = create_rule(predicate(meth, args))
195
-
196
- if block
197
- val = new.instance_eval(&block)
198
-
199
- type_map.update(val.type_map) if val.type_map?
200
-
201
- new_rule = create_rule([:and, [val_rule.to_ast, val.to_ast]])
202
-
203
- add_rule(new_rule)
204
- else
205
- val_rule
206
- end
207
- end
208
- end
209
- end
210
- end
211
- end
@@ -1,126 +0,0 @@
1
- require 'dry/logic/predicates'
2
- require 'dry/types/constraints'
3
-
4
- require 'dry/validation/predicate_registry'
5
- require 'dry/validation/schema_compiler'
6
- require 'dry/validation/schema/key'
7
- require 'dry/validation/schema/value'
8
- require 'dry/validation/schema/check'
9
-
10
- require 'dry/validation/result'
11
- require 'dry/validation/messages'
12
- require 'dry/validation/message_compiler'
13
-
14
- require 'dry/validation/schema/deprecated'
15
- require 'dry/validation/schema/class_interface'
16
- require 'dry/validation/executor'
17
-
18
- module Dry
19
- module Validation
20
- class Schema
21
- attr_reader :config
22
-
23
- attr_reader :input_rule
24
-
25
- attr_reader :rules
26
-
27
- attr_reader :checks
28
-
29
- attr_reader :predicates
30
-
31
- attr_reader :input_processor
32
-
33
- attr_reader :rule_compiler
34
-
35
- attr_reader :message_compiler
36
-
37
- attr_reader :options
38
-
39
- attr_reader :type_map
40
-
41
- attr_reader :executor
42
-
43
- def initialize(rules, options)
44
- @type_map = self.class.type_map
45
- @config = self.class.config
46
- @predicates = options.fetch(:predicate_registry).bind(self)
47
- @rule_compiler = SchemaCompiler.new(predicates, options)
48
- @message_compiler = options.fetch(:message_compiler)
49
- @input_processor = options[:input_processor]
50
-
51
- @input_rule = rule_compiler.visit(config.input_rule.(predicates)) if config.input_rule
52
-
53
- initialize_options(options)
54
- initialize_rules(rules)
55
- initialize_checks(options.fetch(:checks, []))
56
-
57
- @executor = Executor.new do |steps|
58
- steps << ProcessInput.new(input_processor) if input_processor
59
- steps << ApplyInputRule.new(input_rule) if input_rule
60
- steps << ApplyRules.new(@rules)
61
- steps << ApplyChecks.new(@checks) if @checks.any?
62
- end
63
-
64
- freeze
65
- end
66
-
67
- def with(new_options)
68
- self.class.new(self.class.rules, options.merge(new_options))
69
- end
70
-
71
- def call(input)
72
- output, result = executor.(input)
73
- Result.new(output, result, message_compiler, config.path)
74
- end
75
-
76
- def curry(*curry_args)
77
- -> *args { call(*(curry_args + args)) }
78
- end
79
-
80
- def to_proc
81
- -> input { call(input) }
82
- end
83
-
84
- def arity
85
- 1
86
- end
87
-
88
- def ast(*)
89
- self.class.to_ast
90
- end
91
- alias_method :to_ast, :ast
92
-
93
- private
94
-
95
- def initialize_options(options)
96
- @options = options
97
-
98
- self.class.options.each do |name, default|
99
- value = options.fetch(name) do
100
- case default
101
- when Proc then default.()
102
- else default end
103
- end
104
-
105
- instance_variable_set("@#{name}", value)
106
- end
107
- end
108
-
109
- def initialize_rules(rules)
110
- @rules = rules.each_with_object({}) do |rule, result|
111
- result[rule.name] = rule_compiler.visit(rule.to_ast)
112
- end
113
- end
114
-
115
- def initialize_checks(checks)
116
- @checks = checks.each_with_object({}) do |check, result|
117
- if result.key?(check.name)
118
- result[check.name] << rule_compiler.visit(check.to_ast)
119
- else
120
- result[check.name] = [rule_compiler.visit(check.to_ast)]
121
- end
122
- end
123
- end
124
- end
125
- end
126
- end
@@ -1,81 +0,0 @@
1
- require 'dry/logic/rule_compiler'
2
-
3
- module Dry
4
- module Validation
5
- class Guard
6
- attr_reader :rule, :deps
7
-
8
- def initialize(rule, deps)
9
- @rule = rule
10
- @deps = deps
11
- end
12
-
13
- def call(input, results)
14
- rule.(input) if deps_valid?(results)
15
- end
16
-
17
- def with(options)
18
- self.class.new(rule.with(options), deps)
19
- end
20
-
21
- private
22
-
23
- def deps_valid?(results)
24
- deps.all? do |path|
25
- result = nil
26
- Array(path).each do |name|
27
- curr = results[name]
28
- if curr
29
- result = curr.is_a?(Array) ? curr.first.success? : curr.success?
30
- end
31
- end
32
- result
33
- end
34
- end
35
- end
36
-
37
- class SchemaCompiler < Logic::RuleCompiler
38
- attr_reader :schema, :options
39
-
40
- def initialize(*args, options)
41
- super(*args)
42
- @options = options
43
- @schema = predicates.schema
44
- end
45
-
46
- def visit_rule(node)
47
- id, other = node
48
- visit(other).with(id: id)
49
- end
50
-
51
- def visit_predicate(node)
52
- super.eval_args(schema)
53
- end
54
-
55
- def visit_custom(node)
56
- id, predicate = node
57
- Logic::Rule.new(predicate).with(id: id).bind(schema)
58
- end
59
-
60
- def visit_schema(klass)
61
- opt_keys = klass.config.options.keys
62
- opt_vals = options.values_at(*opt_keys).compact
63
-
64
- if opt_vals.empty?
65
- klass.new
66
- else
67
- klass.new(klass.config.rules, Hash[opt_keys.zip(opt_vals)])
68
- end
69
- end
70
-
71
- def visit_guard(node)
72
- deps, other = node
73
- Guard.new(visit(other), deps)
74
- end
75
-
76
- def visit_type(type)
77
- type.rule
78
- end
79
- end
80
- end
81
- end
@@ -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