dry-validation 0.6.0 → 0.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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +1 -0
- data/.travis.yml +3 -2
- data/CHANGELOG.md +42 -0
- data/Gemfile +8 -1
- data/README.md +13 -89
- data/config/errors.yml +35 -29
- data/dry-validation.gemspec +2 -2
- data/examples/basic.rb +3 -7
- data/examples/each.rb +3 -8
- data/examples/form.rb +3 -6
- data/examples/nested.rb +7 -15
- data/lib/dry/validation.rb +33 -5
- data/lib/dry/validation/error.rb +10 -26
- data/lib/dry/validation/error_compiler.rb +69 -99
- data/lib/dry/validation/error_compiler/input.rb +148 -0
- data/lib/dry/validation/hint_compiler.rb +83 -33
- data/lib/dry/validation/input_processor_compiler.rb +98 -0
- data/lib/dry/validation/input_processor_compiler/form.rb +46 -0
- data/lib/dry/validation/input_processor_compiler/sanitizer.rb +46 -0
- data/lib/dry/validation/messages/abstract.rb +30 -10
- data/lib/dry/validation/messages/i18n.rb +2 -1
- data/lib/dry/validation/messages/namespaced.rb +1 -0
- data/lib/dry/validation/messages/yaml.rb +8 -5
- data/lib/dry/validation/result.rb +33 -25
- data/lib/dry/validation/schema.rb +168 -61
- data/lib/dry/validation/schema/attr.rb +5 -27
- data/lib/dry/validation/schema/check.rb +24 -0
- data/lib/dry/validation/schema/dsl.rb +97 -0
- data/lib/dry/validation/schema/form.rb +2 -26
- data/lib/dry/validation/schema/key.rb +32 -28
- data/lib/dry/validation/schema/rule.rb +88 -32
- data/lib/dry/validation/schema/value.rb +77 -27
- data/lib/dry/validation/schema_compiler.rb +38 -0
- data/lib/dry/validation/version.rb +1 -1
- data/spec/fixtures/locales/pl.yml +1 -1
- data/spec/integration/attr_spec.rb +122 -0
- data/spec/integration/custom_error_messages_spec.rb +9 -11
- data/spec/integration/custom_predicates_spec.rb +68 -18
- data/spec/integration/error_compiler_spec.rb +259 -65
- data/spec/integration/hints_spec.rb +28 -9
- data/spec/integration/injecting_rules_spec.rb +11 -12
- data/spec/integration/localized_error_messages_spec.rb +16 -16
- data/spec/integration/messages/i18n_spec.rb +9 -5
- data/spec/integration/optional_keys_spec.rb +9 -11
- data/spec/integration/schema/array_schema_spec.rb +23 -0
- data/spec/integration/schema/check_rules_spec.rb +39 -31
- data/spec/integration/schema/check_with_nth_el_spec.rb +25 -0
- data/spec/integration/schema/each_with_set_spec.rb +23 -24
- data/spec/integration/schema/form_spec.rb +122 -0
- data/spec/integration/schema/inheriting_schema_spec.rb +31 -0
- data/spec/integration/schema/input_processor_spec.rb +46 -0
- data/spec/integration/schema/macros/confirmation_spec.rb +33 -0
- data/spec/integration/schema/macros/maybe_spec.rb +32 -0
- data/spec/integration/schema/macros/required_spec.rb +59 -0
- data/spec/integration/schema/macros/when_spec.rb +65 -0
- data/spec/integration/schema/nested_values_spec.rb +41 -0
- data/spec/integration/schema/not_spec.rb +14 -14
- data/spec/integration/schema/option_with_default_spec.rb +30 -0
- data/spec/integration/schema/reusing_schema_spec.rb +33 -0
- data/spec/integration/schema/using_types_spec.rb +29 -0
- data/spec/integration/schema/xor_spec.rb +17 -14
- data/spec/integration/schema_spec.rb +75 -245
- data/spec/shared/rule_compiler.rb +8 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/unit/hint_compiler_spec.rb +10 -10
- data/spec/unit/{input_type_compiler_spec.rb → input_processor_compiler/form_spec.rb} +88 -73
- data/spec/unit/schema/key_spec.rb +33 -0
- data/spec/unit/schema/rule_spec.rb +7 -6
- data/spec/unit/schema/value_spec.rb +187 -54
- metadata +53 -31
- data/.rubocop.yml +0 -16
- data/.rubocop_todo.yml +0 -7
- data/lib/dry/validation/input_type_compiler.rb +0 -83
- data/lib/dry/validation/schema/definition.rb +0 -74
- data/lib/dry/validation/schema/result.rb +0 -68
- data/rakelib/rubocop.rake +0 -18
- data/spec/integration/rule_groups_spec.rb +0 -94
- data/spec/integration/schema/attrs_spec.rb +0 -38
- data/spec/integration/schema/default_key_behavior_spec.rb +0 -23
- data/spec/integration/schema/grouped_rules_spec.rb +0 -57
- data/spec/integration/schema/nested_spec.rb +0 -31
- data/spec/integration/schema_form_spec.rb +0 -97
@@ -0,0 +1,30 @@
|
|
1
|
+
RSpec.describe Dry::Validation::Schema, 'defining an option with default value' do
|
2
|
+
subject(:schema) do
|
3
|
+
Dry::Validation.Schema do
|
4
|
+
configure do
|
5
|
+
option :db, -> { DB }
|
6
|
+
|
7
|
+
def unique?(name, value)
|
8
|
+
DB.none? { |item| item[name] == value }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
key(:email) { filled? & unique?(:email) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
DB = [{ email: 'jane@doe' }]
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
Object.send(:remove_const, :DB)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'uses external dependency set by option with a default value' do
|
25
|
+
expect(schema.db).to be(DB)
|
26
|
+
|
27
|
+
expect(schema.(email: 'jade@doe')).to be_success
|
28
|
+
expect(schema.(email: 'jane@doe')).to be_failure
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
RSpec.describe 'Reusing schemas' do
|
2
|
+
subject(:schema) do
|
3
|
+
Dry::Validation.Schema do
|
4
|
+
key(:city).required
|
5
|
+
|
6
|
+
key(:location).schema(LocationSchema)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
before do
|
11
|
+
LocationSchema = Dry::Validation.Schema do
|
12
|
+
configure { config.input_processor = :form }
|
13
|
+
|
14
|
+
key(:lat).required(:float?)
|
15
|
+
key(:lng).required(:float?)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
Object.send(:remove_const, :LocationSchema)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 're-uses existing schema' do
|
24
|
+
expect(schema.(city: 'NYC', location: { lat: 1.23, lng: 45.6 })).to be_success
|
25
|
+
|
26
|
+
expect(schema.(city: 'NYC', location: { lat: nil, lng: '45.6' }).messages).to eql(
|
27
|
+
location: {
|
28
|
+
lat: ['must be filled'],
|
29
|
+
lng: ['must be a float']
|
30
|
+
}
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
RSpec.describe Dry::Validation::Schema, 'defining schema using dry types' do
|
2
|
+
subject(:schema) do
|
3
|
+
Dry::Validation.Schema do
|
4
|
+
key(:email).required(Email)
|
5
|
+
key(:age).maybe(Age)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
before do
|
10
|
+
Email = Dry::Types['strict.string']
|
11
|
+
Age = Dry::Types['strict.int'].constrained(gt: 18)
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
Object.send(:remove_const, :Email)
|
16
|
+
Object.send(:remove_const, :Age)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'passes when input is valid' do
|
20
|
+
expect(schema.(email: 'jane@doe', age: 19)).to be_success
|
21
|
+
expect(schema.(email: 'jane@doe', age: nil)).to be_success
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'fails when input is not valid' do
|
25
|
+
expect(schema.(email: '', age: 19)).to_not be_success
|
26
|
+
expect(schema.(email: 'jane@doe', age: 17)).to_not be_success
|
27
|
+
expect(schema.(email: 'jane@doe', age: '19')).to_not be_success
|
28
|
+
end
|
29
|
+
end
|
@@ -1,32 +1,35 @@
|
|
1
1
|
RSpec.describe 'Schema with xor rules' do
|
2
|
-
subject(:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
subject(:schema) do
|
3
|
+
Dry::Validation.Schema do
|
4
|
+
configure do
|
5
|
+
def self.messages
|
6
|
+
Messages.default.merge(
|
7
|
+
en: { errors: { be_reasonable: 'you cannot eat cake and have cake!' } }
|
8
|
+
)
|
9
|
+
end
|
10
10
|
end
|
11
11
|
|
12
|
-
key(:eat_cake)
|
13
|
-
|
12
|
+
key(:eat_cake).required
|
13
|
+
|
14
|
+
key(:have_cake).required
|
14
15
|
|
15
|
-
rule(:be_reasonable)
|
16
|
+
rule(:be_reasonable) do
|
17
|
+
value(:eat_cake).eql?('yes!') ^ value(:have_cake).eql?('yes!')
|
18
|
+
end
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
19
22
|
describe '#messages' do
|
20
23
|
it 'passes when only one option is selected' do
|
21
|
-
messages =
|
24
|
+
messages = schema.(eat_cake: 'yes!', have_cake: 'no!').messages[:be_reasonable]
|
22
25
|
|
23
26
|
expect(messages).to be(nil)
|
24
27
|
end
|
25
28
|
|
26
29
|
it 'fails when both options are selected' do
|
27
|
-
messages =
|
30
|
+
messages = schema.(eat_cake: 'yes!', have_cake: 'yes!').messages[:be_reasonable]
|
28
31
|
|
29
|
-
expect(messages).to eql([
|
32
|
+
expect(messages).to eql(['you cannot eat cake and have cake!'])
|
30
33
|
end
|
31
34
|
end
|
32
35
|
end
|
@@ -1,179 +1,55 @@
|
|
1
|
-
RSpec.describe Dry::Validation::Schema do
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
key(:email) { |email| email.filled? }
|
8
|
-
|
9
|
-
key(:age) do |age|
|
10
|
-
age.none? | (age.int? & age.gt?(18))
|
11
|
-
end
|
12
|
-
|
13
|
-
key(:address) do |address|
|
14
|
-
address.hash? do
|
15
|
-
address.key(:city) do |city|
|
16
|
-
city.min_size?(3)
|
17
|
-
end
|
18
|
-
|
19
|
-
address.key(:street) do |street|
|
20
|
-
street.filled?
|
21
|
-
end
|
22
|
-
|
23
|
-
address.key(:country) do |country|
|
24
|
-
country.key(:name, &:filled?)
|
25
|
-
country.key(:code, &:filled?)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
key(:phone_numbers) do |phone_numbers|
|
31
|
-
phone_numbers.array? { phone_numbers.each(&:str?) }
|
32
|
-
end
|
1
|
+
RSpec.describe Dry::Validation::Schema, 'defining key-based schema' do
|
2
|
+
describe 'with a flat structure' do
|
3
|
+
subject(:schema) do
|
4
|
+
Dry::Validation.Schema do
|
5
|
+
key(:email).required
|
6
|
+
key(:age) { none? | (int? & gt?(18)) }
|
33
7
|
end
|
34
8
|
end
|
35
9
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
age: 19,
|
40
|
-
address: { city: 'NYC', street: 'Street 1/2', country: { code: 'US', name: 'USA' } },
|
41
|
-
phone_numbers: [
|
42
|
-
'123456', '234567'
|
43
|
-
]
|
44
|
-
}.freeze
|
10
|
+
it 'passes when input is valid' do
|
11
|
+
expect(schema.(email: 'jane@doe', age: 19)).to be_success
|
12
|
+
expect(schema.(email: 'jane@doe', age: nil)).to be_success
|
45
13
|
end
|
46
14
|
|
47
|
-
|
48
|
-
|
49
|
-
expect(validation.(input.merge(email: '')).messages).to match_array([
|
50
|
-
[:email, [['email must be filled'], '']]
|
51
|
-
])
|
52
|
-
end
|
15
|
+
it 'fails when input is not valid' do
|
16
|
+
expect(schema.(email: 'jane@doe', age: 17)).to_not be_success
|
53
17
|
end
|
54
18
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'validates presence of an email and min age value' do
|
61
|
-
expect(validation.(input.merge(email: '', age: 18))).to match_array([
|
62
|
-
[:error, [:input, [:age, 18, [[:val, [:age, [:predicate, [:gt?, [18]]]]]]]]],
|
63
|
-
[:error, [:input, [:email, "", [[:val, [:email, [:predicate, [:filled?, []]]]]]]]]
|
64
|
-
])
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'validates presence of the email key and type of age value' do
|
68
|
-
expect(validation.(name: 'Jane', age: '18', address: input[:address], phone_numbers: input[:phone_numbers])).to match_array([
|
69
|
-
[:error, [:input, [:age, "18", [[:val, [:age, [:predicate, [:int?, []]]]]]]]],
|
70
|
-
[:error, [:input, [:email, nil, [[:key, [:email, [:predicate, [:key?, [:email]]]]]]]]]
|
71
|
-
])
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'validates presence of the address and phone_number keys' do
|
75
|
-
expect(validation.(email: 'jane@doe.org', age: 19)).to match_array([
|
76
|
-
[:error, [:input, [:address, nil, [[:key, [:address, [:predicate, [:key?, [:address]]]]]]]]],
|
77
|
-
[:error, [:input, [:phone_numbers, nil, [[:key, [:phone_numbers, [:predicate, [:key?, [:phone_numbers]]]]]]]]]
|
78
|
-
])
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'validates presence of keys under address and min size of the city value' do
|
82
|
-
expect(validation.(input.merge(address: { city: 'NY' }))).to match_array([
|
83
|
-
[:error, [
|
84
|
-
:input, [
|
85
|
-
:address, {city: "NY"},
|
86
|
-
[
|
87
|
-
[:input, [:city, "NY", [[:val, [:city, [:predicate, [:min_size?, [3]]]]]]]],
|
88
|
-
[:input, [:street, nil, [[:key, [:street, [:predicate, [:key?, [:street]]]]]]]],
|
89
|
-
[:input, [:country, nil, [[:key, [:country, [:predicate, [:key?, [:country]]]]]]]]
|
90
|
-
]
|
91
|
-
]
|
92
|
-
]]
|
93
|
-
])
|
94
|
-
end
|
19
|
+
it 'returns result which quacks like hash' do
|
20
|
+
input = { email: 'jane@doe', age: 19 }
|
21
|
+
result = schema.(input)
|
95
22
|
|
96
|
-
|
97
|
-
|
98
|
-
[:error, [:input, [:address, "totally not a hash", [[:val, [:address, [:predicate, [:hash?, []]]]]]]]]
|
99
|
-
])
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'validates address code and name values' do
|
103
|
-
expect(validation.(input.merge(address: input[:address].merge(country: { code: 'US', name: '' })))).to match_array([
|
104
|
-
[:error, [
|
105
|
-
:input, [
|
106
|
-
:address, {city: "NYC", street: "Street 1/2", country: {code: "US", name: ""}},
|
107
|
-
[
|
108
|
-
[
|
109
|
-
:input, [
|
110
|
-
:country, {code: "US", name: ""}, [
|
111
|
-
[
|
112
|
-
:input, [
|
113
|
-
:name, "", [[:val, [:name, [:predicate, [:filled?, []]]]]]
|
114
|
-
]
|
115
|
-
]
|
116
|
-
]
|
117
|
-
]
|
118
|
-
]
|
119
|
-
]
|
120
|
-
]
|
121
|
-
]]
|
122
|
-
])
|
123
|
-
end
|
23
|
+
expect(result[:email]).to eql('jane@doe')
|
24
|
+
expect(Hash[result]).to eql(input)
|
124
25
|
|
125
|
-
|
126
|
-
expect(validation.(input.merge(phone_numbers: ['123', 312]))).to match_array([
|
127
|
-
[:error, [
|
128
|
-
:input, [
|
129
|
-
:phone_numbers, ["123", 312],
|
130
|
-
[
|
131
|
-
[
|
132
|
-
:input, [
|
133
|
-
:phone_numbers, 312, [
|
134
|
-
[:val, [:phone_numbers, [:predicate, [:str?, []]]]]
|
135
|
-
]
|
136
|
-
]
|
137
|
-
]
|
138
|
-
]
|
139
|
-
]
|
140
|
-
]]
|
141
|
-
])
|
142
|
-
end
|
26
|
+
expect(result.to_a).to eql([[:email, 'jane@doe'], [:age, 19]])
|
143
27
|
end
|
144
28
|
end
|
145
29
|
|
146
|
-
describe '
|
147
|
-
|
148
|
-
|
149
|
-
|
30
|
+
describe 'with nested structures' do
|
31
|
+
subject(:schema) do
|
32
|
+
Dry::Validation.Schema do
|
33
|
+
key(:email).required
|
150
34
|
|
151
|
-
|
152
|
-
age.none? | (age.int? & age.gt?(18))
|
153
|
-
end
|
35
|
+
key(:age).maybe(:int?, gt?: 18)
|
154
36
|
|
155
|
-
|
156
|
-
|
157
|
-
city.min_size?(3)
|
158
|
-
end
|
37
|
+
key(:address).schema do
|
38
|
+
key(:city).required(min_size?: 3)
|
159
39
|
|
160
|
-
|
161
|
-
street.filled?
|
162
|
-
end
|
40
|
+
key(:street).required
|
163
41
|
|
164
|
-
|
165
|
-
|
166
|
-
|
42
|
+
key(:country).schema do
|
43
|
+
key(:name).required
|
44
|
+
key(:code).required
|
167
45
|
end
|
168
46
|
end
|
169
47
|
|
170
|
-
|
171
|
-
phone_numbers.array? { phone_numbers.each(&:str?) }
|
172
|
-
end
|
48
|
+
key(:phone_numbers).each(:str?)
|
173
49
|
end
|
174
50
|
end
|
175
51
|
|
176
|
-
let(:
|
52
|
+
let(:input) do
|
177
53
|
{
|
178
54
|
email: 'jane@doe.org',
|
179
55
|
age: 19,
|
@@ -184,126 +60,80 @@ RSpec.describe Dry::Validation::Schema do
|
|
184
60
|
}.freeze
|
185
61
|
end
|
186
62
|
|
187
|
-
def input(data = input_data)
|
188
|
-
struct_from_hash(data)
|
189
|
-
end
|
190
|
-
|
191
63
|
describe '#messages' do
|
192
64
|
it 'returns compiled error messages' do
|
193
|
-
expect(
|
194
|
-
|
195
|
-
|
65
|
+
expect(schema.(input.merge(email: '')).messages).to eql(
|
66
|
+
email: ['must be filled']
|
67
|
+
)
|
196
68
|
end
|
197
69
|
end
|
198
70
|
|
199
71
|
describe '#call' do
|
200
72
|
it 'passes when attributes are valid' do
|
201
|
-
expect(
|
73
|
+
expect(schema.(input)).to be_success
|
202
74
|
end
|
203
75
|
|
204
76
|
it 'validates presence of an email and min age value' do
|
205
|
-
expect(
|
206
|
-
|
207
|
-
|
208
|
-
])
|
77
|
+
expect(schema.(input.merge(email: '', age: 18)).messages).to eql(
|
78
|
+
email: ['must be filled'], age: ['must be greater than 18']
|
79
|
+
)
|
209
80
|
end
|
210
81
|
|
211
|
-
it 'validates presence of the email
|
212
|
-
|
82
|
+
it 'validates presence of the email key and type of age value' do
|
83
|
+
attrs = {
|
84
|
+
name: 'Jane',
|
85
|
+
age: '18',
|
86
|
+
address: input[:address], phone_numbers: input[:phone_numbers]
|
87
|
+
}
|
213
88
|
|
214
|
-
expect(
|
215
|
-
|
216
|
-
|
217
|
-
|
89
|
+
expect(schema.(attrs).messages).to eql(
|
90
|
+
email: ['is missing'],
|
91
|
+
age: ['must be an integer', 'must be greater than 18']
|
92
|
+
)
|
218
93
|
end
|
219
94
|
|
220
95
|
it 'validates presence of the address and phone_number keys' do
|
221
|
-
|
96
|
+
attrs = { email: 'jane@doe.org', age: 19 }
|
222
97
|
|
223
|
-
expect(
|
224
|
-
[
|
225
|
-
|
226
|
-
:address, input_object,
|
227
|
-
[
|
228
|
-
[:attr, [:address, [:predicate, [:attr?, [:address]]]]]
|
229
|
-
]
|
230
|
-
]
|
231
|
-
]],
|
232
|
-
[:error, [
|
233
|
-
:input, [
|
234
|
-
:phone_numbers, input_object,
|
235
|
-
[
|
236
|
-
[:attr, [:phone_numbers, [:predicate, [:attr?, [:phone_numbers]]]]]
|
237
|
-
]
|
238
|
-
]
|
239
|
-
]]
|
240
|
-
])
|
98
|
+
expect(schema.(attrs).messages).to eql(
|
99
|
+
address: ['is missing'], phone_numbers: ['is missing']
|
100
|
+
)
|
241
101
|
end
|
242
102
|
|
243
103
|
it 'validates presence of keys under address and min size of the city value' do
|
244
|
-
|
245
|
-
input_object = input(input_data.merge(address: address))
|
246
|
-
address_object = input_object.address.class.from_hash(address)
|
104
|
+
attrs = input.merge(address: { city: 'NY' })
|
247
105
|
|
248
|
-
expect(
|
249
|
-
|
250
|
-
:
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
[:input, [:country, address_object, [[:attr, [:country, [:predicate, [:attr?, [:country]]]]]]]]
|
256
|
-
]
|
257
|
-
]
|
258
|
-
]]
|
259
|
-
])
|
106
|
+
expect(schema.(attrs).messages).to eql(
|
107
|
+
address: {
|
108
|
+
street: ['is missing'],
|
109
|
+
country: ['is missing'],
|
110
|
+
city: ['size cannot be less than 3']
|
111
|
+
}
|
112
|
+
)
|
260
113
|
end
|
261
114
|
|
262
|
-
it 'validates address
|
263
|
-
|
115
|
+
it 'validates address type' do
|
116
|
+
expect(schema.(input.merge(address: 'totally not a hash')).messages).to eql(
|
117
|
+
address: ['must be a hash']
|
118
|
+
)
|
119
|
+
end
|
264
120
|
|
265
|
-
|
121
|
+
it 'validates address code and name values' do
|
122
|
+
attrs = input.merge(
|
123
|
+
address: input[:address].merge(country: { code: 'US', name: '' })
|
124
|
+
)
|
266
125
|
|
267
|
-
expect(
|
268
|
-
|
269
|
-
|
270
|
-
:address, input_object.address.class.from_hash(city: "NYC", street: "Street 1/2", country: country_object),
|
271
|
-
[
|
272
|
-
[
|
273
|
-
:input, [
|
274
|
-
:country, country_object, [
|
275
|
-
[
|
276
|
-
:input, [
|
277
|
-
:name, "", [[:val, [:name, [:predicate, [:filled?, []]]]]]
|
278
|
-
]
|
279
|
-
]
|
280
|
-
]
|
281
|
-
]
|
282
|
-
]
|
283
|
-
]
|
284
|
-
]
|
285
|
-
]]
|
286
|
-
])
|
126
|
+
expect(schema.(attrs).messages).to eql(
|
127
|
+
address: { country: { name: ['must be filled'] } }
|
128
|
+
)
|
287
129
|
end
|
288
130
|
|
289
131
|
it 'validates each phone number' do
|
290
|
-
|
132
|
+
attrs = input.merge(phone_numbers: ['123', 312])
|
291
133
|
|
292
|
-
expect(
|
293
|
-
|
294
|
-
|
295
|
-
:phone_numbers, ["123", 312],[
|
296
|
-
[
|
297
|
-
:input, [
|
298
|
-
:phone_numbers, 312, [
|
299
|
-
[:val, [:phone_numbers, [:predicate, [:str?, []]]]]
|
300
|
-
]
|
301
|
-
]
|
302
|
-
]
|
303
|
-
]
|
304
|
-
]
|
305
|
-
]]
|
306
|
-
])
|
134
|
+
expect(schema.(attrs).messages).to eql(
|
135
|
+
phone_numbers: { 1 => ['must be a string'] }
|
136
|
+
)
|
307
137
|
end
|
308
138
|
end
|
309
139
|
end
|