dry-validation 0.1.0 → 1.8.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +969 -1
- data/LICENSE +1 -1
- data/README.md +19 -286
- data/config/errors.yml +4 -35
- data/dry-validation.gemspec +38 -22
- data/lib/dry/validation/config.rb +24 -0
- data/lib/dry/validation/constants.rb +43 -0
- data/lib/dry/validation/contract/class_interface.rb +230 -0
- data/lib/dry/validation/contract.rb +173 -0
- data/lib/dry/validation/evaluator.rb +233 -0
- data/lib/dry/validation/extensions/hints.rb +67 -0
- data/lib/dry/validation/extensions/monads.rb +34 -0
- data/lib/dry/validation/extensions/predicates_as_macros.rb +75 -0
- data/lib/dry/validation/failures.rb +70 -0
- data/lib/dry/validation/function.rb +43 -0
- data/lib/dry/validation/macro.rb +38 -0
- data/lib/dry/validation/macros.rb +104 -0
- data/lib/dry/validation/message.rb +100 -0
- data/lib/dry/validation/message_set.rb +97 -0
- data/lib/dry/validation/messages/resolver.rb +129 -0
- data/lib/dry/validation/result.rb +206 -38
- data/lib/dry/validation/rule.rb +116 -106
- data/lib/dry/validation/schema_ext.rb +19 -0
- data/lib/dry/validation/values.rb +108 -0
- data/lib/dry/validation/version.rb +3 -1
- data/lib/dry/validation.rb +55 -7
- data/lib/dry-validation.rb +3 -1
- metadata +80 -106
- data/.gitignore +0 -8
- data/.rspec +0 -3
- data/.rubocop.yml +0 -16
- data/.rubocop_todo.yml +0 -7
- data/.travis.yml +0 -29
- data/Gemfile +0 -11
- data/Rakefile +0 -12
- data/examples/basic.rb +0 -21
- data/examples/nested.rb +0 -30
- data/examples/rule_ast.rb +0 -33
- data/lib/dry/validation/error.rb +0 -43
- data/lib/dry/validation/error_compiler.rb +0 -116
- data/lib/dry/validation/messages.rb +0 -71
- data/lib/dry/validation/predicate.rb +0 -39
- data/lib/dry/validation/predicate_set.rb +0 -22
- data/lib/dry/validation/predicates.rb +0 -88
- data/lib/dry/validation/rule_compiler.rb +0 -57
- data/lib/dry/validation/schema/definition.rb +0 -15
- data/lib/dry/validation/schema/key.rb +0 -39
- data/lib/dry/validation/schema/rule.rb +0 -28
- data/lib/dry/validation/schema/value.rb +0 -31
- data/lib/dry/validation/schema.rb +0 -74
- data/rakelib/rubocop.rake +0 -18
- data/spec/fixtures/errors.yml +0 -4
- data/spec/integration/custom_error_messages_spec.rb +0 -35
- data/spec/integration/custom_predicates_spec.rb +0 -57
- data/spec/integration/validation_spec.rb +0 -118
- data/spec/shared/predicates.rb +0 -31
- data/spec/spec_helper.rb +0 -18
- data/spec/unit/error_compiler_spec.rb +0 -165
- data/spec/unit/predicate_spec.rb +0 -37
- data/spec/unit/predicates/empty_spec.rb +0 -38
- data/spec/unit/predicates/eql_spec.rb +0 -21
- data/spec/unit/predicates/exclusion_spec.rb +0 -35
- data/spec/unit/predicates/filled_spec.rb +0 -38
- data/spec/unit/predicates/format_spec.rb +0 -21
- data/spec/unit/predicates/gt_spec.rb +0 -40
- data/spec/unit/predicates/gteq_spec.rb +0 -40
- data/spec/unit/predicates/inclusion_spec.rb +0 -35
- data/spec/unit/predicates/int_spec.rb +0 -34
- data/spec/unit/predicates/key_spec.rb +0 -29
- data/spec/unit/predicates/lt_spec.rb +0 -40
- data/spec/unit/predicates/lteq_spec.rb +0 -40
- data/spec/unit/predicates/max_size_spec.rb +0 -49
- data/spec/unit/predicates/min_size_spec.rb +0 -49
- data/spec/unit/predicates/nil_spec.rb +0 -28
- data/spec/unit/predicates/size_spec.rb +0 -49
- data/spec/unit/predicates/str_spec.rb +0 -32
- data/spec/unit/rule/each_spec.rb +0 -20
- data/spec/unit/rule/key_spec.rb +0 -27
- data/spec/unit/rule/set_spec.rb +0 -32
- data/spec/unit/rule/value_spec.rb +0 -42
- data/spec/unit/rule_compiler_spec.rb +0 -86
@@ -1,71 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'pathname'
|
3
|
-
|
4
|
-
module Dry
|
5
|
-
module Validation
|
6
|
-
class Messages
|
7
|
-
DEFAULT_PATH = Pathname(__dir__).join('../../../config/errors.yml').freeze
|
8
|
-
|
9
|
-
attr_reader :data
|
10
|
-
|
11
|
-
def self.default
|
12
|
-
load(DEFAULT_PATH)
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.load(path)
|
16
|
-
new(load_yaml(path))
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.load_yaml(path)
|
20
|
-
symbolize_keys(YAML.load_file(path))
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.symbolize_keys(hash)
|
24
|
-
hash.each_with_object({}) do |(k, v), r|
|
25
|
-
r[k.to_sym] = v.is_a?(Hash) ? symbolize_keys(v) : v
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class Namespaced
|
30
|
-
attr_reader :namespace, :fallback
|
31
|
-
|
32
|
-
def initialize(namespace, fallback)
|
33
|
-
@namespace = namespace
|
34
|
-
@fallback = fallback
|
35
|
-
end
|
36
|
-
|
37
|
-
def lookup(*args)
|
38
|
-
namespace.lookup(*args) { fallback.lookup(*args) }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def initialize(data)
|
43
|
-
@data = data
|
44
|
-
end
|
45
|
-
|
46
|
-
def merge(overrides)
|
47
|
-
if overrides.is_a?(Hash)
|
48
|
-
self.class.new(data.merge(overrides))
|
49
|
-
else
|
50
|
-
self.class.new(data.merge(Messages.load_yaml(overrides)))
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def namespaced(namespace)
|
55
|
-
Namespaced.new(Messages.new(data[namespace]), self)
|
56
|
-
end
|
57
|
-
|
58
|
-
def lookup(identifier, key, arg, &block)
|
59
|
-
message = data.fetch(:attributes, {}).fetch(key, {}).fetch(identifier) do
|
60
|
-
data.fetch(identifier, &block)
|
61
|
-
end
|
62
|
-
|
63
|
-
if message.is_a?(Hash)
|
64
|
-
message.fetch(arg.class.name.downcase.to_sym, message.fetch(:default))
|
65
|
-
else
|
66
|
-
message
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Validation
|
3
|
-
def self.Predicate(block)
|
4
|
-
case block
|
5
|
-
when Method then Predicate.new(block.name, &block)
|
6
|
-
else raise ArgumentError, 'predicate needs an :id'
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
class Predicate
|
11
|
-
include Dry::Equalizer(:id)
|
12
|
-
|
13
|
-
attr_reader :id, :args, :fn
|
14
|
-
|
15
|
-
def initialize(id, *args, &block)
|
16
|
-
@id = id
|
17
|
-
@fn = block
|
18
|
-
@args = args
|
19
|
-
end
|
20
|
-
|
21
|
-
def call(*args)
|
22
|
-
fn.(*args)
|
23
|
-
end
|
24
|
-
|
25
|
-
def negation
|
26
|
-
self.class.new(:"not_#{id}") { |input| !fn.(input) }
|
27
|
-
end
|
28
|
-
|
29
|
-
def curry(*args)
|
30
|
-
self.class.new(id, *args, &fn.curry.(*args))
|
31
|
-
end
|
32
|
-
|
33
|
-
def to_ary
|
34
|
-
[:predicate, [id, args]]
|
35
|
-
end
|
36
|
-
alias_method :to_a, :to_ary
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'dry/validation/predicate'
|
2
|
-
|
3
|
-
module Dry
|
4
|
-
module Validation
|
5
|
-
module PredicateSet
|
6
|
-
module Methods
|
7
|
-
def predicate(name, &block)
|
8
|
-
register(name) { Predicate.new(name, &block) }
|
9
|
-
end
|
10
|
-
|
11
|
-
def import(predicate_set)
|
12
|
-
merge(predicate_set)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.extended(other)
|
17
|
-
super
|
18
|
-
other.extend(Methods, Dry::Container::Mixin)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,88 +0,0 @@
|
|
1
|
-
require 'dry/validation/predicate_set'
|
2
|
-
|
3
|
-
module Dry
|
4
|
-
module Validation
|
5
|
-
module Predicates
|
6
|
-
extend PredicateSet
|
7
|
-
|
8
|
-
def self.included(other)
|
9
|
-
super
|
10
|
-
other.extend(PredicateSet)
|
11
|
-
other.import(self)
|
12
|
-
end
|
13
|
-
|
14
|
-
predicate(:nil?) do |input|
|
15
|
-
input.nil?
|
16
|
-
end
|
17
|
-
|
18
|
-
predicate(:key?) do |name, input|
|
19
|
-
input.key?(name)
|
20
|
-
end
|
21
|
-
|
22
|
-
predicate(:empty?) do |input|
|
23
|
-
case input
|
24
|
-
when String, Array, Hash then input.empty?
|
25
|
-
when nil then true
|
26
|
-
else
|
27
|
-
false
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
predicate(:filled?) do |input|
|
32
|
-
!self[:empty?].(input)
|
33
|
-
end
|
34
|
-
|
35
|
-
predicate(:int?) do |input|
|
36
|
-
input.is_a?(Fixnum)
|
37
|
-
end
|
38
|
-
|
39
|
-
predicate(:str?) do |input|
|
40
|
-
input.is_a?(String)
|
41
|
-
end
|
42
|
-
|
43
|
-
predicate(:lt?) do |num, input|
|
44
|
-
input < num
|
45
|
-
end
|
46
|
-
|
47
|
-
predicate(:gt?) do |num, input|
|
48
|
-
input > num
|
49
|
-
end
|
50
|
-
|
51
|
-
predicate(:lteq?) do |num, input|
|
52
|
-
!self[:gt?].(num, input)
|
53
|
-
end
|
54
|
-
|
55
|
-
predicate(:gteq?) do |num, input|
|
56
|
-
!self[:lt?].(num, input)
|
57
|
-
end
|
58
|
-
|
59
|
-
predicate(:size?) do |num, input|
|
60
|
-
input.size == num
|
61
|
-
end
|
62
|
-
|
63
|
-
predicate(:min_size?) do |num, input|
|
64
|
-
input.size >= num
|
65
|
-
end
|
66
|
-
|
67
|
-
predicate(:max_size?) do |num, input|
|
68
|
-
input.size <= num
|
69
|
-
end
|
70
|
-
|
71
|
-
predicate(:inclusion?) do |list, input|
|
72
|
-
list.include?(input)
|
73
|
-
end
|
74
|
-
|
75
|
-
predicate(:exclusion?) do |list, input|
|
76
|
-
!self[:inclusion?].(list, input)
|
77
|
-
end
|
78
|
-
|
79
|
-
predicate(:eql?) do |left, right|
|
80
|
-
left.eql?(right)
|
81
|
-
end
|
82
|
-
|
83
|
-
predicate(:format?) do |regex, input|
|
84
|
-
!regex.match(input).nil?
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'dry/validation/rule'
|
2
|
-
|
3
|
-
module Dry
|
4
|
-
module Validation
|
5
|
-
class RuleCompiler
|
6
|
-
attr_reader :predicates
|
7
|
-
|
8
|
-
def initialize(predicates)
|
9
|
-
@predicates = predicates
|
10
|
-
end
|
11
|
-
|
12
|
-
def call(ast)
|
13
|
-
ast.map { |node| visit(node) }
|
14
|
-
end
|
15
|
-
|
16
|
-
def visit(node)
|
17
|
-
name, nodes = node
|
18
|
-
send(:"visit_#{name}", nodes)
|
19
|
-
end
|
20
|
-
|
21
|
-
def visit_key(node)
|
22
|
-
name, predicate = node
|
23
|
-
Rule::Key.new(name, visit(predicate))
|
24
|
-
end
|
25
|
-
|
26
|
-
def visit_val(node)
|
27
|
-
name, predicate = node
|
28
|
-
Rule::Value.new(name, visit(predicate))
|
29
|
-
end
|
30
|
-
|
31
|
-
def visit_set(node)
|
32
|
-
name, rules = node
|
33
|
-
Rule::Set.new(name, call(rules))
|
34
|
-
end
|
35
|
-
|
36
|
-
def visit_each(node)
|
37
|
-
name, rule = node
|
38
|
-
Rule::Each.new(name, visit(rule))
|
39
|
-
end
|
40
|
-
|
41
|
-
def visit_predicate(node)
|
42
|
-
name, args = node
|
43
|
-
predicates[name].curry(*args)
|
44
|
-
end
|
45
|
-
|
46
|
-
def visit_and(node)
|
47
|
-
left, right = node
|
48
|
-
visit(left) & visit(right)
|
49
|
-
end
|
50
|
-
|
51
|
-
def visit_or(node)
|
52
|
-
left, right = node
|
53
|
-
visit(left) | visit(right)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Validation
|
3
|
-
class Schema
|
4
|
-
module Definition
|
5
|
-
def key(name, &block)
|
6
|
-
Key.new(name, rules).key?(&block)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
require 'dry/validation/schema/rule'
|
14
|
-
require 'dry/validation/schema/value'
|
15
|
-
require 'dry/validation/schema/key'
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'dry/validation/rule'
|
2
|
-
|
3
|
-
module Dry
|
4
|
-
module Validation
|
5
|
-
class Schema
|
6
|
-
class Key
|
7
|
-
attr_reader :name, :rules
|
8
|
-
|
9
|
-
def initialize(name, rules, &block)
|
10
|
-
@name = name
|
11
|
-
@rules = rules
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def method_missing(meth, *args, &block)
|
17
|
-
key_rule = [:key, [name, [:predicate, [meth, args]]]]
|
18
|
-
|
19
|
-
if block
|
20
|
-
val_rule = yield(Value.new(name))
|
21
|
-
|
22
|
-
rules <<
|
23
|
-
if val_rule.is_a?(Array)
|
24
|
-
Definition::Rule.new([:and, [key_rule, [:set, [name, val_rule.map(&:to_ary)]]]])
|
25
|
-
else
|
26
|
-
Definition::Rule.new([:and, [key_rule, val_rule.to_ary]])
|
27
|
-
end
|
28
|
-
else
|
29
|
-
Definition::Rule.new(key_rule)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def respond_to_missing?(meth, _include_private = false)
|
34
|
-
true
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Validation
|
3
|
-
class Schema
|
4
|
-
module Definition
|
5
|
-
class Rule
|
6
|
-
attr_reader :node
|
7
|
-
|
8
|
-
def initialize(node)
|
9
|
-
@node = node
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_ary
|
13
|
-
node
|
14
|
-
end
|
15
|
-
alias_method :to_a, :to_ary
|
16
|
-
|
17
|
-
def &(other)
|
18
|
-
self.class.new([:and, [node, other.to_ary]])
|
19
|
-
end
|
20
|
-
|
21
|
-
def |(other)
|
22
|
-
self.class.new([:or, [node, other.to_ary]])
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Validation
|
3
|
-
class Schema
|
4
|
-
class Value
|
5
|
-
include Schema::Definition
|
6
|
-
|
7
|
-
attr_reader :name, :rules
|
8
|
-
|
9
|
-
def initialize(name)
|
10
|
-
@name = name
|
11
|
-
@rules = []
|
12
|
-
end
|
13
|
-
|
14
|
-
def each(&block)
|
15
|
-
rule = yield(self).to_ary
|
16
|
-
Definition::Rule.new([:each, [name, rule]])
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def method_missing(meth, *args, &block)
|
22
|
-
Definition::Rule.new([:val, [name, [:predicate, [meth, args]]]])
|
23
|
-
end
|
24
|
-
|
25
|
-
def respond_to_missing?(meth, _include_private = false)
|
26
|
-
true
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'dry/validation/schema/definition'
|
2
|
-
require 'dry/validation/predicates'
|
3
|
-
require 'dry/validation/error'
|
4
|
-
require 'dry/validation/rule_compiler'
|
5
|
-
require 'dry/validation/messages'
|
6
|
-
require 'dry/validation/error_compiler'
|
7
|
-
|
8
|
-
module Dry
|
9
|
-
module Validation
|
10
|
-
class Schema
|
11
|
-
extend Dry::Configurable
|
12
|
-
extend Definition
|
13
|
-
|
14
|
-
setting :predicates, Predicates
|
15
|
-
setting :messages, Messages.default
|
16
|
-
setting :messages_file
|
17
|
-
setting :namespace
|
18
|
-
|
19
|
-
def self.predicates
|
20
|
-
config.predicates
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.error_compiler
|
24
|
-
ErrorCompiler.new(messages)
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.messages
|
28
|
-
default = config.messages
|
29
|
-
|
30
|
-
if config.messages_file && config.namespace
|
31
|
-
default.merge(config.messages_file).namespaced(config.namespace)
|
32
|
-
elsif config.messages_file
|
33
|
-
default.merge(config.messages_file)
|
34
|
-
elsif config.namespace
|
35
|
-
default.namespaced(config.namespace)
|
36
|
-
else
|
37
|
-
default
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.rules
|
42
|
-
@__rules__ ||= []
|
43
|
-
end
|
44
|
-
|
45
|
-
attr_reader :rules
|
46
|
-
|
47
|
-
attr_reader :error_compiler
|
48
|
-
|
49
|
-
def initialize(error_compiler = self.class.error_compiler)
|
50
|
-
@rules = RuleCompiler.new(self).(self.class.rules.map(&:to_ary))
|
51
|
-
@error_compiler = error_compiler
|
52
|
-
end
|
53
|
-
|
54
|
-
def call(input)
|
55
|
-
rules.each_with_object(Error::Set.new) do |rule, errors|
|
56
|
-
result = rule.(input)
|
57
|
-
errors << Error.new(result) if result.failure?
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def messages(input)
|
62
|
-
error_compiler.call(call(input).map(&:to_ary))
|
63
|
-
end
|
64
|
-
|
65
|
-
def [](name)
|
66
|
-
if methods.include?(name)
|
67
|
-
Predicate.new(name, &method(name))
|
68
|
-
else
|
69
|
-
self.class.predicates[name]
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
data/rakelib/rubocop.rake
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'rubocop/rake_task'
|
3
|
-
|
4
|
-
Rake::Task[:default].enhance [:rubocop]
|
5
|
-
|
6
|
-
RuboCop::RakeTask.new do |task|
|
7
|
-
task.options << '--display-cop-names'
|
8
|
-
end
|
9
|
-
|
10
|
-
namespace :rubocop do
|
11
|
-
desc 'Generate a configuration file acting as a TODO list.'
|
12
|
-
task :auto_gen_config do
|
13
|
-
exec 'bundle exec rubocop --auto-gen-config'
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
rescue LoadError
|
18
|
-
end
|
data/spec/fixtures/errors.yml
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
RSpec.describe Dry::Validation, 'with custom messages' do
|
2
|
-
subject(:validation) { schema.new }
|
3
|
-
|
4
|
-
describe 'defining schema' do
|
5
|
-
let(:schema) do
|
6
|
-
Class.new(Dry::Validation::Schema) do
|
7
|
-
configure do |config|
|
8
|
-
config.messages_file = SPEC_ROOT.join('fixtures/errors.yml')
|
9
|
-
config.namespace = :user
|
10
|
-
end
|
11
|
-
|
12
|
-
key(:email) { |email| email.filled? }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
let(:attrs) do
|
17
|
-
{
|
18
|
-
email: 'jane@doe.org',
|
19
|
-
age: 19,
|
20
|
-
address: { city: 'NYC', street: 'Street 1/2', country: { code: 'US', name: 'USA' } },
|
21
|
-
phone_numbers: [
|
22
|
-
'123456', '234567'
|
23
|
-
]
|
24
|
-
}.freeze
|
25
|
-
end
|
26
|
-
|
27
|
-
describe '#messages' do
|
28
|
-
it 'returns compiled error messages' do
|
29
|
-
expect(validation.messages(attrs.merge(email: ''))).to eql([
|
30
|
-
[:email, ["email can't be blank"]]
|
31
|
-
])
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
RSpec.describe Dry::Validation do
|
2
|
-
subject(:validation) { schema.new }
|
3
|
-
|
4
|
-
shared_context 'uses custom predicates' do
|
5
|
-
it 'uses provided custom predicates' do
|
6
|
-
expect(validation.(email: 'jane@doe')).to be_empty
|
7
|
-
|
8
|
-
expect(validation.(email: nil)).to match_array([
|
9
|
-
[:error, [:input, [:email, nil, [[:val, [:email, [:predicate, [:filled?, []]]]]]]]]
|
10
|
-
])
|
11
|
-
|
12
|
-
expect(validation.(email: 'jane')).to match_array([
|
13
|
-
[:error, [:input, [:email, 'jane', [[:val, [:email, [:predicate, [:email?, []]]]]]]]]
|
14
|
-
])
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
describe 'defining schema with custom predicates container' do
|
19
|
-
let(:schema) do
|
20
|
-
Class.new(Dry::Validation::Schema) do
|
21
|
-
configure do |config|
|
22
|
-
config.predicates = Test::Predicates
|
23
|
-
end
|
24
|
-
|
25
|
-
key(:email) { |value| value.filled? & value.email? }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
before do
|
30
|
-
module Test
|
31
|
-
module Predicates
|
32
|
-
include Dry::Validation::Predicates
|
33
|
-
|
34
|
-
predicate(:email?) do |input|
|
35
|
-
input.include?('@') # for the lols
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
include_context 'uses custom predicates'
|
42
|
-
end
|
43
|
-
|
44
|
-
describe 'defining schema with custom predicate methods' do
|
45
|
-
let(:schema) do
|
46
|
-
Class.new(Dry::Validation::Schema) do
|
47
|
-
key(:email) { |value| value.filled? & value.email? }
|
48
|
-
|
49
|
-
def email?(value)
|
50
|
-
value.include?('@')
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
include_context 'uses custom predicates'
|
56
|
-
end
|
57
|
-
end
|