definition 0.7.1 → 0.8.1
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/.gitignore +1 -0
- data/Changelog.md +15 -0
- data/Gemfile.lock +21 -19
- data/README.md +134 -54
- data/UpgradeNotes.md +27 -0
- data/benchmark/initializer.rb +91 -0
- data/benchmark/model.rb +70 -0
- data/benchmark/validation_only.rb +11 -13
- data/config/locales/en.yml +2 -2
- data/lib/definition/dsl/comparators.rb +29 -19
- data/lib/definition/dsl/nil.rb +1 -1
- data/lib/definition/dsl.rb +15 -15
- data/lib/definition/initializer.rb +52 -0
- data/lib/definition/model.rb +85 -0
- data/lib/definition/types/keys.rb +49 -67
- data/lib/definition/types/lambda.rb +7 -1
- data/lib/definition/v1_deprecator.rb +7 -0
- data/lib/definition/version.rb +1 -1
- data/lib/definition.rb +2 -0
- metadata +9 -4
- data/tags +0 -155
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "definition/v1_deprecator"
|
4
|
+
|
3
5
|
module Definition
|
4
6
|
module Dsl
|
5
7
|
module Comparators
|
6
8
|
# Example:
|
7
9
|
# MaxSize(5)
|
8
|
-
def MaxSize(max_size) # rubocop:disable
|
10
|
+
def MaxSize(max_size) # rubocop:disable Naming/MethodName
|
9
11
|
Types::Lambda.new(:max_size, context: { max_size: max_size }) do |value|
|
10
12
|
case value
|
11
13
|
when String, Enumerable
|
@@ -18,7 +20,7 @@ module Definition
|
|
18
20
|
|
19
21
|
# Example:
|
20
22
|
# MinSize(5)
|
21
|
-
def MinSize(min_size) # rubocop:disable
|
23
|
+
def MinSize(min_size) # rubocop:disable Naming/MethodName
|
22
24
|
Types::Lambda.new(:min_size, context: { min_size: min_size }) do |value|
|
23
25
|
case value
|
24
26
|
when String, Enumerable
|
@@ -31,45 +33,53 @@ module Definition
|
|
31
33
|
|
32
34
|
# Example:
|
33
35
|
# NonEmptyString
|
34
|
-
def NonEmptyString # rubocop:disable
|
36
|
+
def NonEmptyString # rubocop:disable Naming/MethodName
|
35
37
|
Types::And.new(:non_empty_string, Type(String), MinSize(1))
|
36
38
|
end
|
37
39
|
|
38
40
|
# Example:
|
39
|
-
#
|
40
|
-
def
|
41
|
-
Types::Lambda.new("
|
41
|
+
# GreaterThan(5)
|
42
|
+
def GreaterThan(min_value) # rubocop:disable Naming/MethodName
|
43
|
+
Types::Lambda.new("greater_than", context: { min_value: min_value }) do |value|
|
42
44
|
conform_with(value) if value.is_a?(Numeric) && value > min_value
|
43
45
|
end
|
44
46
|
end
|
47
|
+
alias GreaterThen GreaterThan
|
48
|
+
deprecate :GreaterThen, deprecator: V1Deprecator
|
45
49
|
|
46
50
|
# Example:
|
47
|
-
#
|
48
|
-
def
|
49
|
-
Types::Lambda.new("
|
51
|
+
# GreaterThanEqual(5)
|
52
|
+
def GreaterThanEqual(min_value) # rubocop:disable Naming/MethodName
|
53
|
+
Types::Lambda.new("greater_than_equal", context: { min_value: min_value }) do |value|
|
50
54
|
conform_with(value) if value.is_a?(Numeric) && value >= min_value
|
51
55
|
end
|
52
56
|
end
|
57
|
+
alias GreaterThenEqual GreaterThanEqual
|
58
|
+
deprecate :GreaterThenEqual, deprecator: V1Deprecator
|
53
59
|
|
54
60
|
# Example:
|
55
|
-
#
|
56
|
-
def
|
57
|
-
Types::Lambda.new("
|
61
|
+
# LessThan(5)
|
62
|
+
def LessThan(max_value) # rubocop:disable Naming/MethodName
|
63
|
+
Types::Lambda.new("less_than", context: { max_value: max_value }) do |value|
|
58
64
|
conform_with(value) if value.is_a?(Numeric) && value < max_value
|
59
65
|
end
|
60
66
|
end
|
67
|
+
alias LessThen LessThan
|
68
|
+
deprecate :LessThen, deprecator: V1Deprecator
|
61
69
|
|
62
70
|
# Example:
|
63
|
-
#
|
64
|
-
def
|
65
|
-
Types::Lambda.new("
|
71
|
+
# LessThanEqual(5)
|
72
|
+
def LessThanEqual(max_value) # rubocop:disable Naming/MethodName
|
73
|
+
Types::Lambda.new("less_than_equal", context: { max_value: max_value }) do |value|
|
66
74
|
conform_with(value) if value.is_a?(Numeric) && value <= max_value
|
67
75
|
end
|
68
76
|
end
|
77
|
+
alias LessThenEqual LessThanEqual
|
78
|
+
deprecate :LessThenEqual, deprecator: V1Deprecator
|
69
79
|
|
70
80
|
# Example:
|
71
81
|
# Equal("value")
|
72
|
-
def Equal(expected_value) # rubocop:disable
|
82
|
+
def Equal(expected_value) # rubocop:disable Naming/MethodName
|
73
83
|
Types::Lambda.new(:equal, context: { expected_value: expected_value }) do |value|
|
74
84
|
conform_with(value) if value == expected_value
|
75
85
|
end
|
@@ -77,7 +87,7 @@ module Definition
|
|
77
87
|
|
78
88
|
# Example:
|
79
89
|
# Empty
|
80
|
-
def Empty # rubocop:disable
|
90
|
+
def Empty # rubocop:disable Naming/MethodName
|
81
91
|
Types::Lambda.new(:empty) do |value|
|
82
92
|
case value
|
83
93
|
when String, Array, Hash
|
@@ -90,7 +100,7 @@ module Definition
|
|
90
100
|
|
91
101
|
# Example:
|
92
102
|
# NonEmpty
|
93
|
-
def NonEmpty # rubocop:disable
|
103
|
+
def NonEmpty # rubocop:disable Naming/MethodName
|
94
104
|
Types::Lambda.new(:non_empty) do |value|
|
95
105
|
case value
|
96
106
|
when String, Array, Hash
|
@@ -103,7 +113,7 @@ module Definition
|
|
103
113
|
|
104
114
|
# Example:
|
105
115
|
# Regex
|
106
|
-
def Regex(regex, name: :regex) # rubocop:disable
|
116
|
+
def Regex(regex, name: :regex) # rubocop:disable Naming/MethodName
|
107
117
|
Types::Lambda.new(name, context: { regex: regex.inspect }) do |value|
|
108
118
|
case value
|
109
119
|
when String
|
data/lib/definition/dsl/nil.rb
CHANGED
data/lib/definition/dsl.rb
CHANGED
@@ -9,33 +9,33 @@ module Definition
|
|
9
9
|
# required :name, Types::Type(String)
|
10
10
|
# optional :age, Types::Type(Integer)
|
11
11
|
# end
|
12
|
-
def Keys(&block) # rubocop:disable
|
12
|
+
def Keys(&block) # rubocop:disable Naming/MethodName
|
13
13
|
Types::Keys.new(:hash).tap do |instance|
|
14
14
|
instance.instance_exec(&block)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
# Example:
|
19
|
-
# And(Types::Type(Float), Types::
|
20
|
-
def And(*definitions) # rubocop:disable
|
19
|
+
# And(Types::Type(Float), Types::GreaterThan(10.0))
|
20
|
+
def And(*definitions) # rubocop:disable Naming/MethodName
|
21
21
|
Types::And.new(:and, *definitions)
|
22
22
|
end
|
23
23
|
|
24
24
|
# Example:
|
25
25
|
# Or(Types::Type(Float), Types::Type(Integer))
|
26
|
-
def Or(*definitions) # rubocop:disable
|
26
|
+
def Or(*definitions) # rubocop:disable Naming/MethodName
|
27
27
|
Types::Or.new(:or, *definitions)
|
28
28
|
end
|
29
29
|
|
30
30
|
# Example:
|
31
31
|
# Type(Integer)
|
32
|
-
def Type(klass) # rubocop:disable
|
32
|
+
def Type(klass) # rubocop:disable Naming/MethodName
|
33
33
|
Types::Type.new(:type, klass)
|
34
34
|
end
|
35
35
|
|
36
36
|
# Example:
|
37
37
|
# CoercibleType(Integer)
|
38
|
-
def CoercibleType(klass) # rubocop:disable
|
38
|
+
def CoercibleType(klass) # rubocop:disable Naming/MethodName
|
39
39
|
unless Kernel.respond_to?(klass.name)
|
40
40
|
raise ArgumentError.new("#{klass} can't be used as CoercibleType because its not "\
|
41
41
|
"a primitive that has a coercion function defined")
|
@@ -51,13 +51,13 @@ module Definition
|
|
51
51
|
# Lambda(:even) do |value|
|
52
52
|
# value.even?
|
53
53
|
# end
|
54
|
-
def Lambda(name, context: {}, &block) # rubocop:disable
|
54
|
+
def Lambda(name, context: {}, &block) # rubocop:disable Naming/MethodName
|
55
55
|
Types::Lambda.new(name, context: context, &block)
|
56
56
|
end
|
57
57
|
|
58
58
|
# Example:
|
59
59
|
# Enum("allowed_value1", "allowed_value2")
|
60
|
-
def Enum(*allowed_values) # rubocop:disable
|
60
|
+
def Enum(*allowed_values) # rubocop:disable Naming/MethodName
|
61
61
|
Lambda("enum", context: { allowed_values: allowed_values }) do |value|
|
62
62
|
conform_with(value) if allowed_values.include?(value)
|
63
63
|
end
|
@@ -65,24 +65,24 @@ module Definition
|
|
65
65
|
|
66
66
|
# Example:
|
67
67
|
# Each(Definition::Type(Integer))
|
68
|
-
def Each(definition) # rubocop:disable
|
68
|
+
def Each(definition) # rubocop:disable Naming/MethodName
|
69
69
|
Types::Each.new(:each, definition: definition)
|
70
70
|
end
|
71
71
|
|
72
72
|
# Example:
|
73
73
|
# Boolean
|
74
|
-
def Boolean # rubocop:disable
|
74
|
+
def Boolean # rubocop:disable Naming/MethodName
|
75
75
|
Types::Or.new(:boolean, Type(TrueClass), Type(FalseClass))
|
76
76
|
end
|
77
77
|
|
78
78
|
# Example:
|
79
|
-
#
|
80
|
-
def
|
81
|
-
Types::Or.new(:
|
79
|
+
# CoercibleModel(ModelClass)
|
80
|
+
def CoercibleModel(klass) # rubocop:disable Naming/MethodName
|
81
|
+
Types::Or.new(:coercible_model,
|
82
82
|
Definition.Type(klass), # If its of ther correct type already this will let it pass already
|
83
83
|
And(
|
84
84
|
klass, # First make sure that the input could be coerced to 'klass'
|
85
|
-
Lambda("value_object_coercion", context: {
|
85
|
+
Lambda("value_object_coercion", context: { model_class: klass }) do |value|
|
86
86
|
conform_with(klass.new(value)) # Actually coerce the input to klass
|
87
87
|
end
|
88
88
|
))
|
@@ -90,7 +90,7 @@ module Definition
|
|
90
90
|
|
91
91
|
# Example:
|
92
92
|
# Nilable(Definition.Type(Integer))
|
93
|
-
def Nilable(definition) # rubocop:disable
|
93
|
+
def Nilable(definition) # rubocop:disable Naming/MethodName
|
94
94
|
Types::Or.new(:nilable, Nil(), definition)
|
95
95
|
end
|
96
96
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Definition
|
4
|
+
module Initializer
|
5
|
+
class InvalidArgumentError < ArgumentError
|
6
|
+
attr_accessor :conform_result
|
7
|
+
|
8
|
+
def initialize(conform_result)
|
9
|
+
super("Arguments passed into the initializer are invalid: #{conform_result.error_message}")
|
10
|
+
self.conform_result = conform_result
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def required(name, *args)
|
16
|
+
_keys_definition.required(name, *args)
|
17
|
+
_define_attr_accessor(name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def optional(name, *args, **kwargs)
|
21
|
+
_keys_definition.optional(name, *args, **kwargs)
|
22
|
+
_define_attr_accessor(name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def _keys_definition
|
26
|
+
@_keys_definition ||= Definition.Keys {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def _define_attr_accessor(key)
|
30
|
+
define_method(key) do
|
31
|
+
@_attributes.fetch(key, nil)
|
32
|
+
end
|
33
|
+
define_method("#{key}=") do |value|
|
34
|
+
@_attributes[key] = value
|
35
|
+
end
|
36
|
+
protected key
|
37
|
+
protected "#{key}="
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.included(klass)
|
42
|
+
klass.extend(ClassMethods)
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(**kwargs)
|
46
|
+
result = self.class._keys_definition.conform(kwargs)
|
47
|
+
raise InvalidArgumentError.new(result) unless result.passed?
|
48
|
+
|
49
|
+
@_attributes = result.value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Definition
|
4
|
+
class InvalidModelError < StandardError
|
5
|
+
attr_accessor :conform_result
|
6
|
+
|
7
|
+
def initialize(conform_result)
|
8
|
+
super(conform_result.error_message)
|
9
|
+
self.conform_result = conform_result
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Model
|
14
|
+
class << self
|
15
|
+
def conform(value)
|
16
|
+
_definition.conform(value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def required(key, definition)
|
20
|
+
_define_attr_accessor(key)
|
21
|
+
_definition.required(key, definition)
|
22
|
+
end
|
23
|
+
|
24
|
+
def optional(key, definition, **opts)
|
25
|
+
_define_attr_accessor(key)
|
26
|
+
_definition.optional(key, definition, **opts)
|
27
|
+
end
|
28
|
+
|
29
|
+
def option(option_name)
|
30
|
+
_definition.option(option_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def _define_attr_accessor(key)
|
34
|
+
define_method(key) do
|
35
|
+
@_attributes.fetch(key, nil)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def _definition
|
40
|
+
@_definition ||= ::Definition.Keys {}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(hash = nil, **kwargs)
|
45
|
+
result = self.class.conform(hash || kwargs)
|
46
|
+
raise InvalidModelError.new(result) unless result.passed?
|
47
|
+
|
48
|
+
@_attributes = result.value.freeze
|
49
|
+
end
|
50
|
+
|
51
|
+
def new(**kwargs)
|
52
|
+
self.class.new(**to_h.merge!(kwargs))
|
53
|
+
end
|
54
|
+
|
55
|
+
def ==(other)
|
56
|
+
return false unless other.is_a?(self.class)
|
57
|
+
|
58
|
+
@_attributes.hash == other.instance_variable_get(:@_attributes).hash
|
59
|
+
end
|
60
|
+
alias eql? ==
|
61
|
+
|
62
|
+
def hash
|
63
|
+
@_attributes.hash
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_h
|
67
|
+
_deep_transform_values_in_object(@_attributes) do |value|
|
68
|
+
value.is_a?(::Definition::Model) ? value.to_h : value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def _deep_transform_values_in_object(object, &block)
|
75
|
+
case object
|
76
|
+
when Hash
|
77
|
+
object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
|
78
|
+
when Array
|
79
|
+
object.map { |e| _deep_transform_values_in_object(e, &block) }
|
80
|
+
else
|
81
|
+
yield(object)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -9,11 +9,11 @@ module Definition
|
|
9
9
|
class Keys < Base
|
10
10
|
module Dsl
|
11
11
|
def required(key, definition)
|
12
|
-
required_definitions
|
12
|
+
required_definitions << { key: key, definition: definition }
|
13
13
|
end
|
14
14
|
|
15
15
|
def optional(key, definition, **opts)
|
16
|
-
optional_definitions
|
16
|
+
optional_definitions << { key: key, definition: definition }
|
17
17
|
default(key, opts[:default]) if opts.key?(:default)
|
18
18
|
end
|
19
19
|
|
@@ -30,15 +30,10 @@ module Definition
|
|
30
30
|
raise ArgumentError.new("Included Definition can only be a Keys Definition") unless other.is_a?(Types::Keys)
|
31
31
|
|
32
32
|
ensure_keys_do_not_interfere(other)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
other.
|
37
|
-
optional(key, definition)
|
38
|
-
end
|
39
|
-
other.defaults.each do |key, default|
|
40
|
-
default(key, default)
|
41
|
-
end
|
33
|
+
|
34
|
+
self.required_definitions += other.required_definitions
|
35
|
+
self.optional_definitions += other.optional_definitions
|
36
|
+
defaults.merge!(other.defaults)
|
42
37
|
end
|
43
38
|
|
44
39
|
private
|
@@ -62,8 +57,8 @@ module Definition
|
|
62
57
|
|
63
58
|
def initialize(name, req: {}, opt: {}, defaults: {}, options: {})
|
64
59
|
super(name)
|
65
|
-
self.required_definitions = req
|
66
|
-
self.optional_definitions = opt
|
60
|
+
self.required_definitions = req.map { |key, definition| { key: key, definition: definition } }
|
61
|
+
self.optional_definitions = opt.map { |key, definition| { key: key, definition: definition } }
|
67
62
|
self.defaults = defaults
|
68
63
|
self.ignore_extra_keys = options.fetch(:ignore_extra_keys, false)
|
69
64
|
end
|
@@ -73,7 +68,7 @@ module Definition
|
|
73
68
|
end
|
74
69
|
|
75
70
|
def keys
|
76
|
-
required_definitions
|
71
|
+
(required_definitions + optional_definitions).map { |hash| hash[:key] }
|
77
72
|
end
|
78
73
|
|
79
74
|
class Conformer
|
@@ -81,18 +76,15 @@ module Definition
|
|
81
76
|
self.definition = definition
|
82
77
|
self.value = value
|
83
78
|
self.errors = []
|
79
|
+
@conform_result_value = {} # This will be the output value after conforming
|
80
|
+
@not_conformed_value_keys = value.dup # Used to track which keys are left over in the end (unexpected keys)
|
84
81
|
end
|
85
82
|
|
86
83
|
def conform
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
else
|
92
|
-
errors.push(ConformError.new(definition,
|
93
|
-
"#{definition.name} is not a Hash",
|
94
|
-
i18n_key: "keys.not_a_hash"))
|
95
|
-
end
|
84
|
+
return invalid_input_result unless valid_input_type?
|
85
|
+
|
86
|
+
values = conform_all_keys
|
87
|
+
add_extra_key_errors unless definition.ignore_extra_keys
|
96
88
|
|
97
89
|
ConformResult.new(values, errors: errors)
|
98
90
|
end
|
@@ -101,12 +93,19 @@ module Definition
|
|
101
93
|
|
102
94
|
attr_accessor :errors
|
103
95
|
|
96
|
+
def invalid_input_result
|
97
|
+
errors = [ConformError.new(definition,
|
98
|
+
"#{definition.name} is not a Hash",
|
99
|
+
i18n_key: "keys.not_a_hash")]
|
100
|
+
ConformResult.new(value, errors: errors)
|
101
|
+
end
|
102
|
+
|
104
103
|
def valid_input_type?
|
105
104
|
value.is_a?(Hash)
|
106
105
|
end
|
107
106
|
|
108
107
|
def add_extra_key_errors
|
109
|
-
extra_keys =
|
108
|
+
extra_keys = @not_conformed_value_keys.keys
|
110
109
|
return if extra_keys.empty?
|
111
110
|
|
112
111
|
extra_keys.each do |key|
|
@@ -120,59 +119,42 @@ module Definition
|
|
120
119
|
end
|
121
120
|
|
122
121
|
def conform_all_keys
|
123
|
-
|
124
|
-
|
122
|
+
conform_definitions(definition.required_definitions, required: true)
|
123
|
+
conform_definitions(definition.optional_definitions, required: false)
|
125
124
|
|
126
|
-
|
125
|
+
@conform_result_value
|
127
126
|
end
|
128
127
|
|
129
|
-
def
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
def required_keys
|
138
|
-
required_definitions.keys
|
139
|
-
end
|
140
|
-
|
141
|
-
def optional_definitions
|
142
|
-
definition.optional_definitions
|
143
|
-
end
|
144
|
-
|
145
|
-
def optional_keys
|
146
|
-
optional_definitions.keys
|
128
|
+
def conform_definitions(keys, required:)
|
129
|
+
keys.each do |hash|
|
130
|
+
key = hash[:key]
|
131
|
+
key_definition = hash[:definition]
|
132
|
+
conform_definition(key, key_definition, required: required)
|
133
|
+
end
|
147
134
|
end
|
148
135
|
|
149
|
-
|
150
|
-
|
151
|
-
|
136
|
+
# Rubcop rules are disabled for performance optimization purposes
|
137
|
+
def conform_definition(key, key_definition, required:) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
138
|
+
@not_conformed_value_keys.delete(key) # Keys left over in that hash at the end are considered unexpected
|
152
139
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
errors.push(
|
158
|
-
|
159
|
-
|
160
|
-
sub_errors: result.error_tree))
|
140
|
+
# If the input value is missing a key:
|
141
|
+
# a) add a missing key error if it is a required key
|
142
|
+
# b) otherwise initialize the missing key in the output value if a default value is configured
|
143
|
+
unless value.key?(key)
|
144
|
+
errors.push(missing_key_error(key)) if required
|
145
|
+
@conform_result_value[key] = definition.defaults[key] if definition.defaults.key?(key)
|
146
|
+
return
|
161
147
|
end
|
162
|
-
end
|
163
148
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
*required_keys
|
168
|
-
)
|
169
|
-
|
170
|
-
result = required_definition.conform(value)
|
149
|
+
# If the input value has a key then its value is conformed against the configured definition
|
150
|
+
result = key_definition.conform(value[key])
|
151
|
+
@conform_result_value[key] = result.value
|
171
152
|
return if result.passed?
|
172
153
|
|
173
|
-
|
174
|
-
|
175
|
-
|
154
|
+
errors.push(KeyConformError.new(key_definition,
|
155
|
+
"#{definition.name} fails validation for key #{key}",
|
156
|
+
key: key,
|
157
|
+
sub_errors: result.error_tree))
|
176
158
|
end
|
177
159
|
|
178
160
|
def missing_key_error(key)
|
@@ -52,10 +52,16 @@ module Definition
|
|
52
52
|
"Did not pass test for #{definition.name}"
|
53
53
|
end
|
54
54
|
|
55
|
+
def contextual_error_message
|
56
|
+
return standard_error_message if definition.context.empty?
|
57
|
+
|
58
|
+
"#{standard_error_message} (#{definition.context.values.join(',')})"
|
59
|
+
end
|
60
|
+
|
55
61
|
def failure_result_with(value, error_message)
|
56
62
|
ConformResult.new(value, errors: [
|
57
63
|
ConformError.new(definition,
|
58
|
-
|
64
|
+
contextual_error_message,
|
59
65
|
translated_message: error_message)
|
60
66
|
])
|
61
67
|
end
|
data/lib/definition/version.rb
CHANGED
data/lib/definition.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: definition
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Goltermann
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -266,8 +266,11 @@ files:
|
|
266
266
|
- LICENSE
|
267
267
|
- README.md
|
268
268
|
- Rakefile
|
269
|
+
- UpgradeNotes.md
|
269
270
|
- benchmark/coercion.rb
|
270
271
|
- benchmark/complex_example.rb
|
272
|
+
- benchmark/initializer.rb
|
273
|
+
- benchmark/model.rb
|
271
274
|
- benchmark/validation_only.rb
|
272
275
|
- bin/console
|
273
276
|
- bin/setup
|
@@ -280,7 +283,9 @@ files:
|
|
280
283
|
- lib/definition/dsl/comparators.rb
|
281
284
|
- lib/definition/dsl/nil.rb
|
282
285
|
- lib/definition/i18n.rb
|
286
|
+
- lib/definition/initializer.rb
|
283
287
|
- lib/definition/key_conform_error.rb
|
288
|
+
- lib/definition/model.rb
|
284
289
|
- lib/definition/types.rb
|
285
290
|
- lib/definition/types/and.rb
|
286
291
|
- lib/definition/types/base.rb
|
@@ -293,9 +298,9 @@ files:
|
|
293
298
|
- lib/definition/types/lambda.rb
|
294
299
|
- lib/definition/types/or.rb
|
295
300
|
- lib/definition/types/type.rb
|
301
|
+
- lib/definition/v1_deprecator.rb
|
296
302
|
- lib/definition/value_object.rb
|
297
303
|
- lib/definition/version.rb
|
298
|
-
- tags
|
299
304
|
homepage: https://github.com/Goltergaul/definition
|
300
305
|
licenses:
|
301
306
|
- MIT
|
@@ -315,7 +320,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
315
320
|
- !ruby/object:Gem::Version
|
316
321
|
version: '0'
|
317
322
|
requirements: []
|
318
|
-
rubygems_version: 3.
|
323
|
+
rubygems_version: 3.3.7
|
319
324
|
signing_key:
|
320
325
|
specification_version: 4
|
321
326
|
summary: Simple and composable validation and coercion of data structures inspired
|