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,35 +0,0 @@
1
- require 'i18n'
2
- require 'dry/validation/messages/abstract'
3
-
4
- module Dry
5
- module Validation
6
- class Messages::I18n < Messages::Abstract
7
- attr_reader :t
8
-
9
- ::I18n.load_path.concat(config.paths)
10
-
11
- def initialize
12
- super
13
- @t = I18n.method(:t)
14
- end
15
-
16
- def get(key, options = {})
17
- t.(key, options) if key
18
- end
19
-
20
- def key?(key, options)
21
- ::I18n.exists?(key, options.fetch(:locale, default_locale)) ||
22
- ::I18n.exists?(key, I18n.default_locale)
23
- end
24
-
25
- def merge(path)
26
- ::I18n.load_path << path
27
- self
28
- end
29
-
30
- def default_locale
31
- I18n.locale || I18n.default_locale || super
32
- end
33
- end
34
- end
35
- end
@@ -1,32 +0,0 @@
1
- module Dry
2
- module Validation
3
- module Messages
4
- class Namespaced < Messages::Abstract
5
- attr_reader :namespace, :messages, :root
6
-
7
- def initialize(namespace, messages)
8
- super()
9
- @namespace = namespace
10
- @messages = messages
11
- @root = messages.root
12
- end
13
-
14
- def key?(key, *args)
15
- messages.key?(key, *args)
16
- end
17
-
18
- def get(key, options = {})
19
- messages.get(key, options)
20
- end
21
-
22
- def lookup_paths(tokens)
23
- super(tokens.merge(root: "#{root}.rules.#{namespace}")) + super
24
- end
25
-
26
- def default_locale
27
- messages.default_locale
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,54 +0,0 @@
1
- require 'yaml'
2
- require 'pathname'
3
-
4
- require 'dry/equalizer'
5
- require 'dry/validation/messages/abstract'
6
-
7
- module Dry
8
- module Validation
9
- class Messages::YAML < Messages::Abstract
10
- include Dry::Equalizer(:data)
11
-
12
- attr_reader :data
13
-
14
- configure do |config|
15
- config.root = '%{locale}.errors'.freeze
16
- end
17
-
18
- def self.load(paths = config.paths)
19
- new(paths.map { |path| load_file(path) }.reduce(:merge))
20
- end
21
-
22
- def self.load_file(path)
23
- flat_hash(YAML.load_file(path))
24
- end
25
-
26
- def self.flat_hash(h, f = [], g = {})
27
- return g.update(f.join('.'.freeze) => h) unless h.is_a? Hash
28
- h.each { |k, r| flat_hash(r, f + [k], g) }
29
- g
30
- end
31
-
32
- def initialize(data)
33
- super()
34
- @data = data
35
- end
36
-
37
- def get(key, options = {})
38
- data[key % { locale: options.fetch(:locale, default_locale) }]
39
- end
40
-
41
- def key?(key, options = {})
42
- data.key?(key % { locale: options.fetch(:locale, default_locale) })
43
- end
44
-
45
- def merge(overrides)
46
- if overrides.is_a?(Hash)
47
- self.class.new(data.merge(self.class.flat_hash(overrides)))
48
- else
49
- self.class.new(data.merge(Messages::YAML.load_file(overrides)))
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,115 +0,0 @@
1
- require 'dry/logic/rule/predicate'
2
-
3
- module Dry
4
- module Validation
5
- class PredicateRegistry
6
- module PredicateDetector
7
- def method_added(name)
8
- super
9
-
10
- if name.to_s.end_with?('?')
11
- registry.update(name => instance_method(name))
12
- end
13
- end
14
- end
15
-
16
- attr_reader :predicates
17
- attr_reader :external
18
-
19
- class Bound < PredicateRegistry
20
- attr_reader :schema
21
-
22
- def initialize(*args)
23
- super(*args[0..1])
24
- @schema = args.last
25
- freeze
26
- end
27
- end
28
-
29
- class Unbound < PredicateRegistry
30
- def bind(schema)
31
- bound_predicates = predicates.each_with_object({}) do |(n, p), res|
32
- res[n] = p.bind(schema)
33
- end
34
- Bound.new(external, bound_predicates, schema)
35
- end
36
-
37
- def update(other)
38
- predicates.update(other)
39
- self
40
- end
41
- end
42
-
43
- def self.[](predicates)
44
- Unbound.new(predicates)
45
- end
46
-
47
- def initialize(external, predicates = {})
48
- @external = external
49
- @predicates = predicates
50
- end
51
-
52
- def new(klass)
53
- new_predicates = predicates
54
- .keys
55
- .each_with_object({}) { |key, res| res[key] = klass.instance_method(key) }
56
-
57
- self.class.new(external).update(new_predicates)
58
- end
59
-
60
- def [](name)
61
- predicates.fetch(name) do
62
- if external.public_methods.include?(name)
63
- external[name]
64
- else
65
- raise_unknown_predicate_error(name)
66
- end
67
- end
68
- end
69
-
70
- def key?(name)
71
- predicates.key?(name) || external.public_methods.include?(name)
72
- end
73
-
74
- def arg_list(name, *values)
75
- predicate = self[name]
76
-
77
- predicate
78
- .parameters
79
- .map(&:last)
80
- .zip(values + Array.new(predicate.arity - values.size, Undefined))
81
- end
82
-
83
- def ensure_valid_predicate(name, args_or_arity, schema = nil)
84
- return if schema && schema.instance_methods.include?(name)
85
-
86
- if name == :key?
87
- raise InvalidSchemaError, "#{name} is a reserved predicate name"
88
- end
89
-
90
- if key?(name)
91
- arity = self[name].arity
92
-
93
- case args_or_arity
94
- when Array
95
- raise_invalid_arity_error(name) if ![0, args_or_arity.size + 1].include?(arity)
96
- when Integer
97
- raise_invalid_arity_error(name) if args_or_arity != arity
98
- end
99
- else
100
- raise_unknown_predicate_error(name)
101
- end
102
- end
103
-
104
- private
105
-
106
- def raise_unknown_predicate_error(name)
107
- raise ArgumentError, "+#{name}+ is not a valid predicate name"
108
- end
109
-
110
- def raise_invalid_arity_error(name)
111
- raise ArgumentError, "#{name} predicate arity is invalid"
112
- end
113
- end
114
- end
115
- 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,37 +0,0 @@
1
- module Dry
2
- module Validation
3
- class Schema
4
- class Check < Value
5
- def class
6
- Check
7
- end
8
-
9
- def schema(other = nil, &block)
10
- schema = Schema.create_class(self, other, &block)
11
-
12
- if other
13
- schema.config.input_processor = other.class.config.input_processor
14
- end
15
-
16
- hash?.and(create_rule([:check, [[path], schema.to_ast]]))
17
- end
18
-
19
- private
20
-
21
- def method_missing(meth, *meth_args)
22
- vals, args = meth_args.partition { |arg| arg.class < DSL }
23
-
24
- keys = [path, vals.map(&:path)].reject(&:empty?)
25
-
26
- registry.ensure_valid_predicate(meth, args.size + keys.size, schema_class)
27
- predicate = predicate(meth, args)
28
-
29
- rule = create_rule([:check, [keys.reverse, predicate]], name)
30
-
31
- add_rule(rule)
32
- rule
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,189 +0,0 @@
1
- require 'dry/configurable'
2
- require 'dry/validation/messages'
3
- require 'dry/validation/type_specs'
4
-
5
- module Dry
6
- module Validation
7
- class Schema
8
- extend Dry::Configurable
9
- extend TypeSpecs
10
- extend PredicateRegistry::PredicateDetector
11
-
12
- NOOP_INPUT_PROCESSOR = -> input { input }
13
-
14
- setting :path
15
- setting :predicates, Logic::Predicates
16
- setting :registry
17
- setting :messages, :yaml
18
- setting :messages_file
19
- setting :namespace
20
- setting :rules, []
21
- setting :checks, []
22
- setting :options, {}
23
- setting :input, nil
24
- setting :input_rule, nil
25
- setting :dsl_extensions, nil
26
-
27
- DEFAULT_PROCESSOR_MAP = {
28
- sanitizer: InputProcessorCompiler::Sanitizer.new,
29
- json: InputProcessorCompiler::JSON.new,
30
- params: InputProcessorCompiler::Params.new,
31
- }
32
-
33
- setting :input_processor_map, DEFAULT_PROCESSOR_MAP
34
-
35
- setting :type_specs, false
36
-
37
- def self.new(rules = config.rules, **options)
38
- super(rules, default_options.merge(options))
39
- end
40
-
41
- def self.define(options = {}, &block)
42
- source = options.fetch(:schema_class)
43
- config = source.config
44
-
45
- dsl_ext = config.dsl_extensions
46
-
47
- options = options.merge(rules: options[:rules].dup) if options.key?(:rules)
48
- dsl = Schema::Value.new(options.merge(registry: source.registry))
49
- dsl_ext.__send__(:extend_object, dsl) if dsl_ext
50
- dsl.predicates(options[:predicates]) if options.key?(:predicates)
51
- dsl.instance_exec(&block) if block
52
-
53
- target = dsl.schema_class
54
-
55
- if config.input
56
- config.input_rule = -> predicates {
57
- Schema::Value.new(registry: predicates).infer_predicates(Array(target.config.input)).to_ast
58
- }
59
- end
60
-
61
- rules = target.config.rules + (options.fetch(:rules, []) + dsl.rules)
62
-
63
- target.configure do |cfg|
64
- cfg.rules = rules
65
- cfg.checks = cfg.checks + dsl.checks
66
- cfg.path = dsl.path
67
- cfg.type_map = target.build_type_map(dsl.type_map) if cfg.type_specs
68
- end
69
-
70
- target
71
- end
72
-
73
- def self.define!(options = {}, &block)
74
- define(schema_class: self, &block)
75
- end
76
-
77
- def self.predicates(predicate_set = nil)
78
- if predicate_set
79
- config.predicates = predicate_set
80
- set_registry!
81
- else
82
- config.predicates
83
- end
84
- end
85
-
86
- def self.option(name, default = nil)
87
- attr_reader(*name)
88
- options.update(name => default)
89
- end
90
-
91
- def self.create_class(target, other = nil, &block)
92
- klass =
93
- if other.is_a?(self)
94
- Class.new(other.class)
95
- elsif other.respond_to?(:schema) && other.schema.is_a?(self)
96
- Class.new(other.schema.class)
97
- else
98
- Validation.Schema(target.schema_class, parent: target, build: false, &block)
99
- end
100
-
101
- klass.config.path = target.path if other
102
- klass.config.input_processor = :noop
103
-
104
- klass
105
- end
106
-
107
- def self.clone
108
- klass = Class.new(self)
109
- klass.config.rules = []
110
- klass.config.registry = registry
111
- klass
112
- end
113
-
114
- def self.to_ast
115
- [:schema, self]
116
- end
117
-
118
- def self.registry
119
- config.registry
120
- end
121
-
122
- def self.type_map
123
- config.type_map
124
- end
125
-
126
- def self.rules
127
- config.rules
128
- end
129
-
130
- def self.options
131
- config.options
132
- end
133
-
134
- def self.messages
135
- default = default_messages
136
-
137
- if config.messages_file && config.namespace
138
- default.merge(config.messages_file).namespaced(config.namespace)
139
- elsif config.messages_file
140
- default.merge(config.messages_file)
141
- elsif config.namespace
142
- default.namespaced(config.namespace)
143
- else
144
- default
145
- end
146
- end
147
-
148
- def self.default_messages
149
- case config.messages
150
- when :yaml then Messages.default
151
- when :i18n then Messages::I18n.new
152
- else
153
- raise "+#{config.messages}+ is not a valid messages identifier"
154
- end
155
- end
156
-
157
- def self.message_compiler
158
- @message_compiler ||= MessageCompiler.new(messages)
159
- end
160
-
161
- def self.rule_ast
162
- @rule_ast ||= config.rules.map(&:to_ast)
163
- end
164
-
165
- def self.default_options
166
- @default_options ||= { predicate_registry: registry,
167
- message_compiler: message_compiler,
168
- input_processor: input_processor,
169
- checks: config.checks }
170
- end
171
-
172
- def self.inherited(klass)
173
- super
174
-
175
- klass.config.options = klass.config.options.dup
176
-
177
- if registry && self != Schema
178
- klass.config.registry = registry.new(self)
179
- else
180
- klass.set_registry!
181
- end
182
- end
183
-
184
- def self.set_registry!
185
- config.registry = PredicateRegistry[config.predicates]
186
- end
187
- end
188
- end
189
- end