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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +506 -95
- data/LICENSE +1 -1
- data/README.md +16 -12
- data/config/errors.yml +3 -88
- data/dry-validation.gemspec +37 -24
- 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 +171 -0
- data/lib/dry/validation/evaluator.rb +224 -0
- data/lib/dry/validation/extensions/hints.rb +67 -0
- data/lib/dry/validation/extensions/monads.rb +24 -8
- 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 +44 -0
- data/lib/dry/validation/macro.rb +38 -0
- data/lib/dry/validation/macros.rb +104 -0
- data/lib/dry/validation/message.rb +80 -80
- data/lib/dry/validation/message_set.rb +80 -105
- data/lib/dry/validation/messages/resolver.rb +131 -0
- data/lib/dry/validation/result.rb +183 -41
- data/lib/dry/validation/rule.rb +135 -0
- data/lib/dry/validation/schema_ext.rb +19 -0
- data/lib/dry/validation/values.rb +104 -0
- data/lib/dry/validation/version.rb +3 -1
- data/lib/dry/validation.rb +45 -28
- data/lib/dry-validation.rb +3 -1
- metadata +46 -344
- data/.codeclimate.yml +0 -17
- data/.gitignore +0 -9
- data/.rspec +0 -3
- data/.travis.yml +0 -29
- data/CONTRIBUTING.md +0 -31
- data/Gemfile +0 -25
- data/Rakefile +0 -22
- data/benchmarks/benchmark_form_invalid.rb +0 -64
- data/benchmarks/benchmark_form_valid.rb +0 -64
- data/benchmarks/benchmark_schema_invalid_huge.rb +0 -52
- data/benchmarks/profile_schema_call_invalid.rb +0 -20
- data/benchmarks/profile_schema_call_valid.rb +0 -20
- data/benchmarks/profile_schema_definition.rb +0 -14
- data/benchmarks/profile_schema_huge_invalid.rb +0 -30
- data/benchmarks/profile_schema_messages_invalid.rb +0 -20
- data/benchmarks/suite.rb +0 -5
- data/examples/basic.rb +0 -15
- data/examples/each.rb +0 -14
- data/examples/json.rb +0 -12
- data/examples/multiple.rb +0 -27
- data/examples/nested.rb +0 -22
- data/examples/params.rb +0 -11
- data/lib/dry/validation/compat/form.rb +0 -67
- data/lib/dry/validation/deprecations.rb +0 -24
- data/lib/dry/validation/executor.rb +0 -91
- data/lib/dry/validation/extensions/struct.rb +0 -32
- data/lib/dry/validation/extensions.rb +0 -7
- data/lib/dry/validation/input_processor_compiler/json.rb +0 -45
- data/lib/dry/validation/input_processor_compiler/params.rb +0 -49
- data/lib/dry/validation/input_processor_compiler/sanitizer.rb +0 -47
- data/lib/dry/validation/input_processor_compiler.rb +0 -137
- data/lib/dry/validation/message_compiler/visitor_opts.rb +0 -37
- data/lib/dry/validation/message_compiler.rb +0 -188
- data/lib/dry/validation/messages/abstract.rb +0 -119
- data/lib/dry/validation/messages/i18n.rb +0 -47
- data/lib/dry/validation/messages/namespaced.rb +0 -39
- data/lib/dry/validation/messages/yaml.rb +0 -61
- data/lib/dry/validation/messages.rb +0 -14
- data/lib/dry/validation/predicate_registry.rb +0 -115
- data/lib/dry/validation/predicates.rb +0 -19
- data/lib/dry/validation/schema/check.rb +0 -37
- data/lib/dry/validation/schema/class_interface.rb +0 -190
- data/lib/dry/validation/schema/deprecated.rb +0 -30
- data/lib/dry/validation/schema/dsl.rb +0 -118
- data/lib/dry/validation/schema/form.rb +0 -9
- data/lib/dry/validation/schema/json.rb +0 -21
- data/lib/dry/validation/schema/key.rb +0 -71
- data/lib/dry/validation/schema/params.rb +0 -22
- data/lib/dry/validation/schema/rule.rb +0 -202
- data/lib/dry/validation/schema/value.rb +0 -211
- data/lib/dry/validation/schema.rb +0 -126
- data/lib/dry/validation/schema_compiler.rb +0 -81
- data/lib/dry/validation/template.rb +0 -66
- data/lib/dry/validation/type_specs.rb +0 -70
- data/log/.gitkeep +0 -0
- data/spec/extensions/monads/result_spec.rb +0 -40
- data/spec/extensions/struct/schema_spec.rb +0 -32
- data/spec/fixtures/locales/en.yml +0 -8
- data/spec/fixtures/locales/pl.yml +0 -22
- data/spec/integration/custom_error_messages_spec.rb +0 -54
- data/spec/integration/custom_predicates_spec.rb +0 -228
- data/spec/integration/hints_spec.rb +0 -170
- data/spec/integration/injecting_rules_spec.rb +0 -30
- data/spec/integration/json/defining_base_schema_spec.rb +0 -41
- data/spec/integration/localized_error_messages_spec.rb +0 -72
- data/spec/integration/message_compiler_spec.rb +0 -405
- data/spec/integration/messages/i18n_spec.rb +0 -104
- data/spec/integration/optional_keys_spec.rb +0 -28
- data/spec/integration/params/predicates/array_spec.rb +0 -287
- data/spec/integration/params/predicates/empty_spec.rb +0 -263
- data/spec/integration/params/predicates/eql_spec.rb +0 -327
- data/spec/integration/params/predicates/even_spec.rb +0 -455
- data/spec/integration/params/predicates/excluded_from_spec.rb +0 -455
- data/spec/integration/params/predicates/excludes_spec.rb +0 -391
- data/spec/integration/params/predicates/false_spec.rb +0 -455
- data/spec/integration/params/predicates/filled_spec.rb +0 -467
- data/spec/integration/params/predicates/format_spec.rb +0 -454
- data/spec/integration/params/predicates/gt_spec.rb +0 -519
- data/spec/integration/params/predicates/gteq_spec.rb +0 -519
- data/spec/integration/params/predicates/included_in_spec.rb +0 -455
- data/spec/integration/params/predicates/includes_spec.rb +0 -391
- data/spec/integration/params/predicates/key_spec.rb +0 -67
- data/spec/integration/params/predicates/lt_spec.rb +0 -519
- data/spec/integration/params/predicates/lteq_spec.rb +0 -519
- data/spec/integration/params/predicates/max_size_spec.rb +0 -391
- data/spec/integration/params/predicates/min_size_spec.rb +0 -391
- data/spec/integration/params/predicates/none_spec.rb +0 -265
- data/spec/integration/params/predicates/not_eql_spec.rb +0 -327
- data/spec/integration/params/predicates/odd_spec.rb +0 -455
- data/spec/integration/params/predicates/size/fixed_spec.rb +0 -393
- data/spec/integration/params/predicates/size/range_spec.rb +0 -396
- data/spec/integration/params/predicates/true_spec.rb +0 -455
- data/spec/integration/params/predicates/type_spec.rb +0 -391
- data/spec/integration/result_spec.rb +0 -81
- data/spec/integration/schema/array_schema_spec.rb +0 -59
- data/spec/integration/schema/check_rules_spec.rb +0 -119
- data/spec/integration/schema/check_with_nested_el_spec.rb +0 -37
- data/spec/integration/schema/check_with_nth_el_spec.rb +0 -25
- data/spec/integration/schema/default_settings_spec.rb +0 -11
- data/spec/integration/schema/defining_base_schema_spec.rb +0 -41
- data/spec/integration/schema/dynamic_predicate_args_spec.rb +0 -43
- data/spec/integration/schema/each_with_set_spec.rb +0 -70
- data/spec/integration/schema/extending_dsl_spec.rb +0 -27
- data/spec/integration/schema/form_spec.rb +0 -236
- data/spec/integration/schema/hash_schema_spec.rb +0 -47
- data/spec/integration/schema/inheriting_schema_spec.rb +0 -31
- data/spec/integration/schema/input_processor_spec.rb +0 -46
- data/spec/integration/schema/json/explicit_types_spec.rb +0 -157
- data/spec/integration/schema/json_spec.rb +0 -163
- data/spec/integration/schema/macros/confirmation_spec.rb +0 -35
- data/spec/integration/schema/macros/each_spec.rb +0 -268
- data/spec/integration/schema/macros/filled_spec.rb +0 -87
- data/spec/integration/schema/macros/input_spec.rb +0 -139
- data/spec/integration/schema/macros/maybe_spec.rb +0 -99
- data/spec/integration/schema/macros/rule_spec.rb +0 -75
- data/spec/integration/schema/macros/value_spec.rb +0 -119
- data/spec/integration/schema/macros/when_spec.rb +0 -62
- data/spec/integration/schema/nested_schemas_spec.rb +0 -236
- data/spec/integration/schema/nested_values_spec.rb +0 -46
- data/spec/integration/schema/not_spec.rb +0 -34
- data/spec/integration/schema/numbers_spec.rb +0 -19
- data/spec/integration/schema/option_with_default_spec.rb +0 -64
- data/spec/integration/schema/or_spec.rb +0 -87
- data/spec/integration/schema/params/defining_base_schema_spec.rb +0 -41
- data/spec/integration/schema/params/explicit_types_spec.rb +0 -195
- data/spec/integration/schema/params_spec.rb +0 -234
- data/spec/integration/schema/predicate_verification_spec.rb +0 -9
- data/spec/integration/schema/predicates/array_spec.rb +0 -295
- data/spec/integration/schema/predicates/custom_spec.rb +0 -103
- data/spec/integration/schema/predicates/empty_spec.rb +0 -263
- data/spec/integration/schema/predicates/eql_spec.rb +0 -327
- data/spec/integration/schema/predicates/even_spec.rb +0 -455
- data/spec/integration/schema/predicates/excluded_from/array_spec.rb +0 -459
- data/spec/integration/schema/predicates/excluded_from/range_spec.rb +0 -459
- data/spec/integration/schema/predicates/excludes_spec.rb +0 -391
- data/spec/integration/schema/predicates/filled_spec.rb +0 -467
- data/spec/integration/schema/predicates/format_spec.rb +0 -455
- data/spec/integration/schema/predicates/gt_spec.rb +0 -519
- data/spec/integration/schema/predicates/gteq_spec.rb +0 -519
- data/spec/integration/schema/predicates/hash_spec.rb +0 -69
- data/spec/integration/schema/predicates/included_in/array_spec.rb +0 -459
- data/spec/integration/schema/predicates/included_in/range_spec.rb +0 -459
- data/spec/integration/schema/predicates/includes_spec.rb +0 -391
- data/spec/integration/schema/predicates/key_spec.rb +0 -88
- data/spec/integration/schema/predicates/lt_spec.rb +0 -520
- data/spec/integration/schema/predicates/lteq_spec.rb +0 -519
- data/spec/integration/schema/predicates/max_size_spec.rb +0 -391
- data/spec/integration/schema/predicates/min_size_spec.rb +0 -391
- data/spec/integration/schema/predicates/none_spec.rb +0 -265
- data/spec/integration/schema/predicates/not_eql_spec.rb +0 -391
- data/spec/integration/schema/predicates/odd_spec.rb +0 -455
- data/spec/integration/schema/predicates/size/fixed_spec.rb +0 -398
- data/spec/integration/schema/predicates/size/range_spec.rb +0 -395
- data/spec/integration/schema/predicates/type_spec.rb +0 -413
- data/spec/integration/schema/reusing_schema_spec.rb +0 -33
- data/spec/integration/schema/using_types_spec.rb +0 -135
- data/spec/integration/schema/validate_spec.rb +0 -120
- data/spec/integration/schema/xor_spec.rb +0 -35
- data/spec/integration/schema_builders_spec.rb +0 -17
- data/spec/integration/schema_spec.rb +0 -173
- data/spec/shared/message_compiler.rb +0 -11
- data/spec/shared/predicate_helper.rb +0 -15
- data/spec/shared/rule_compiler.rb +0 -8
- data/spec/spec_helper.rb +0 -62
- data/spec/support/define_struct.rb +0 -25
- data/spec/support/matchers.rb +0 -38
- data/spec/support/mutant.rb +0 -9
- data/spec/support/predicates_integration.rb +0 -7
- data/spec/unit/input_processor_compiler/json_spec.rb +0 -283
- data/spec/unit/input_processor_compiler/params_spec.rb +0 -328
- data/spec/unit/message_compiler/visit_failure_spec.rb +0 -38
- data/spec/unit/message_compiler/visit_spec.rb +0 -16
- data/spec/unit/message_compiler_spec.rb +0 -7
- data/spec/unit/predicate_registry_spec.rb +0 -34
- data/spec/unit/schema/key_spec.rb +0 -38
- data/spec/unit/schema/rule_spec.rb +0 -42
- data/spec/unit/schema/value_spec.rb +0 -131
- data/spec/unit/schema_spec.rb +0 -35
@@ -1,70 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Validation
|
3
|
-
module TypeSpecs
|
4
|
-
def self.extended(klass)
|
5
|
-
super
|
6
|
-
klass.class_eval do
|
7
|
-
setting :input_processor, :noop
|
8
|
-
setting :hash_type, :weak
|
9
|
-
setting :type_map, {}
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def build_type_map(type_specs, category = config.input_processor)
|
14
|
-
if type_specs.is_a?(Array)
|
15
|
-
build_array_type(type_specs[0], category)
|
16
|
-
else
|
17
|
-
type_specs.reduce({}) { |res, (name, spec)|
|
18
|
-
res.update(name => resolve_spec(spec, category))
|
19
|
-
}
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def build_hash_type(spec = type_map)
|
24
|
-
lookup_type("hash", config.input_processor)
|
25
|
-
.public_send(config.hash_type, spec)
|
26
|
-
end
|
27
|
-
|
28
|
-
def build_array_type(spec, category)
|
29
|
-
member_schema = build_type_map(spec, category)
|
30
|
-
member_type = lookup_type("hash", category)
|
31
|
-
.public_send(config.hash_type, member_schema)
|
32
|
-
|
33
|
-
lookup_type("array", category).of(member_type)
|
34
|
-
end
|
35
|
-
|
36
|
-
def build_sum_type(spec, category)
|
37
|
-
spec
|
38
|
-
.map { |id| id.is_a?(Symbol) ? lookup_type(id, category) : id }
|
39
|
-
.reduce(:|)
|
40
|
-
end
|
41
|
-
|
42
|
-
def resolve_spec(spec, category)
|
43
|
-
case spec
|
44
|
-
when Symbol
|
45
|
-
lookup_type(spec, category)
|
46
|
-
when Hash
|
47
|
-
build_hash_type(spec)
|
48
|
-
when Array
|
49
|
-
if spec.size == 1
|
50
|
-
if spec[0].is_a?(Hash)
|
51
|
-
build_array_type(spec[0], category)
|
52
|
-
else
|
53
|
-
array_member = lookup_type(spec[0], category)
|
54
|
-
lookup_type("array", category).of(array_member)
|
55
|
-
end
|
56
|
-
else
|
57
|
-
build_sum_type(spec, category)
|
58
|
-
end
|
59
|
-
else
|
60
|
-
spec
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def lookup_type(name, category)
|
65
|
-
id = "#{category}.#{name}"
|
66
|
-
Types.type_keys.include?(id) ? Types[id] : Types[name.to_s]
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
data/log/.gitkeep
DELETED
File without changes
|
@@ -1,40 +0,0 @@
|
|
1
|
-
RSpec.describe Dry::Validation::Result do
|
2
|
-
before { Dry::Validation.load_extensions(:monads) }
|
3
|
-
|
4
|
-
let(:schema) { Dry::Validation.Schema { required(:name).filled(:str?, size?: 2..4) } }
|
5
|
-
|
6
|
-
context 'with valid input' do
|
7
|
-
let(:input) { { name: 'Jane' } }
|
8
|
-
|
9
|
-
describe '#to_monad' do
|
10
|
-
it 'returns a Success value' do
|
11
|
-
monad = result.to_monad
|
12
|
-
|
13
|
-
expect(monad).to be_a Dry::Monads::Result
|
14
|
-
expect(monad).to be_a_success
|
15
|
-
expect(monad.value!).to eql(name: 'Jane')
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'with invalid input' do
|
21
|
-
let(:input) { { name: '' } }
|
22
|
-
|
23
|
-
describe '#to_monad' do
|
24
|
-
it 'returns a Failure value' do
|
25
|
-
monad = result.to_monad
|
26
|
-
|
27
|
-
expect(monad).to be_a_failure
|
28
|
-
expect(monad.failure).to eql(name: ['must be filled', 'length must be within 2 - 4'])
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'returns full messages' do
|
32
|
-
monad = result.to_monad(full: true)
|
33
|
-
|
34
|
-
expect(monad).to be_a Dry::Monads::Result
|
35
|
-
expect(monad).to be_a_failure
|
36
|
-
expect(monad.failure).to eql(name: ['name must be filled', 'name length must be within 2 - 4'])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
RSpec.describe Dry::Validation::Schema, 'defining schema using dry struct' do
|
2
|
-
before do
|
3
|
-
Dry::Validation.load_extensions(:struct)
|
4
|
-
end
|
5
|
-
|
6
|
-
subject(:schema) do
|
7
|
-
Dry::Validation.Schema do
|
8
|
-
required(:person).filled(Test::Person)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
before do
|
13
|
-
class Test::Name < Dry::Struct::Value
|
14
|
-
attribute :given_name, Dry::Types['strict.string']
|
15
|
-
attribute :family_name, Dry::Types['strict.string']
|
16
|
-
end
|
17
|
-
|
18
|
-
class Test::Person < Dry::Struct::Value
|
19
|
-
attribute :name, Test::Name
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'handles nested structs' do
|
24
|
-
expect(schema.call(person: { name: { given_name: 'Tim', family_name: 'Cooper' } })).to be_success
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'fails when input is not valid' do
|
28
|
-
expect(schema.call(person: { name: { given_name: 'Tim' } }).messages).to eq(
|
29
|
-
person: { name: { family_name: ['is missing', 'must be String'] } }
|
30
|
-
)
|
31
|
-
end
|
32
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
pl:
|
2
|
-
errors:
|
3
|
-
filled?: "nie może być pusty"
|
4
|
-
size?:
|
5
|
-
arg:
|
6
|
-
default: "wielkość musi być równa %{size}"
|
7
|
-
range: "wielkość musi być między %{size_left} a %{size_right}"
|
8
|
-
value:
|
9
|
-
string:
|
10
|
-
arg:
|
11
|
-
default: "wielkość musi być równa %{size}"
|
12
|
-
rules:
|
13
|
-
email:
|
14
|
-
filled?: "Proszę podać adres email"
|
15
|
-
user:
|
16
|
-
rules:
|
17
|
-
email:
|
18
|
-
filled?: "Hej user! Dawaj ten email no!"
|
19
|
-
|
20
|
-
rules:
|
21
|
-
email:
|
22
|
-
'Adres email'
|
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'dry/validation/messages/i18n'
|
2
|
-
|
3
|
-
RSpec.describe Dry::Validation do
|
4
|
-
shared_context 'schema with customized messages' do
|
5
|
-
describe '#messages' do
|
6
|
-
it 'returns compiled error messages' do
|
7
|
-
expect(schema.(email: '', age: 12).messages).to eql(
|
8
|
-
email: ['Please provide your email'], age: ['12 must be greater than 18']
|
9
|
-
)
|
10
|
-
|
11
|
-
expect(schema.(email: '', age: 14).messages).to eql(
|
12
|
-
email: ['Please provide your email'], age: ['14 must be greater than 18']
|
13
|
-
)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'yaml' do
|
19
|
-
subject(:schema) do
|
20
|
-
Dry::Validation.Schema do
|
21
|
-
configure do
|
22
|
-
config.messages_file = SPEC_ROOT.join('fixtures/locales/en.yml')
|
23
|
-
end
|
24
|
-
|
25
|
-
required(:email).filled
|
26
|
-
required(:age).value(gt?: 18)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
include_context 'schema with customized messages'
|
31
|
-
end
|
32
|
-
|
33
|
-
context 'i18n' do
|
34
|
-
context 'with custom messages set globally' do
|
35
|
-
before do
|
36
|
-
I18n.load_path << SPEC_ROOT.join('fixtures/locales/en.yml')
|
37
|
-
I18n.backend.load_translations
|
38
|
-
end
|
39
|
-
|
40
|
-
subject(:schema) do
|
41
|
-
Dry::Validation.Schema do
|
42
|
-
configure do
|
43
|
-
config.messages = :i18n
|
44
|
-
end
|
45
|
-
|
46
|
-
required(:email).filled
|
47
|
-
required(:age).value(gt?: 18)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
include_context 'schema with customized messages'
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,228 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
RSpec.describe Dry::Validation do
|
3
|
-
shared_context 'uses custom predicates' do
|
4
|
-
it 'uses provided custom predicates' do
|
5
|
-
expect(schema.(email: 'jane@doe')).to be_success
|
6
|
-
|
7
|
-
expect(schema.(email: nil).messages).to eql(
|
8
|
-
email: ['must be filled', 'must be a valid email']
|
9
|
-
)
|
10
|
-
|
11
|
-
expect(schema.(email: 'jane').messages).to eql(
|
12
|
-
email: ['must be a valid email']
|
13
|
-
)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
let(:base_class) do
|
18
|
-
Class.new(Dry::Validation::Schema) do
|
19
|
-
def self.messages
|
20
|
-
Dry::Validation::Messages.default.merge(
|
21
|
-
en: { errors: { email?: 'must be a valid email' } }
|
22
|
-
)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe 'defining schema with custom predicates container' do
|
28
|
-
before do
|
29
|
-
module Test
|
30
|
-
module Predicates
|
31
|
-
include Dry::Logic::Predicates
|
32
|
-
|
33
|
-
def self.email?(input)
|
34
|
-
input.include?('@') # for the lols
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'when configured globally' do
|
41
|
-
subject(:schema) do
|
42
|
-
Dry::Validation.Schema(base_class) do
|
43
|
-
required(:email) { filled? & email? }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
before do
|
48
|
-
Dry::Validation::Schema.predicates(Test::Predicates)
|
49
|
-
end
|
50
|
-
|
51
|
-
after do
|
52
|
-
# HACK: reset global predicates configuration
|
53
|
-
Dry::Validation::Schema.configure do |config|
|
54
|
-
config.predicates = Dry::Logic::Predicates
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
include_context 'uses custom predicates'
|
59
|
-
end
|
60
|
-
|
61
|
-
context 'when configured locally' do
|
62
|
-
subject(:schema) do
|
63
|
-
Dry::Validation.Schema(base_class) do
|
64
|
-
configure do
|
65
|
-
predicates(Test::Predicates)
|
66
|
-
end
|
67
|
-
|
68
|
-
required(:email) { filled? & email? }
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
include_context 'uses custom predicates'
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe 'defining schema with custom predicate methods' do
|
77
|
-
subject(:schema) do
|
78
|
-
Dry::Validation.Schema(base_class) do
|
79
|
-
configure do
|
80
|
-
def email?(value)
|
81
|
-
value.include?('@')
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
required(:email) { filled? & email? }
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
include_context 'uses custom predicates'
|
90
|
-
end
|
91
|
-
|
92
|
-
describe 'custom predicate which requires an arbitrary dependency' do
|
93
|
-
subject(:schema) do
|
94
|
-
Dry::Validation.Schema(base_class) do
|
95
|
-
configure do
|
96
|
-
option :email_check
|
97
|
-
|
98
|
-
def email?(value)
|
99
|
-
email_check.(value)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
required(:email).filled(:email?)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'uses injected dependency for the custom predicate' do
|
108
|
-
email_check = -> input { input.include?('@') }
|
109
|
-
|
110
|
-
expect(schema.with(email_check: email_check).(email: 'foo').messages).to eql(
|
111
|
-
email: ['must be a valid email']
|
112
|
-
)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'raises an error when message is missing' do
|
117
|
-
schema = Dry::Validation.Schema do
|
118
|
-
configure do
|
119
|
-
def email?(value)
|
120
|
-
false
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
required(:email).filled(:email?)
|
125
|
-
end
|
126
|
-
|
127
|
-
expect { schema.(email: 'foo').messages }.to raise_error(
|
128
|
-
Dry::Validation::MissingMessageError, /email/
|
129
|
-
)
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'works with custom predicate args' do
|
133
|
-
schema = Dry::Validation.Schema do
|
134
|
-
configure do
|
135
|
-
def self.messages
|
136
|
-
Dry::Validation::Messages.default.merge(
|
137
|
-
en: { errors: { fav_number?: 'must be %{expected}' } }
|
138
|
-
)
|
139
|
-
end
|
140
|
-
def fav_number?(expected, current)
|
141
|
-
current == expected
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
required(:foo) { fav_number?(23) }
|
146
|
-
end
|
147
|
-
|
148
|
-
expect(schema.(foo: 20).messages).to eql(
|
149
|
-
foo: ['must be 23']
|
150
|
-
)
|
151
|
-
|
152
|
-
end
|
153
|
-
|
154
|
-
it 'works when no predicate args' do
|
155
|
-
schema = Dry::Validation.Schema do
|
156
|
-
configure do
|
157
|
-
def self.messages
|
158
|
-
Dry::Validation::Messages.default.merge(
|
159
|
-
en: { errors: { with_no_args?: 'is always false' } }
|
160
|
-
)
|
161
|
-
end
|
162
|
-
|
163
|
-
def with_no_args?
|
164
|
-
false
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
required(:email).filled(:with_no_args?)
|
169
|
-
end
|
170
|
-
|
171
|
-
expect(schema.(email: 'foo').messages).to eql(
|
172
|
-
email: ['is always false']
|
173
|
-
)
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'works with nested schemas' do
|
177
|
-
schema = Dry::Validation.Schema do
|
178
|
-
configure do
|
179
|
-
def ok?(_value)
|
180
|
-
true
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
required(:foo).schema do
|
185
|
-
required(:bar).value(:ok?)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
expect(schema.(foo: { bar: "1" })).to be_success
|
190
|
-
end
|
191
|
-
|
192
|
-
it 'works with interpolation of messages' do
|
193
|
-
schema = Dry::Validation.Schema do
|
194
|
-
configure do
|
195
|
-
option :categories, []
|
196
|
-
|
197
|
-
def self.messages
|
198
|
-
Dry::Validation::Messages.default.merge(
|
199
|
-
en: {
|
200
|
-
errors: {
|
201
|
-
valid_category?: 'must be one of the categories: %{categories}'
|
202
|
-
}
|
203
|
-
},
|
204
|
-
pl: {
|
205
|
-
errors: {
|
206
|
-
valid_category?: 'musi być jedną z: %{categories}'
|
207
|
-
}
|
208
|
-
}
|
209
|
-
)
|
210
|
-
end
|
211
|
-
|
212
|
-
def valid_category?(categories, value)
|
213
|
-
categories.include?(value)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
required(:category).filled(valid_category?: categories)
|
218
|
-
end.with(categories: %w(foo bar))
|
219
|
-
|
220
|
-
expect(schema.(category: 'baz').messages).to eql(
|
221
|
-
category: ['must be one of the categories: foo, bar']
|
222
|
-
)
|
223
|
-
|
224
|
-
expect(schema.(category: 'baz').messages(locale: :pl)).to eql(
|
225
|
-
category: ['musi być jedną z: foo, bar']
|
226
|
-
)
|
227
|
-
end
|
228
|
-
end
|
@@ -1,170 +0,0 @@
|
|
1
|
-
require 'dry/validation/messages/i18n'
|
2
|
-
|
3
|
-
RSpec.describe 'Validation hints' do
|
4
|
-
shared_context '#messages' do
|
5
|
-
it 'provides hints for additional rules that were not checked' do
|
6
|
-
expect(schema.(age: '17').messages).to eql(
|
7
|
-
age: ['must be an integer', 'must be greater than 18']
|
8
|
-
)
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'skips type-check rules' do
|
12
|
-
expect(schema.(age: 17).messages).to eql(
|
13
|
-
age: ['must be greater than 18']
|
14
|
-
)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'with yaml messages' do
|
19
|
-
subject(:schema) do
|
20
|
-
Dry::Validation.Schema do
|
21
|
-
required(:age).maybe(:int?, gt?: 18)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
include_context '#messages'
|
26
|
-
end
|
27
|
-
|
28
|
-
context 'with i18n messages' do
|
29
|
-
subject(:schema) do
|
30
|
-
Dry::Validation.Schema do
|
31
|
-
configure { configure { |c| c.messages = :i18n } }
|
32
|
-
|
33
|
-
required(:age).maybe(:int?, gt?: 18)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
include_context '#messages'
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'when type expectation is specified' do
|
41
|
-
subject(:schema) do
|
42
|
-
Dry::Validation.Schema do
|
43
|
-
required(:email).filled
|
44
|
-
required(:name).filled(:str?, size?: 5..25)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'infers message for specific type' do
|
49
|
-
expect(schema.(email: 'jane@doe', name: 'HN').messages).to eql(
|
50
|
-
name: ['length must be within 5 - 25']
|
51
|
-
)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'when predicate failed and there is a corresponding hint generated' do
|
56
|
-
subject(:schema) do
|
57
|
-
Dry::Validation.Schema do
|
58
|
-
required(:age).value(lt?: 23)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'provides only failure error message' do
|
63
|
-
result = schema.call(age: 23)
|
64
|
-
expect(result.messages).to eql(age: ['must be less than 23'])
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'with a nested schema with same rule names' do
|
69
|
-
subject(:schema) do
|
70
|
-
Dry::Validation.Schema do
|
71
|
-
required(:code).filled(:str?, eql?: 'foo')
|
72
|
-
|
73
|
-
required(:nested).schema do
|
74
|
-
required(:code).filled(:str?, eql?: 'bar')
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'provides error messages' do
|
80
|
-
result = schema.call(code: 'x', nested: { code: 'y' })
|
81
|
-
|
82
|
-
expect(result.messages).to eql(
|
83
|
-
code: ['must be equal to foo'],
|
84
|
-
nested: {
|
85
|
-
code: ['must be equal to bar']
|
86
|
-
}
|
87
|
-
)
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'provides hints' do
|
91
|
-
result = schema.call(code: '', nested: { code: '' })
|
92
|
-
|
93
|
-
expect(result.messages).to eql(
|
94
|
-
code: ['must be filled', 'must be equal to foo'],
|
95
|
-
nested: {
|
96
|
-
code: ['must be filled', 'must be equal to bar']
|
97
|
-
}
|
98
|
-
)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
context 'with an each rule' do
|
103
|
-
subject(:schema) do
|
104
|
-
Dry::Validation.Schema do
|
105
|
-
required(:nums).each(:int?, gt?: 0)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'provides hints for each element' do
|
110
|
-
expect(schema.(nums: [1, 'foo', 0]).messages).to eql(
|
111
|
-
nums: {
|
112
|
-
1 => ['must be an integer', 'must be greater than 0'],
|
113
|
-
2 => ['must be greater than 0']
|
114
|
-
}
|
115
|
-
)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
context 'with a format? predicate' do
|
120
|
-
subject(:schema) do
|
121
|
-
Dry::Validation.Schema do
|
122
|
-
required(:name).value(size?: 2, format?: /xy/)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'skips hints' do
|
127
|
-
expect(schema.(name: 'x').messages[:name]).to_not include('is in invalid format')
|
128
|
-
expect(schema.(name: 'ab').messages[:name]).to include('is in invalid format')
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
context 'when the message uses input value' do
|
133
|
-
subject(:schema) do
|
134
|
-
Dry::Validation.Schema do
|
135
|
-
configure do
|
136
|
-
def self.messages
|
137
|
-
Messages.default.merge(
|
138
|
-
en: {
|
139
|
-
errors: {
|
140
|
-
blue?: {
|
141
|
-
failure: '%{value} is not equal to blue',
|
142
|
-
hint: 'must be equal to blue'
|
143
|
-
}
|
144
|
-
}
|
145
|
-
}
|
146
|
-
)
|
147
|
-
end
|
148
|
-
|
149
|
-
def blue?(value)
|
150
|
-
value == 'blue'
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
required(:pill).filled(:blue?)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'provides a correct failure message' do
|
159
|
-
expect(schema.(pill: 'red').messages).to eql(
|
160
|
-
pill: ['red is not equal to blue']
|
161
|
-
)
|
162
|
-
end
|
163
|
-
|
164
|
-
it 'provides a correct hint' do
|
165
|
-
expect(schema.(pill: nil).messages).to eql(
|
166
|
-
pill: ['must be filled', 'must be equal to blue']
|
167
|
-
)
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
RSpec.describe 'Schema / Injecting Rules' do
|
2
|
-
subject(:schema) do
|
3
|
-
Dry::Validation.Schema(rules: other.class.rules) do
|
4
|
-
required(:email).maybe
|
5
|
-
|
6
|
-
rule(:email) { value(:login).true? > value(:email).filled? }
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
let(:other) do
|
11
|
-
Dry::Validation.Schema do
|
12
|
-
required(:login) { |value| value.bool? }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'appends rules from another schema' do
|
17
|
-
expect(schema.(login: true, email: 'jane@doe')).to be_success
|
18
|
-
expect(schema.(login: false, email: nil)).to be_success
|
19
|
-
expect(schema.(login: true, email: nil)).to_not be_success
|
20
|
-
expect(schema.(login: nil, email: 'jane@doe')).to_not be_success
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'keeps the original schema rules intact' do
|
24
|
-
expect(other.class.rules.size).to eq(1)
|
25
|
-
|
26
|
-
schema.(login: true, email: 'jane@doe')
|
27
|
-
|
28
|
-
expect(other.class.rules.size).to eq(1)
|
29
|
-
end
|
30
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'dry/validation/messages/i18n'
|
2
|
-
require 'i18n'
|
3
|
-
|
4
|
-
RSpec.describe 'Defining base schema class' do
|
5
|
-
subject(:schema) do
|
6
|
-
Dry::Validation.JSON(BaseSchema) do
|
7
|
-
required(:email).filled(:email?)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
before do
|
12
|
-
class BaseSchema < Dry::Validation::Schema
|
13
|
-
configure do |config|
|
14
|
-
config.messages_file = SPEC_ROOT.join('fixtures/locales/en.yml')
|
15
|
-
config.messages = :i18n
|
16
|
-
end
|
17
|
-
|
18
|
-
def email?(value)
|
19
|
-
true
|
20
|
-
end
|
21
|
-
|
22
|
-
define! do
|
23
|
-
required(:name).filled
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
after do
|
29
|
-
Object.send(:remove_const, :BaseSchema)
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'inherits predicates' do
|
33
|
-
expect(schema).to respond_to(:email?)
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'inherits rules' do
|
37
|
-
expect(schema.('name' => '').messages).to eql(
|
38
|
-
name: ['must be filled'], email: ['is missing', 'must be an email']
|
39
|
-
)
|
40
|
-
end
|
41
|
-
end
|