dry-validation 0.2.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +26 -2
- data/Gemfile +4 -0
- data/README.md +131 -42
- data/config/errors.yml +36 -27
- data/examples/basic.rb +2 -4
- data/examples/each.rb +2 -2
- data/examples/form.rb +1 -2
- data/examples/nested.rb +2 -4
- data/examples/rule_ast.rb +0 -8
- data/lib/dry/validation.rb +0 -5
- data/lib/dry/validation/error.rb +2 -6
- data/lib/dry/validation/error_compiler.rb +19 -5
- data/lib/dry/validation/input_type_compiler.rb +2 -1
- data/lib/dry/validation/messages.rb +7 -58
- data/lib/dry/validation/messages/abstract.rb +75 -0
- data/lib/dry/validation/messages/i18n.rb +24 -0
- data/lib/dry/validation/messages/namespaced.rb +27 -0
- data/lib/dry/validation/messages/yaml.rb +50 -0
- data/lib/dry/validation/result.rb +19 -49
- data/lib/dry/validation/rule.rb +2 -2
- data/lib/dry/validation/rule/group.rb +21 -0
- data/lib/dry/validation/rule/result.rb +73 -0
- data/lib/dry/validation/rule_compiler.rb +5 -0
- data/lib/dry/validation/schema.rb +33 -14
- data/lib/dry/validation/schema/definition.rb +16 -0
- data/lib/dry/validation/schema/result.rb +21 -3
- data/lib/dry/validation/schema/rule.rb +1 -1
- data/lib/dry/validation/schema/value.rb +2 -1
- data/lib/dry/validation/version.rb +1 -1
- data/spec/fixtures/locales/en.yml +5 -0
- data/spec/fixtures/locales/pl.yml +14 -0
- data/spec/integration/custom_error_messages_spec.rb +4 -16
- data/spec/{unit → integration}/error_compiler_spec.rb +81 -39
- data/spec/integration/localized_error_messages_spec.rb +52 -0
- data/spec/integration/messages/i18n_spec.rb +71 -0
- data/spec/integration/rule_groups_spec.rb +35 -0
- data/spec/integration/schema_form_spec.rb +9 -9
- data/spec/integration/schema_spec.rb +2 -2
- data/spec/shared/predicates.rb +2 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/rule/group_spec.rb +12 -0
- data/spec/unit/schema_spec.rb +35 -0
- metadata +24 -6
- data/spec/fixtures/errors.yml +0 -4
data/lib/dry/validation/rule.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'dry/validation/result'
|
2
|
-
|
3
1
|
module Dry
|
4
2
|
module Validation
|
5
3
|
class Rule
|
@@ -44,3 +42,5 @@ require 'dry/validation/rule/value'
|
|
44
42
|
require 'dry/validation/rule/each'
|
45
43
|
require 'dry/validation/rule/set'
|
46
44
|
require 'dry/validation/rule/composite'
|
45
|
+
require 'dry/validation/rule/group'
|
46
|
+
require 'dry/validation/rule/result'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Dry
|
2
|
+
module Validation
|
3
|
+
class Rule::Group < Rule
|
4
|
+
attr_reader :rules
|
5
|
+
|
6
|
+
def initialize(identifier, predicate)
|
7
|
+
name, rules = identifier.to_a.first
|
8
|
+
@rules = rules
|
9
|
+
super(name, predicate)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(*input)
|
13
|
+
Validation.Result(input, predicate.(*input), self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
:group
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Dry
|
2
|
+
module Validation
|
3
|
+
def self.Result(input, value, rule)
|
4
|
+
case value
|
5
|
+
when Array then Rule::Result::Set.new(input, value, rule)
|
6
|
+
else Rule::Result::Value.new(input, value, rule)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Rule::Result
|
11
|
+
include Dry::Equalizer(:success?, :input, :rule)
|
12
|
+
|
13
|
+
attr_reader :input, :value, :rule, :name
|
14
|
+
|
15
|
+
class Rule::Result::Set < Rule::Result
|
16
|
+
def success?
|
17
|
+
value.all?(&:success?)
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_ary
|
21
|
+
indices = value.map { |v| v.failure? ? value.index(v) : nil }.compact
|
22
|
+
[:input, [rule.name, input, value.values_at(*indices).map(&:to_ary)]]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Rule::Result::Value < Rule::Result
|
27
|
+
def to_ary
|
28
|
+
[:input, [rule.name, input, [rule.to_ary]]]
|
29
|
+
end
|
30
|
+
alias_method :to_a, :to_ary
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(input, value, rule)
|
34
|
+
@input = input
|
35
|
+
@value = value
|
36
|
+
@rule = rule
|
37
|
+
@name = rule.name
|
38
|
+
end
|
39
|
+
|
40
|
+
def >(other)
|
41
|
+
if success?
|
42
|
+
other.(input)
|
43
|
+
else
|
44
|
+
Validation.Result(input, true, rule)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def and(other)
|
49
|
+
if success?
|
50
|
+
other.(input)
|
51
|
+
else
|
52
|
+
self
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def or(other)
|
57
|
+
if success?
|
58
|
+
self
|
59
|
+
else
|
60
|
+
other.(input)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def success?
|
65
|
+
@value
|
66
|
+
end
|
67
|
+
|
68
|
+
def failure?
|
69
|
+
! success?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -4,6 +4,7 @@ require 'dry/validation/error'
|
|
4
4
|
require 'dry/validation/rule_compiler'
|
5
5
|
require 'dry/validation/messages'
|
6
6
|
require 'dry/validation/error_compiler'
|
7
|
+
require 'dry/validation/result'
|
7
8
|
require 'dry/validation/schema/result'
|
8
9
|
|
9
10
|
module Dry
|
@@ -13,7 +14,7 @@ module Dry
|
|
13
14
|
extend Definition
|
14
15
|
|
15
16
|
setting :predicates, Predicates
|
16
|
-
setting :messages,
|
17
|
+
setting :messages, :yaml
|
17
18
|
setting :messages_file
|
18
19
|
setting :namespace
|
19
20
|
|
@@ -26,7 +27,13 @@ module Dry
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def self.messages
|
29
|
-
default =
|
30
|
+
default =
|
31
|
+
case config.messages
|
32
|
+
when :yaml then Messages.default
|
33
|
+
when :i18n then Messages::I18n.new
|
34
|
+
else
|
35
|
+
raise RuntimeError, "+#{config.messages}+ is not a valid messages identifier"
|
36
|
+
end
|
30
37
|
|
31
38
|
if config.messages_file && config.namespace
|
32
39
|
default.merge(config.messages_file).namespaced(config.namespace)
|
@@ -43,36 +50,48 @@ module Dry
|
|
43
50
|
@__rules__ ||= []
|
44
51
|
end
|
45
52
|
|
46
|
-
|
53
|
+
def self.groups
|
54
|
+
@__groups__ ||= []
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :rules, :groups
|
47
58
|
|
48
59
|
attr_reader :error_compiler
|
49
60
|
|
50
61
|
def initialize(error_compiler = self.class.error_compiler)
|
51
|
-
|
62
|
+
compiler = RuleCompiler.new(self)
|
63
|
+
@rules = compiler.(self.class.rules.map(&:to_ary))
|
64
|
+
@groups = compiler.(self.class.groups.map(&:to_ary))
|
52
65
|
@error_compiler = error_compiler
|
53
66
|
end
|
54
67
|
|
55
68
|
def call(input)
|
56
|
-
|
57
|
-
|
58
|
-
|
69
|
+
result = Validation::Result.new(rules.map { |rule| rule.(input) })
|
70
|
+
|
71
|
+
groups.each do |group|
|
72
|
+
result.with_values(group.rules) do |values|
|
73
|
+
result << group.(*values)
|
74
|
+
end
|
59
75
|
end
|
60
76
|
|
61
|
-
|
62
|
-
end
|
77
|
+
errors = Error::Set.new(result.failures.map { |failure| Error.new(failure) })
|
63
78
|
|
64
|
-
|
65
|
-
result = call(input)
|
66
|
-
Result.new(result.params, error_compiler.(result.to_ary))
|
79
|
+
Schema::Result.new(input, result, errors, error_compiler)
|
67
80
|
end
|
68
81
|
|
69
82
|
def [](name)
|
70
|
-
if
|
83
|
+
if predicates.key?(name)
|
84
|
+
predicates[name]
|
85
|
+
elsif respond_to?(name)
|
71
86
|
Predicate.new(name, &method(name))
|
72
87
|
else
|
73
|
-
|
88
|
+
raise ArgumentError, "+#{name}+ is not a valid predicate name"
|
74
89
|
end
|
75
90
|
end
|
91
|
+
|
92
|
+
def predicates
|
93
|
+
self.class.predicates
|
94
|
+
end
|
76
95
|
end
|
77
96
|
end
|
78
97
|
end
|
@@ -9,6 +9,22 @@ module Dry
|
|
9
9
|
def optional(name, &block)
|
10
10
|
Key.new(name, rules).optional(&block)
|
11
11
|
end
|
12
|
+
|
13
|
+
def rule(name, **options)
|
14
|
+
predicate, rules = options.to_a.first
|
15
|
+
identifier = { name => rules }
|
16
|
+
|
17
|
+
groups << [:group, [identifier, [:predicate, predicate]]]
|
18
|
+
end
|
19
|
+
|
20
|
+
def confirmation(name)
|
21
|
+
identifier = :"#{name}_confirmation"
|
22
|
+
|
23
|
+
key(name, &:filled?)
|
24
|
+
key(identifier, &:filled?)
|
25
|
+
|
26
|
+
rule(identifier, eql?: [name, identifier])
|
27
|
+
end
|
12
28
|
end
|
13
29
|
end
|
14
30
|
end
|
@@ -1,20 +1,26 @@
|
|
1
1
|
module Dry
|
2
2
|
module Validation
|
3
3
|
class Schema::Result
|
4
|
-
include Dry::Equalizer(:params, :
|
4
|
+
include Dry::Equalizer(:params, :messages)
|
5
5
|
include Enumerable
|
6
6
|
|
7
7
|
attr_reader :params
|
8
8
|
|
9
|
+
attr_reader :result
|
10
|
+
|
9
11
|
attr_reader :errors
|
10
12
|
|
11
|
-
|
13
|
+
attr_reader :error_compiler
|
14
|
+
|
15
|
+
def initialize(params, result, errors, error_compiler)
|
12
16
|
@params = params
|
17
|
+
@result = result
|
13
18
|
@errors = errors
|
19
|
+
@error_compiler = error_compiler
|
14
20
|
end
|
15
21
|
|
16
22
|
def each(&block)
|
17
|
-
|
23
|
+
failures.each(&block)
|
18
24
|
end
|
19
25
|
|
20
26
|
def empty?
|
@@ -24,6 +30,18 @@ module Dry
|
|
24
30
|
def to_ary
|
25
31
|
errors.map(&:to_ary)
|
26
32
|
end
|
33
|
+
|
34
|
+
def messages(options = {})
|
35
|
+
@messages ||= error_compiler.with(options).(errors.map(&:to_ary))
|
36
|
+
end
|
37
|
+
|
38
|
+
def successes
|
39
|
+
result.successes
|
40
|
+
end
|
41
|
+
|
42
|
+
def failures
|
43
|
+
result.failures
|
44
|
+
end
|
27
45
|
end
|
28
46
|
end
|
29
47
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
pl:
|
2
|
+
errors:
|
3
|
+
filled?: "%{name} nie może być pusty"
|
4
|
+
size?:
|
5
|
+
arg:
|
6
|
+
default: "wielkość musi być równa %{num}"
|
7
|
+
range: "wielkość musi być między %{left} a %{right}"
|
8
|
+
rules:
|
9
|
+
email:
|
10
|
+
filled?: "Proszę podać adres email"
|
11
|
+
user:
|
12
|
+
rules:
|
13
|
+
email:
|
14
|
+
filled?: "Hej user! Dawaj ten email no!"
|
@@ -5,29 +5,17 @@ RSpec.describe Dry::Validation, 'with custom messages' do
|
|
5
5
|
let(:schema) do
|
6
6
|
Class.new(Dry::Validation::Schema) do
|
7
7
|
configure do |config|
|
8
|
-
config.messages_file = SPEC_ROOT.join('fixtures/
|
9
|
-
config.namespace = :user
|
8
|
+
config.messages_file = SPEC_ROOT.join('fixtures/locales/en.yml')
|
10
9
|
end
|
11
10
|
|
12
|
-
key(:email
|
11
|
+
key(:email, &:filled?)
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
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
15
|
describe '#messages' do
|
28
16
|
it 'returns compiled error messages' do
|
29
|
-
expect(validation.
|
30
|
-
[:email, [
|
17
|
+
expect(validation.(email: '').messages).to match_array([
|
18
|
+
[:email, [['Please provide your email', '']]]
|
31
19
|
])
|
32
20
|
end
|
33
21
|
end
|
@@ -6,10 +6,14 @@ RSpec.describe Dry::Validation::ErrorCompiler do
|
|
6
6
|
|
7
7
|
let(:messages) do
|
8
8
|
Messages.default.merge(
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
en: {
|
10
|
+
errors: {
|
11
|
+
key?: '+%{name}+ key is missing in the hash',
|
12
|
+
rules: {
|
13
|
+
address: {
|
14
|
+
filled?: 'Please provide your address'
|
15
|
+
}
|
16
|
+
}
|
13
17
|
}
|
14
18
|
}
|
15
19
|
)
|
@@ -26,202 +30,240 @@ RSpec.describe Dry::Validation::ErrorCompiler do
|
|
26
30
|
end
|
27
31
|
|
28
32
|
it 'converts error ast into another format' do
|
29
|
-
expect(error_compiler.(ast)).to eql(
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
expect(error_compiler.(ast)).to eql(
|
34
|
+
name: [["+name+ key is missing in the hash", nil]],
|
35
|
+
age: [["age must be greater than 18", 18]],
|
36
|
+
email: [["email must be filled", '']],
|
37
|
+
address: [["Please provide your address", '']]
|
38
|
+
)
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
38
42
|
describe '#visit_predicate' do
|
39
43
|
describe ':empty?' do
|
40
44
|
it 'returns valid message' do
|
41
|
-
msg = error_compiler.visit_predicate([:empty?, []], [], :tags)
|
45
|
+
msg, val = error_compiler.visit_predicate([:empty?, []], [], :tags)
|
42
46
|
|
47
|
+
expect(val).to eql([])
|
43
48
|
expect(msg).to eql('tags cannot be empty')
|
44
49
|
end
|
45
50
|
end
|
46
51
|
|
47
52
|
describe ':exclusion?' do
|
48
53
|
it 'returns valid message' do
|
49
|
-
msg = error_compiler.visit_predicate([:exclusion?, [[1, 2, 3]]], 2, :num)
|
54
|
+
msg, val = error_compiler.visit_predicate([:exclusion?, [[1, 2, 3]]], 2, :num)
|
50
55
|
|
56
|
+
expect(val).to be(2)
|
51
57
|
expect(msg).to eql('num must not be one of: 1, 2, 3')
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
55
61
|
describe ':inclusion?' do
|
56
62
|
it 'returns valid message' do
|
57
|
-
msg = error_compiler.visit_predicate([:inclusion?, [[1, 2, 3]]], 2, :num)
|
63
|
+
msg, val = error_compiler.visit_predicate([:inclusion?, [[1, 2, 3]]], 2, :num)
|
58
64
|
|
65
|
+
expect(val).to be(2)
|
59
66
|
expect(msg).to eql('num must be one of: 1, 2, 3')
|
60
67
|
end
|
61
68
|
end
|
62
69
|
|
63
70
|
describe ':gt?' do
|
64
71
|
it 'returns valid message' do
|
65
|
-
msg = error_compiler.visit_predicate([:gt?, [3]], 2, :num)
|
72
|
+
msg, val = error_compiler.visit_predicate([:gt?, [3]], 2, :num)
|
66
73
|
|
67
|
-
expect(
|
74
|
+
expect(val).to be(2)
|
75
|
+
expect(msg).to eql('num must be greater than 3')
|
68
76
|
end
|
69
77
|
end
|
70
78
|
|
71
79
|
describe ':gteq?' do
|
72
80
|
it 'returns valid message' do
|
73
|
-
msg = error_compiler.visit_predicate([:gteq?, [3]], 2, :num)
|
81
|
+
msg, val = error_compiler.visit_predicate([:gteq?, [3]], 2, :num)
|
74
82
|
|
83
|
+
expect(val).to be(2)
|
75
84
|
expect(msg).to eql('num must be greater than or equal to 3')
|
76
85
|
end
|
77
86
|
end
|
78
87
|
|
79
88
|
describe ':lt?' do
|
80
89
|
it 'returns valid message' do
|
81
|
-
msg = error_compiler.visit_predicate([:lt?, [3]], 2, :num)
|
90
|
+
msg, val = error_compiler.visit_predicate([:lt?, [3]], 2, :num)
|
82
91
|
|
92
|
+
expect(val).to be(2)
|
83
93
|
expect(msg).to eql('num must be less than 3 (2 was given)')
|
84
94
|
end
|
85
95
|
end
|
86
96
|
|
87
97
|
describe ':lteq?' do
|
88
98
|
it 'returns valid message' do
|
89
|
-
msg = error_compiler.visit_predicate([:lteq?, [3]], 2, :num)
|
99
|
+
msg, val = error_compiler.visit_predicate([:lteq?, [3]], 2, :num)
|
90
100
|
|
101
|
+
expect(val).to be(2)
|
91
102
|
expect(msg).to eql('num must be less than or equal to 3')
|
92
103
|
end
|
93
104
|
end
|
94
105
|
|
95
106
|
describe ':hash?' do
|
96
107
|
it 'returns valid message' do
|
97
|
-
msg = error_compiler.visit_predicate([:hash?, []], '', :address)
|
108
|
+
msg, val = error_compiler.visit_predicate([:hash?, []], '', :address)
|
98
109
|
|
110
|
+
expect(val).to eql('')
|
99
111
|
expect(msg).to eql('address must be a hash')
|
100
112
|
end
|
101
113
|
end
|
102
114
|
|
103
115
|
describe ':array?' do
|
104
116
|
it 'returns valid message' do
|
105
|
-
msg = error_compiler.visit_predicate([:array?, []], '', :phone_numbers)
|
117
|
+
msg, val = error_compiler.visit_predicate([:array?, []], '', :phone_numbers)
|
106
118
|
|
119
|
+
expect(val).to eql('')
|
107
120
|
expect(msg).to eql('phone_numbers must be an array')
|
108
121
|
end
|
109
122
|
end
|
110
123
|
|
111
124
|
describe ':int?' do
|
112
125
|
it 'returns valid message' do
|
113
|
-
msg = error_compiler.visit_predicate([:int?, []], '2', :num)
|
126
|
+
msg, val = error_compiler.visit_predicate([:int?, []], '2', :num)
|
114
127
|
|
128
|
+
expect(val).to eql('2')
|
115
129
|
expect(msg).to eql('num must be an integer')
|
116
130
|
end
|
117
131
|
end
|
118
132
|
|
119
133
|
describe ':float?' do
|
120
134
|
it 'returns valid message' do
|
121
|
-
msg = error_compiler.visit_predicate([:float?, []], '2', :num)
|
135
|
+
msg, val = error_compiler.visit_predicate([:float?, []], '2', :num)
|
122
136
|
|
137
|
+
expect(val).to eql('2')
|
123
138
|
expect(msg).to eql('num must be a float')
|
124
139
|
end
|
125
140
|
end
|
126
141
|
|
127
142
|
describe ':decimal?' do
|
128
143
|
it 'returns valid message' do
|
129
|
-
msg = error_compiler.visit_predicate([:decimal?, []], '2', :num)
|
144
|
+
msg, val = error_compiler.visit_predicate([:decimal?, []], '2', :num)
|
130
145
|
|
146
|
+
expect(val).to eql('2')
|
131
147
|
expect(msg).to eql('num must be a decimal')
|
132
148
|
end
|
133
149
|
end
|
134
150
|
|
135
151
|
describe ':date?' do
|
136
152
|
it 'returns valid message' do
|
137
|
-
msg = error_compiler.visit_predicate([:date?, []], '2', :num)
|
153
|
+
msg, val = error_compiler.visit_predicate([:date?, []], '2', :num)
|
138
154
|
|
155
|
+
expect(val).to eql('2')
|
139
156
|
expect(msg).to eql('num must be a date')
|
140
157
|
end
|
141
158
|
end
|
142
159
|
|
143
160
|
describe ':date_time?' do
|
144
161
|
it 'returns valid message' do
|
145
|
-
msg = error_compiler.visit_predicate([:date_time?, []], '2', :num)
|
162
|
+
msg, val = error_compiler.visit_predicate([:date_time?, []], '2', :num)
|
146
163
|
|
164
|
+
expect(val).to eql('2')
|
147
165
|
expect(msg).to eql('num must be a date time')
|
148
166
|
end
|
149
167
|
end
|
150
168
|
|
151
169
|
describe ':time?' do
|
152
170
|
it 'returns valid message' do
|
153
|
-
msg = error_compiler.visit_predicate([:time?, []], '2', :num)
|
171
|
+
msg, val = error_compiler.visit_predicate([:time?, []], '2', :num)
|
154
172
|
|
173
|
+
expect(val).to eql('2')
|
155
174
|
expect(msg).to eql('num must be a time')
|
156
175
|
end
|
157
176
|
end
|
158
177
|
|
159
178
|
describe ':max_size?' do
|
160
179
|
it 'returns valid message' do
|
161
|
-
msg = error_compiler.visit_predicate([:max_size?, [3]], 'abcd', :num)
|
180
|
+
msg, val = error_compiler.visit_predicate([:max_size?, [3]], 'abcd', :num)
|
162
181
|
|
182
|
+
expect(val).to eql('abcd')
|
163
183
|
expect(msg).to eql('num size cannot be greater than 3')
|
164
184
|
end
|
165
185
|
end
|
166
186
|
|
167
187
|
describe ':min_size?' do
|
168
188
|
it 'returns valid message' do
|
169
|
-
msg = error_compiler.visit_predicate([:min_size?, [3]], 'ab', :num)
|
189
|
+
msg, val = error_compiler.visit_predicate([:min_size?, [3]], 'ab', :num)
|
170
190
|
|
191
|
+
expect(val).to eql('ab')
|
171
192
|
expect(msg).to eql('num size cannot be less than 3')
|
172
193
|
end
|
173
194
|
end
|
174
195
|
|
175
|
-
describe ':
|
196
|
+
describe ':none?' do
|
176
197
|
it 'returns valid message' do
|
177
|
-
msg = error_compiler.visit_predicate([:
|
198
|
+
msg, val = error_compiler.visit_predicate([:none?, []], nil, :num)
|
178
199
|
|
179
|
-
expect(
|
200
|
+
expect(val).to be(nil)
|
201
|
+
expect(msg).to eql('num cannot be defined')
|
180
202
|
end
|
181
203
|
end
|
182
204
|
|
183
205
|
describe ':size?' do
|
206
|
+
it 'returns valid message when val is array and arg is int' do
|
207
|
+
msg, val = error_compiler.visit_predicate([:size?, [3]], [1], :numbers)
|
208
|
+
|
209
|
+
expect(val).to eql([1])
|
210
|
+
expect(msg).to eql('numbers size must be 3')
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'returns valid message when val is array and arg is range' do
|
214
|
+
msg, val = error_compiler.visit_predicate([:size?, [3..4]], [1], :numbers)
|
215
|
+
|
216
|
+
expect(val).to eql([1])
|
217
|
+
expect(msg).to eql('numbers size must be within 3 - 4')
|
218
|
+
end
|
219
|
+
|
184
220
|
it 'returns valid message when arg is int' do
|
185
|
-
msg = error_compiler.visit_predicate([:size?, [3]], 'ab', :num)
|
221
|
+
msg, val = error_compiler.visit_predicate([:size?, [3]], 'ab', :num)
|
186
222
|
|
187
|
-
expect(
|
223
|
+
expect(val).to eql('ab')
|
224
|
+
expect(msg).to eql('num length must be 3')
|
188
225
|
end
|
189
226
|
|
190
227
|
it 'returns valid message when arg is range' do
|
191
|
-
msg = error_compiler.visit_predicate([:size?, [3..4]], 'ab', :num)
|
228
|
+
msg, val = error_compiler.visit_predicate([:size?, [3..4]], 'ab', :num)
|
192
229
|
|
193
|
-
expect(
|
230
|
+
expect(val).to eql('ab')
|
231
|
+
expect(msg).to eql('num length must be within 3 - 4')
|
194
232
|
end
|
195
233
|
end
|
196
234
|
|
197
235
|
describe ':str?' do
|
198
236
|
it 'returns valid message' do
|
199
|
-
msg = error_compiler.visit_predicate([:str?, []], 3, :num)
|
237
|
+
msg, val = error_compiler.visit_predicate([:str?, []], 3, :num)
|
200
238
|
|
239
|
+
expect(val).to be(3)
|
201
240
|
expect(msg).to eql('num must be a string')
|
202
241
|
end
|
203
242
|
end
|
204
243
|
|
205
244
|
describe ':bool?' do
|
206
245
|
it 'returns valid message' do
|
207
|
-
msg = error_compiler.visit_predicate([:bool?, []], 3, :num)
|
246
|
+
msg, val = error_compiler.visit_predicate([:bool?, []], 3, :num)
|
208
247
|
|
248
|
+
expect(val).to be(3)
|
209
249
|
expect(msg).to eql('num must be boolean')
|
210
250
|
end
|
211
251
|
end
|
212
252
|
|
213
253
|
describe ':format?' do
|
214
254
|
it 'returns valid message' do
|
215
|
-
msg = error_compiler.visit_predicate([:format?, [/^F/]], 'Bar', :str)
|
255
|
+
msg, val = error_compiler.visit_predicate([:format?, [/^F/]], 'Bar', :str)
|
216
256
|
|
257
|
+
expect(val).to eql('Bar')
|
217
258
|
expect(msg).to eql('str is in invalid format')
|
218
259
|
end
|
219
260
|
end
|
220
261
|
|
221
262
|
describe ':eql?' do
|
222
263
|
it 'returns valid message' do
|
223
|
-
msg = error_compiler.visit_predicate([:eql?, ['Bar']], 'Foo', :str)
|
264
|
+
msg, val = error_compiler.visit_predicate([:eql?, ['Bar']], 'Foo', :str)
|
224
265
|
|
266
|
+
expect(val).to eql('Foo')
|
225
267
|
expect(msg).to eql('str must be equal to Bar')
|
226
268
|
end
|
227
269
|
end
|