dry-schema 1.4.1 → 1.5.2
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 +210 -73
- data/LICENSE +1 -1
- data/README.md +4 -6
- data/config/errors.yml +4 -0
- data/dry-schema.gemspec +46 -0
- data/lib/dry-schema.rb +1 -1
- data/lib/dry/schema.rb +20 -7
- data/lib/dry/schema/compiler.rb +5 -5
- data/lib/dry/schema/config.rb +15 -6
- data/lib/dry/schema/constants.rb +16 -7
- data/lib/dry/schema/dsl.rb +89 -31
- data/lib/dry/schema/extensions.rb +10 -2
- data/lib/dry/schema/extensions/hints.rb +15 -8
- data/lib/dry/schema/extensions/hints/message_compiler_methods.rb +2 -2
- data/lib/dry/schema/extensions/hints/message_set_methods.rb +0 -47
- data/lib/dry/schema/extensions/info.rb +27 -0
- data/lib/dry/schema/extensions/info/schema_compiler.rb +105 -0
- data/lib/dry/schema/extensions/monads.rb +1 -1
- data/lib/dry/schema/extensions/struct.rb +32 -0
- data/lib/dry/schema/json.rb +1 -1
- data/lib/dry/schema/key.rb +20 -5
- data/lib/dry/schema/key_coercer.rb +4 -4
- data/lib/dry/schema/key_map.rb +9 -4
- data/lib/dry/schema/key_validator.rb +67 -0
- data/lib/dry/schema/macros.rb +8 -8
- data/lib/dry/schema/macros/array.rb +17 -4
- data/lib/dry/schema/macros/core.rb +11 -6
- data/lib/dry/schema/macros/dsl.rb +44 -23
- data/lib/dry/schema/macros/each.rb +4 -4
- data/lib/dry/schema/macros/filled.rb +5 -5
- data/lib/dry/schema/macros/hash.rb +21 -3
- data/lib/dry/schema/macros/key.rb +10 -9
- data/lib/dry/schema/macros/maybe.rb +4 -5
- data/lib/dry/schema/macros/optional.rb +1 -1
- data/lib/dry/schema/macros/required.rb +1 -1
- data/lib/dry/schema/macros/schema.rb +23 -2
- data/lib/dry/schema/macros/value.rb +34 -7
- data/lib/dry/schema/message.rb +35 -9
- data/lib/dry/schema/message/or.rb +18 -39
- data/lib/dry/schema/message/or/abstract.rb +28 -0
- data/lib/dry/schema/message/or/multi_path.rb +37 -0
- data/lib/dry/schema/message/or/single_path.rb +64 -0
- data/lib/dry/schema/message_compiler.rb +58 -22
- data/lib/dry/schema/message_compiler/visitor_opts.rb +2 -2
- data/lib/dry/schema/message_set.rb +26 -37
- data/lib/dry/schema/messages.rb +6 -6
- data/lib/dry/schema/messages/abstract.rb +54 -62
- data/lib/dry/schema/messages/i18n.rb +36 -10
- data/lib/dry/schema/messages/namespaced.rb +12 -2
- data/lib/dry/schema/messages/template.rb +19 -44
- data/lib/dry/schema/messages/yaml.rb +61 -14
- data/lib/dry/schema/params.rb +1 -1
- data/lib/dry/schema/path.rb +44 -5
- data/lib/dry/schema/predicate.rb +4 -2
- data/lib/dry/schema/predicate_inferrer.rb +4 -184
- data/lib/dry/schema/predicate_registry.rb +2 -2
- data/lib/dry/schema/primitive_inferrer.rb +16 -0
- data/lib/dry/schema/processor.rb +50 -29
- data/lib/dry/schema/processor_steps.rb +50 -27
- data/lib/dry/schema/result.rb +53 -6
- data/lib/dry/schema/rule_applier.rb +7 -7
- data/lib/dry/schema/step.rb +79 -0
- data/lib/dry/schema/trace.rb +5 -4
- data/lib/dry/schema/type_container.rb +3 -3
- data/lib/dry/schema/type_registry.rb +2 -2
- data/lib/dry/schema/types.rb +1 -1
- data/lib/dry/schema/value_coercer.rb +2 -2
- data/lib/dry/schema/version.rb +1 -1
- metadata +21 -7
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/schema/macros/value"
|
4
4
|
|
5
5
|
module Dry
|
6
6
|
module Schema
|
@@ -13,8 +13,13 @@ module Dry
|
|
13
13
|
def call(*args, &block)
|
14
14
|
super(*args, &nil) unless args.empty?
|
15
15
|
|
16
|
+
if args.size.equal?(1) && (op = args.first).is_a?(Dry::Logic::Operations::Abstract)
|
17
|
+
process_operation(op)
|
18
|
+
end
|
19
|
+
|
16
20
|
if block
|
17
21
|
schema = define(*args, &block)
|
22
|
+
import_steps(schema)
|
18
23
|
trace << schema.to_rule
|
19
24
|
end
|
20
25
|
|
@@ -23,9 +28,25 @@ module Dry
|
|
23
28
|
|
24
29
|
private
|
25
30
|
|
31
|
+
# @api private
|
32
|
+
def process_operation(op)
|
33
|
+
schemas = op.rules.select { |rule| rule.is_a?(Processor) }
|
34
|
+
|
35
|
+
hash_schema = hash_type.schema(
|
36
|
+
schemas.map(&:schema_dsl).map(&:types).reduce(:merge)
|
37
|
+
)
|
38
|
+
|
39
|
+
type(hash_schema)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @api private
|
43
|
+
def hash_type
|
44
|
+
schema_dsl.resolve_type(:hash)
|
45
|
+
end
|
46
|
+
|
26
47
|
# @api private
|
27
48
|
def define(*args, &block)
|
28
|
-
definition = schema_dsl.new(&block)
|
49
|
+
definition = schema_dsl.new(path: schema_dsl.path, &block)
|
29
50
|
schema = definition.call
|
30
51
|
type_schema =
|
31
52
|
if array_type?(parent_type)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/schema/path"
|
4
|
+
require "dry/schema/macros/dsl"
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module Schema
|
@@ -13,6 +14,8 @@ module Dry
|
|
13
14
|
def call(*predicates, **opts, &block)
|
14
15
|
schema = predicates.detect { |predicate| predicate.is_a?(Processor) }
|
15
16
|
|
17
|
+
type_spec = opts[:type_spec]
|
18
|
+
|
16
19
|
if schema
|
17
20
|
current_type = schema_dsl.types[name]
|
18
21
|
|
@@ -23,17 +26,32 @@ module Dry
|
|
23
26
|
schema.type_schema
|
24
27
|
end
|
25
28
|
|
26
|
-
|
29
|
+
import_steps(schema)
|
30
|
+
|
31
|
+
type(updated_type) unless custom_type? && !current_type.respond_to?(:of)
|
27
32
|
end
|
28
33
|
|
29
|
-
|
30
|
-
|
34
|
+
trace_opts = opts.reject { |key, _| key == :type_spec || key == :type_rule }
|
35
|
+
|
36
|
+
if (type_rule = opts[:type_rule])
|
37
|
+
trace.append(type_rule).evaluate(*predicates, **trace_opts)
|
38
|
+
trace.append(new(chain: false).instance_exec(&block)) if block
|
39
|
+
else
|
40
|
+
trace.evaluate(*predicates, **trace_opts)
|
41
|
+
|
42
|
+
if block && type_spec.equal?(:hash)
|
43
|
+
hash(&block)
|
44
|
+
elsif type_spec.is_a?(::Dry::Types::Type) && hash_type?(type_spec)
|
45
|
+
hash(type_spec)
|
46
|
+
elsif block
|
47
|
+
trace.append(new(chain: false).instance_exec(&block))
|
48
|
+
end
|
49
|
+
end
|
31
50
|
|
32
51
|
if trace.captures.empty?
|
33
|
-
raise ArgumentError,
|
52
|
+
raise ArgumentError, "wrong number of arguments (given 0, expected at least 1)"
|
34
53
|
end
|
35
54
|
|
36
|
-
type_spec = opts[:type_spec]
|
37
55
|
each(type_spec.type.member) if type_spec.respond_to?(:member)
|
38
56
|
|
39
57
|
self
|
@@ -44,12 +62,16 @@ module Dry
|
|
44
62
|
primitive_inferrer[type].eql?([::Array])
|
45
63
|
end
|
46
64
|
|
65
|
+
def hash_type?(type)
|
66
|
+
primitive_inferrer[type].eql?([::Hash])
|
67
|
+
end
|
68
|
+
|
47
69
|
# @api private
|
48
70
|
def build_array_type(array_type, member)
|
49
71
|
if array_type.respond_to?(:of)
|
50
72
|
array_type.of(member)
|
51
73
|
else
|
52
|
-
raise ArgumentError, <<~ERROR.split("\n").join(
|
74
|
+
raise ArgumentError, <<~ERROR.split("\n").join(" ")
|
53
75
|
Cannot define schema for a nominal array type.
|
54
76
|
Array types must be instances of Dry::Types::Array,
|
55
77
|
usually constructed with Types::Constructor(Array) { ... } or
|
@@ -58,6 +80,11 @@ module Dry
|
|
58
80
|
end
|
59
81
|
end
|
60
82
|
|
83
|
+
# @api private
|
84
|
+
def import_steps(schema)
|
85
|
+
schema_dsl.steps.import_callbacks(Path[[*path, name]], schema.steps)
|
86
|
+
end
|
87
|
+
|
61
88
|
# @api private
|
62
89
|
def respond_to_missing?(meth, include_private = false)
|
63
90
|
super || meth.to_s.end_with?(QUESTION_MARK)
|
data/lib/dry/schema/message.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "dry/initializer"
|
4
|
+
require "dry/equalizer"
|
5
5
|
|
6
|
-
require
|
7
|
-
require
|
6
|
+
require "dry/schema/path"
|
7
|
+
require "dry/schema/message/or"
|
8
8
|
|
9
9
|
module Dry
|
10
10
|
module Schema
|
@@ -52,9 +52,22 @@ module Dry
|
|
52
52
|
#
|
53
53
|
# @api public
|
54
54
|
def dump
|
55
|
-
@dump ||= meta.empty? ? text : {
|
55
|
+
@dump ||= meta.empty? ? text : {text: text, **meta}
|
56
|
+
end
|
57
|
+
alias_method :to_s, :dump
|
58
|
+
|
59
|
+
# Dump the message into a hash
|
60
|
+
#
|
61
|
+
# The hash will be deeply nested if the path's size is greater than 1
|
62
|
+
#
|
63
|
+
# @see Message#to_h
|
64
|
+
#
|
65
|
+
# @return [Hash]
|
66
|
+
#
|
67
|
+
# @api public
|
68
|
+
def to_h
|
69
|
+
@to_h ||= _path.to_h(dump)
|
56
70
|
end
|
57
|
-
alias to_s dump
|
58
71
|
|
59
72
|
# See if another message is the same
|
60
73
|
#
|
@@ -69,19 +82,32 @@ module Dry
|
|
69
82
|
other.is_a?(String) ? text == other : super
|
70
83
|
end
|
71
84
|
|
85
|
+
# @api private
|
86
|
+
def to_or(root)
|
87
|
+
clone = dup
|
88
|
+
clone.instance_variable_set("@path", path - root.to_a)
|
89
|
+
clone.instance_variable_set("@_path", nil)
|
90
|
+
clone
|
91
|
+
end
|
92
|
+
|
72
93
|
# See which message is higher in the hierarchy
|
73
94
|
#
|
74
95
|
# @api private
|
75
96
|
def <=>(other)
|
76
|
-
l_path =
|
77
|
-
r_path =
|
97
|
+
l_path = _path
|
98
|
+
r_path = other._path
|
78
99
|
|
79
100
|
unless l_path.same_root?(r_path)
|
80
|
-
raise ArgumentError,
|
101
|
+
raise ArgumentError, "Cannot compare messages from different root paths"
|
81
102
|
end
|
82
103
|
|
83
104
|
l_path <=> r_path
|
84
105
|
end
|
106
|
+
|
107
|
+
# @api private
|
108
|
+
def _path
|
109
|
+
@_path ||= Path[path]
|
110
|
+
end
|
85
111
|
end
|
86
112
|
end
|
87
113
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/schema/message/or/single_path"
|
4
|
+
require "dry/schema/message/or/multi_path"
|
4
5
|
|
5
6
|
module Dry
|
6
7
|
module Schema
|
@@ -8,45 +9,23 @@ module Dry
|
|
8
9
|
#
|
9
10
|
# @api public
|
10
11
|
class Message
|
11
|
-
|
12
|
-
#
|
13
|
-
# @api public
|
14
|
-
class Or
|
12
|
+
module Or
|
15
13
|
# @api private
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
@messages = messages
|
32
|
-
@path = left.path
|
33
|
-
end
|
34
|
-
|
35
|
-
# Dump a message into a string
|
36
|
-
#
|
37
|
-
# @see Message#dump
|
38
|
-
#
|
39
|
-
# @return [String]
|
40
|
-
#
|
41
|
-
# @api public
|
42
|
-
def dump
|
43
|
-
to_a.map(&:dump).join(" #{messages[:or][:text]} ")
|
44
|
-
end
|
45
|
-
alias to_s dump
|
46
|
-
|
47
|
-
# @api private
|
48
|
-
def to_a
|
49
|
-
[left, right]
|
14
|
+
def self.[](left, right, messages)
|
15
|
+
msgs = [left, right].flatten
|
16
|
+
paths = msgs.map(&:path)
|
17
|
+
|
18
|
+
if paths.uniq.size == 1
|
19
|
+
SinglePath.new(left, right, messages)
|
20
|
+
elsif right.is_a?(Array)
|
21
|
+
if left.is_a?(Array) && paths.uniq.size > 1
|
22
|
+
MultiPath.new(left, right)
|
23
|
+
else
|
24
|
+
right
|
25
|
+
end
|
26
|
+
else
|
27
|
+
msgs.max
|
28
|
+
end
|
50
29
|
end
|
51
30
|
end
|
52
31
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Schema
|
5
|
+
class Message
|
6
|
+
module Or
|
7
|
+
# A message type used by OR operations
|
8
|
+
#
|
9
|
+
# @abstract
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
class Abstract
|
13
|
+
# @api private
|
14
|
+
attr_reader :left
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
attr_reader :right
|
18
|
+
|
19
|
+
# @api private
|
20
|
+
def initialize(left, right)
|
21
|
+
@left = left
|
22
|
+
@right = right
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/equalizer"
|
4
|
+
|
5
|
+
require "dry/schema/message/or/abstract"
|
6
|
+
require "dry/schema/path"
|
7
|
+
|
8
|
+
module Dry
|
9
|
+
module Schema
|
10
|
+
class Message
|
11
|
+
module Or
|
12
|
+
# A message type used by OR operations with different paths
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
class MultiPath < Abstract
|
16
|
+
# @api private
|
17
|
+
attr_reader :root
|
18
|
+
|
19
|
+
# @api private
|
20
|
+
def initialize(*args)
|
21
|
+
super
|
22
|
+
@root = [left, right].flatten.map(&:_path).reduce(:&)
|
23
|
+
@left = left.map { |msg| msg.to_or(root) }
|
24
|
+
@right = right.map { |msg| msg.to_or(root) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# @api public
|
28
|
+
def to_h
|
29
|
+
@to_h ||= Path[[*root, :or]].to_h(
|
30
|
+
[left.map(&:to_h).reduce(:merge), right.map(&:to_h).reduce(:merge)]
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/schema/message/or/abstract"
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Schema
|
7
|
+
class Message
|
8
|
+
module Or
|
9
|
+
# A message type used by OR operations with the same path
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
class SinglePath < Abstract
|
13
|
+
# @api private
|
14
|
+
attr_reader :path
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
attr_reader :_path
|
18
|
+
|
19
|
+
# @api private
|
20
|
+
attr_reader :messages
|
21
|
+
|
22
|
+
# @api private
|
23
|
+
def initialize(*args, messages)
|
24
|
+
super(*args)
|
25
|
+
@messages = messages
|
26
|
+
@path = left.path
|
27
|
+
@_path = left._path
|
28
|
+
end
|
29
|
+
|
30
|
+
# Dump a message into a string
|
31
|
+
#
|
32
|
+
# Both sides of the message will be joined using translated
|
33
|
+
# value under `dry_schema.or` message key
|
34
|
+
#
|
35
|
+
# @see Message#dump
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
def dump
|
41
|
+
@dump ||= "#{left.dump} #{messages[:or][:text]} #{right.dump}"
|
42
|
+
end
|
43
|
+
alias_method :to_s, :dump
|
44
|
+
|
45
|
+
# Dump an `or` message into a hash
|
46
|
+
#
|
47
|
+
# @see Message#to_h
|
48
|
+
#
|
49
|
+
# @return [String]
|
50
|
+
#
|
51
|
+
# @api public
|
52
|
+
def to_h
|
53
|
+
@to_h ||= _path.to_h(dump)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @api private
|
57
|
+
def to_a
|
58
|
+
@to_a ||= [left, right]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/initializer"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
5
|
+
require "dry/schema/constants"
|
6
|
+
require "dry/schema/message"
|
7
|
+
require "dry/schema/message_set"
|
8
|
+
require "dry/schema/message_compiler/visitor_opts"
|
9
9
|
|
10
10
|
module Dry
|
11
11
|
module Schema
|
@@ -29,6 +29,14 @@ module Dry
|
|
29
29
|
|
30
30
|
EMPTY_OPTS = VisitorOpts.new
|
31
31
|
EMPTY_MESSAGE_SET = MessageSet.new(EMPTY_ARRAY).freeze
|
32
|
+
FULL_MESSAGE_WHITESPACE = Hash.new(' ').merge(
|
33
|
+
ja: '',
|
34
|
+
zh: '',
|
35
|
+
bn: '',
|
36
|
+
th: '',
|
37
|
+
lo: '',
|
38
|
+
my: '',
|
39
|
+
)
|
32
40
|
|
33
41
|
param :messages
|
34
42
|
|
@@ -41,10 +49,10 @@ module Dry
|
|
41
49
|
attr_reader :default_lookup_options
|
42
50
|
|
43
51
|
# @api private
|
44
|
-
def initialize(messages, options
|
52
|
+
def initialize(messages, **options)
|
45
53
|
super
|
46
54
|
@options = options
|
47
|
-
@default_lookup_options = options[:locale] ? {
|
55
|
+
@default_lookup_options = options[:locale] ? {locale: locale} : EMPTY_HASH
|
48
56
|
end
|
49
57
|
|
50
58
|
# @api private
|
@@ -55,7 +63,7 @@ module Dry
|
|
55
63
|
|
56
64
|
return self if updated_opts.eql?(options)
|
57
65
|
|
58
|
-
self.class.new(messages, updated_opts)
|
66
|
+
self.class.new(messages, **updated_opts)
|
59
67
|
end
|
60
68
|
|
61
69
|
# @api private
|
@@ -100,23 +108,35 @@ module Dry
|
|
100
108
|
end
|
101
109
|
end
|
102
110
|
|
111
|
+
# @api private
|
112
|
+
def visit_unexpected_key(node, _opts)
|
113
|
+
path, input = node
|
114
|
+
|
115
|
+
msg = messages.translate("errors.unexpected_key")
|
116
|
+
|
117
|
+
Message.new(
|
118
|
+
path: path,
|
119
|
+
text: msg[:text],
|
120
|
+
predicate: nil,
|
121
|
+
input: input
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
103
125
|
# @api private
|
104
126
|
def visit_or(node, opts)
|
105
127
|
left, right = node.map { |n| visit(n, opts) }
|
128
|
+
Message::Or[left, right, or_translator]
|
129
|
+
end
|
106
130
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
right
|
111
|
-
else
|
112
|
-
[left, right].flatten.max
|
113
|
-
end
|
131
|
+
# @api private
|
132
|
+
def or_translator
|
133
|
+
@or_translator ||= proc { |k| messages.translate(k, **default_lookup_options) }
|
114
134
|
end
|
115
135
|
|
116
136
|
# @api private
|
117
137
|
def visit_namespace(node, opts)
|
118
138
|
ns, rest = node
|
119
|
-
self.class.new(messages.namespaced(ns), options).visit(rest, opts)
|
139
|
+
self.class.new(messages.namespaced(ns), **options).visit(rest, opts)
|
120
140
|
end
|
121
141
|
|
122
142
|
# @api private
|
@@ -130,13 +150,21 @@ module Dry
|
|
130
150
|
path: path.last, **tokens, **lookup_options(arg_vals: arg_vals, input: input)
|
131
151
|
).to_h
|
132
152
|
|
133
|
-
template, meta = messages[predicate, options]
|
134
|
-
|
153
|
+
template, meta = messages[predicate, options]
|
154
|
+
|
155
|
+
unless template
|
156
|
+
raise MissingMessageError.new(path, messages.looked_up_paths(predicate, options))
|
157
|
+
end
|
135
158
|
|
136
159
|
text = message_text(template, tokens, options)
|
137
160
|
|
138
161
|
message_type(options).new(
|
139
|
-
text: text,
|
162
|
+
text: text,
|
163
|
+
meta: meta,
|
164
|
+
path: path,
|
165
|
+
predicate: predicate,
|
166
|
+
args: arg_vals,
|
167
|
+
input: input
|
140
168
|
)
|
141
169
|
end
|
142
170
|
|
@@ -180,15 +208,15 @@ module Dry
|
|
180
208
|
def message_text(template, tokens, options)
|
181
209
|
text = template[template.data(tokens)]
|
182
210
|
|
183
|
-
return text
|
211
|
+
return text if !text || !full
|
184
212
|
|
185
213
|
rule = options[:path]
|
186
|
-
|
214
|
+
[messages.rule(rule, options) || rule, text].join(FULL_MESSAGE_WHITESPACE[template.options[:locale]])
|
187
215
|
end
|
188
216
|
|
189
217
|
# @api private
|
190
218
|
def message_tokens(args)
|
191
|
-
args.each_with_object({}) do |arg, hash|
|
219
|
+
tokens = args.each_with_object({}) do |arg, hash|
|
192
220
|
case arg[1]
|
193
221
|
when Array
|
194
222
|
hash[arg[0]] = arg[1].join(LIST_SEPARATOR)
|
@@ -199,6 +227,14 @@ module Dry
|
|
199
227
|
hash[arg[0]] = arg[1]
|
200
228
|
end
|
201
229
|
end
|
230
|
+
args.any? { |e| e.first == :size } ? append_mapped_size_tokens(tokens) : tokens
|
231
|
+
end
|
232
|
+
|
233
|
+
# @api private
|
234
|
+
def append_mapped_size_tokens(tokens)
|
235
|
+
# this is a temporary fix for the inconsistency in the "size" errors arguments
|
236
|
+
mapped_hash = tokens.each_with_object({}) { |(k, v), h| h[k.to_s.gsub("size", "num").to_sym] = v }
|
237
|
+
tokens.merge(mapped_hash)
|
202
238
|
end
|
203
239
|
end
|
204
240
|
end
|