stannum 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/README.md +85 -21
- data/config/locales/en.rb +17 -3
- data/lib/stannum/constraints/base.rb +11 -4
- data/lib/stannum/constraints/hashes/extra_keys.rb +10 -2
- data/lib/stannum/constraints/hashes/indifferent_extra_keys.rb +47 -0
- data/lib/stannum/constraints/hashes.rb +6 -2
- data/lib/stannum/constraints/parameters/extra_arguments.rb +23 -0
- data/lib/stannum/constraints/parameters/extra_keywords.rb +29 -0
- data/lib/stannum/constraints/parameters.rb +11 -0
- data/lib/stannum/constraints/properties/base.rb +124 -0
- data/lib/stannum/constraints/properties/do_not_match_property.rb +117 -0
- data/lib/stannum/constraints/properties/match_property.rb +117 -0
- data/lib/stannum/constraints/properties/matching.rb +112 -0
- data/lib/stannum/constraints/properties.rb +17 -0
- data/lib/stannum/constraints/tuples/extra_items.rb +1 -1
- data/lib/stannum/constraints/type.rb +1 -1
- data/lib/stannum/constraints/types/hash_type.rb +6 -2
- data/lib/stannum/constraints.rb +2 -0
- data/lib/stannum/contracts/builder.rb +13 -2
- data/lib/stannum/contracts/hash_contract.rb +14 -0
- data/lib/stannum/contracts/indifferent_hash_contract.rb +13 -0
- data/lib/stannum/contracts/parameters/arguments_contract.rb +2 -7
- data/lib/stannum/contracts/parameters/keywords_contract.rb +2 -7
- data/lib/stannum/contracts/tuple_contract.rb +1 -1
- data/lib/stannum/entities/attributes.rb +218 -0
- data/lib/stannum/entities/constraints.rb +177 -0
- data/lib/stannum/entities/properties.rb +186 -0
- data/lib/stannum/entities.rb +13 -0
- data/lib/stannum/entity.rb +83 -0
- data/lib/stannum/errors.rb +3 -3
- data/lib/stannum/messages/default_loader.rb +95 -0
- data/lib/stannum/messages/default_strategy.rb +31 -50
- data/lib/stannum/messages.rb +1 -0
- data/lib/stannum/rspec/match_errors_matcher.rb +6 -6
- data/lib/stannum/rspec/validate_parameter_matcher.rb +10 -9
- data/lib/stannum/schema.rb +78 -37
- data/lib/stannum/struct.rb +12 -346
- data/lib/stannum/support/coercion.rb +19 -0
- data/lib/stannum/version.rb +1 -1
- data/lib/stannum.rb +3 -0
- metadata +29 -19
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints/properties'
|
4
|
+
require 'stannum/constraints/properties/matching'
|
5
|
+
|
6
|
+
module Stannum::Constraints::Properties
|
7
|
+
# Compares the properties of the given object with the specified property.
|
8
|
+
#
|
9
|
+
# If none of the property values equal the expected value, the constraint will
|
10
|
+
# match the object; otherwise, if there are any matching values, the
|
11
|
+
# constraint will not match.
|
12
|
+
#
|
13
|
+
# @example Using an Properties::Match constraint
|
14
|
+
# UpdatePassword = Struct.new(:old_password, :new_password)
|
15
|
+
# constraint = Stannum::Constraints::Properties::DoNotMatchProperty.new(
|
16
|
+
# :old_password,
|
17
|
+
# :new_password
|
18
|
+
# )
|
19
|
+
#
|
20
|
+
# params = UpdatePassword.new('tronlives', 'ifightfortheusers')
|
21
|
+
# constraint.matches?(params)
|
22
|
+
# #=> true
|
23
|
+
#
|
24
|
+
# params = UpdatePassword.new('tronlives', 'tronlives')
|
25
|
+
# constraint.matches?(params)
|
26
|
+
# #=> false
|
27
|
+
# constraint.errors_for(params)
|
28
|
+
# #=> [
|
29
|
+
# {
|
30
|
+
# path: [:confirmation],
|
31
|
+
# type: 'stannum.constraints.is_equal_to',
|
32
|
+
# data: { expected: '[FILTERED]', actual: '[FILTERED]' }
|
33
|
+
# }
|
34
|
+
# ]
|
35
|
+
class DoNotMatchProperty < Stannum::Constraints::Properties::Matching
|
36
|
+
# The :type of the error generated for a matching object.
|
37
|
+
NEGATED_TYPE = Stannum::Constraints::Equality::TYPE
|
38
|
+
|
39
|
+
# The :type of the error generated for a non-matching object.
|
40
|
+
TYPE = Stannum::Constraints::Equality::NEGATED_TYPE
|
41
|
+
|
42
|
+
# @return [true, false] true if the property values match the reference
|
43
|
+
# property value; otherwise false.
|
44
|
+
def does_not_match?(actual)
|
45
|
+
return false unless can_match_properties?(actual)
|
46
|
+
|
47
|
+
expected = expected_value(actual)
|
48
|
+
|
49
|
+
return false if skip_property?(expected)
|
50
|
+
|
51
|
+
each_non_matching_property(
|
52
|
+
actual: actual,
|
53
|
+
expected: expected,
|
54
|
+
include_all: true
|
55
|
+
)
|
56
|
+
.none?
|
57
|
+
end
|
58
|
+
|
59
|
+
# (see Stannum::Constraints::Base#errors_for)
|
60
|
+
def errors_for(actual, errors: nil)
|
61
|
+
errors ||= Stannum::Errors.new
|
62
|
+
|
63
|
+
return invalid_object_errors(errors) unless can_match_properties?(actual)
|
64
|
+
|
65
|
+
expected = expected_value(actual)
|
66
|
+
matching = each_matching_property(actual: actual, expected: expected)
|
67
|
+
|
68
|
+
return generic_errors(errors) if matching.count.zero?
|
69
|
+
|
70
|
+
matching.each do |property_name, _|
|
71
|
+
errors[property_name].add(type, message: message)
|
72
|
+
end
|
73
|
+
|
74
|
+
errors
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [true, false] false if any of the property values match the
|
78
|
+
# reference property value; otherwise true.
|
79
|
+
def matches?(actual)
|
80
|
+
return false unless can_match_properties?(actual)
|
81
|
+
|
82
|
+
expected = expected_value(actual)
|
83
|
+
|
84
|
+
return true if skip_property?(expected)
|
85
|
+
|
86
|
+
each_matching_property(actual: actual, expected: expected).none?
|
87
|
+
end
|
88
|
+
alias match? matches?
|
89
|
+
|
90
|
+
# (see Stannum::Constraints::Base#negated_errors_for)
|
91
|
+
def negated_errors_for(actual, errors: nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
92
|
+
errors ||= Stannum::Errors.new
|
93
|
+
|
94
|
+
return invalid_object_errors(errors) unless can_match_properties?(actual)
|
95
|
+
|
96
|
+
expected = expected_value(actual)
|
97
|
+
matching = each_non_matching_property(
|
98
|
+
actual: actual,
|
99
|
+
expected: expected,
|
100
|
+
include_all: true
|
101
|
+
)
|
102
|
+
|
103
|
+
return generic_errors(errors) if matching.count.zero?
|
104
|
+
|
105
|
+
matching.each do |property_name, value|
|
106
|
+
errors[property_name].add(
|
107
|
+
negated_type,
|
108
|
+
message: negated_message,
|
109
|
+
expected: filter_parameters? ? '[FILTERED]' : expected_value(actual),
|
110
|
+
actual: filter_parameters? ? '[FILTERED]' : value
|
111
|
+
)
|
112
|
+
end
|
113
|
+
|
114
|
+
errors
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints/properties'
|
4
|
+
require 'stannum/constraints/properties/matching'
|
5
|
+
|
6
|
+
module Stannum::Constraints::Properties
|
7
|
+
# Compares the properties of the given object with the specified property.
|
8
|
+
#
|
9
|
+
# If all of the property values equal the expected value, the constraint will
|
10
|
+
# match the object; otherwise, if there are any non-matching values, the
|
11
|
+
# constraint will not match.
|
12
|
+
#
|
13
|
+
# @example Using an Properties::Match constraint
|
14
|
+
# ConfirmPassword = Struct.new(:password, :confirmation)
|
15
|
+
# constraint = Stannum::Constraints::Properties::MatchProperty.new(
|
16
|
+
# :password,
|
17
|
+
# :confirmation
|
18
|
+
# )
|
19
|
+
#
|
20
|
+
# params = ConfirmPassword.new('tronlives', 'ifightfortheusers')
|
21
|
+
# constraint.matches?(params)
|
22
|
+
# #=> false
|
23
|
+
# constraint.errors_for(params)
|
24
|
+
# #=> [
|
25
|
+
# {
|
26
|
+
# path: [:confirmation],
|
27
|
+
# type: 'stannum.constraints.is_not_equal_to',
|
28
|
+
# data: { expected: '[FILTERED]', actual: '[FILTERED]' }
|
29
|
+
# }
|
30
|
+
# ]
|
31
|
+
#
|
32
|
+
# params = ConfirmPassword.new('tronlives', 'tronlives')
|
33
|
+
# constraint.matches?(params)
|
34
|
+
# #=> true
|
35
|
+
class MatchProperty < Stannum::Constraints::Properties::Matching
|
36
|
+
# The :type of the error generated for a matching object.
|
37
|
+
NEGATED_TYPE = Stannum::Constraints::Equality::NEGATED_TYPE
|
38
|
+
|
39
|
+
# The :type of the error generated for a non-matching object.
|
40
|
+
TYPE = Stannum::Constraints::Equality::TYPE
|
41
|
+
|
42
|
+
# @return [true, false] false if any of the property values match the
|
43
|
+
# reference property value; otherwise true.
|
44
|
+
def does_not_match?(actual)
|
45
|
+
return false unless can_match_properties?(actual)
|
46
|
+
|
47
|
+
expected = expected_value(actual)
|
48
|
+
|
49
|
+
return false if skip_property?(expected)
|
50
|
+
|
51
|
+
each_matching_property(
|
52
|
+
actual: actual,
|
53
|
+
expected: expected,
|
54
|
+
include_all: true
|
55
|
+
)
|
56
|
+
.none?
|
57
|
+
end
|
58
|
+
|
59
|
+
# (see Stannum::Constraints::Base#errors_for)
|
60
|
+
def errors_for(actual, errors: nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
61
|
+
errors ||= Stannum::Errors.new
|
62
|
+
|
63
|
+
return invalid_object_errors(errors) unless can_match_properties?(actual)
|
64
|
+
|
65
|
+
expected = expected_value(actual)
|
66
|
+
matching = each_non_matching_property(actual: actual, expected: expected)
|
67
|
+
|
68
|
+
return generic_errors(errors) if matching.count.zero?
|
69
|
+
|
70
|
+
matching.each do |property_name, value|
|
71
|
+
errors[property_name].add(
|
72
|
+
type,
|
73
|
+
message: message,
|
74
|
+
expected: filter_parameters? ? '[FILTERED]' : expected_value(actual),
|
75
|
+
actual: filter_parameters? ? '[FILTERED]' : value
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
errors
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [true, false] true if the property values match the reference
|
83
|
+
# property value; otherwise false.
|
84
|
+
def matches?(actual)
|
85
|
+
return false unless can_match_properties?(actual)
|
86
|
+
|
87
|
+
expected = expected_value(actual)
|
88
|
+
|
89
|
+
return true if skip_property?(expected)
|
90
|
+
|
91
|
+
each_non_matching_property(actual: actual, expected: expected).none?
|
92
|
+
end
|
93
|
+
alias match? matches?
|
94
|
+
|
95
|
+
# (see Stannum::Constraints::Base#negated_errors_for)
|
96
|
+
def negated_errors_for(actual, errors: nil) # rubocop:disable Metrics/MethodLength
|
97
|
+
errors ||= Stannum::Errors.new
|
98
|
+
|
99
|
+
return invalid_object_errors(errors) unless can_match_properties?(actual)
|
100
|
+
|
101
|
+
expected = expected_value(actual)
|
102
|
+
matching = each_matching_property(
|
103
|
+
actual: actual,
|
104
|
+
expected: expected,
|
105
|
+
include_all: true
|
106
|
+
)
|
107
|
+
|
108
|
+
return generic_errors(errors) if matching.count.zero?
|
109
|
+
|
110
|
+
matching.each do |property_name, _|
|
111
|
+
errors[property_name].add(negated_type, message: negated_message)
|
112
|
+
end
|
113
|
+
|
114
|
+
errors
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints/properties'
|
4
|
+
require 'stannum/constraints/properties/base'
|
5
|
+
|
6
|
+
module Stannum::Constraints::Properties
|
7
|
+
# Abstract base class for property matching constraints.
|
8
|
+
class Matching < Stannum::Constraints::Properties::Base
|
9
|
+
# @param reference_name [String, Symbol] the name of the reference property
|
10
|
+
# to compare to.
|
11
|
+
# @param property_names [Array<String, Symbol>] the name or names of the
|
12
|
+
# properties to compare.
|
13
|
+
# @param options [Hash<Symbol, Object>] configuration options for the
|
14
|
+
# constraint. Defaults to an empty Hash.
|
15
|
+
#
|
16
|
+
# @option options allow_empty [true, false] if true, will match against an
|
17
|
+
# object with empty property values, such as an empty string.
|
18
|
+
# @option options allow_nil [true, false] if true, will match against an
|
19
|
+
# object with nil property values.
|
20
|
+
def initialize(reference_name, *property_names, **options)
|
21
|
+
@reference_name = reference_name
|
22
|
+
|
23
|
+
validate_reference_name
|
24
|
+
|
25
|
+
super(*property_names, reference_name: reference_name, **options)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [String, Symbol] the name of the reference property to compare to.
|
29
|
+
attr_reader :reference_name
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def each_matching_property( # rubocop:disable Metrics/MethodLength
|
34
|
+
actual:,
|
35
|
+
expected:,
|
36
|
+
include_all: false,
|
37
|
+
&block
|
38
|
+
)
|
39
|
+
unless block_given?
|
40
|
+
return to_enum(
|
41
|
+
__method__,
|
42
|
+
actual: actual,
|
43
|
+
expected: expected,
|
44
|
+
include_all: include_all
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
enumerator = each_property(actual)
|
49
|
+
|
50
|
+
unless include_all
|
51
|
+
enumerator = enumerator.reject { |_, value| skip_property?(value) }
|
52
|
+
end
|
53
|
+
|
54
|
+
enumerator = enumerator.select { |_, value| valid?(expected, value) }
|
55
|
+
|
56
|
+
block_given? ? enumerator.each(&block) : enumerator
|
57
|
+
end
|
58
|
+
|
59
|
+
def each_non_matching_property( # rubocop:disable Metrics/MethodLength
|
60
|
+
actual:,
|
61
|
+
expected:,
|
62
|
+
include_all: false,
|
63
|
+
&block
|
64
|
+
)
|
65
|
+
unless block_given?
|
66
|
+
return to_enum(
|
67
|
+
__method__,
|
68
|
+
actual: actual,
|
69
|
+
expected: expected,
|
70
|
+
include_all: include_all
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
enumerator = each_property(actual)
|
75
|
+
|
76
|
+
unless include_all
|
77
|
+
enumerator = enumerator.reject { |_, value| skip_property?(value) }
|
78
|
+
end
|
79
|
+
|
80
|
+
enumerator = enumerator.reject { |_, value| valid?(expected, value) }
|
81
|
+
|
82
|
+
block_given? ? enumerator.each(&block) : enumerator
|
83
|
+
end
|
84
|
+
|
85
|
+
def expected_value(actual)
|
86
|
+
actual[reference_name]
|
87
|
+
end
|
88
|
+
|
89
|
+
def filter_parameters?
|
90
|
+
return @filter_parameters unless @filter_parameters.nil?
|
91
|
+
|
92
|
+
filters = filtered_parameters.map { |param| Regexp.new(param.to_s) }
|
93
|
+
|
94
|
+
@filter_parameters =
|
95
|
+
[reference_name, *property_names].any? do |property_name|
|
96
|
+
filters.any? { |filter| filter.match?(property_name.to_s) }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def generic_errors(errors)
|
101
|
+
errors.add(Stannum::Constraints::Base::NEGATED_TYPE)
|
102
|
+
end
|
103
|
+
|
104
|
+
def valid?(expected, value)
|
105
|
+
value == expected
|
106
|
+
end
|
107
|
+
|
108
|
+
def validate_reference_name
|
109
|
+
tools.assertions.validate_name(reference_name, as: 'reference name')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/constraints'
|
4
|
+
|
5
|
+
module Stannum::Constraints
|
6
|
+
# Namespace for Object property-specific constraints.
|
7
|
+
module Properties
|
8
|
+
autoload :Base,
|
9
|
+
'stannum/constraints/properties/base'
|
10
|
+
autoload :DoNotMatchProperty,
|
11
|
+
'stannum/constraints/properties/do_not_match_property'
|
12
|
+
autoload :MatchProperty,
|
13
|
+
'stannum/constraints/properties/match_property'
|
14
|
+
autoload :Matching,
|
15
|
+
'stannum/constraints/properties/matching'
|
16
|
+
end
|
17
|
+
end
|
@@ -78,7 +78,7 @@ module Stannum::Constraints::Tuples
|
|
78
78
|
def each_extra_item(actual, &block)
|
79
79
|
return if matches?(actual)
|
80
80
|
|
81
|
-
actual[expected_count
|
81
|
+
actual[expected_count..].each.with_index(expected_count, &block)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
@@ -184,13 +184,17 @@ module Stannum::Constraints::Types
|
|
184
184
|
|
185
185
|
def update_key_errors_for(actual:, errors:)
|
186
186
|
non_matching_keys(actual).each do |key|
|
187
|
-
|
187
|
+
mapped_key = Stannum::Support::Coercion.error_key(key)
|
188
|
+
|
189
|
+
key_type.errors_for(key, errors: errors[:keys][mapped_key])
|
188
190
|
end
|
189
191
|
end
|
190
192
|
|
191
193
|
def update_value_errors_for(actual:, errors:)
|
192
194
|
non_matching_values(actual).each do |key, value|
|
193
|
-
|
195
|
+
mapped_key = Stannum::Support::Coercion.error_key(key)
|
196
|
+
|
197
|
+
value_type.errors_for(value, errors: errors[mapped_key])
|
194
198
|
end
|
195
199
|
end
|
196
200
|
|
data/lib/stannum/constraints.rb
CHANGED
@@ -15,7 +15,9 @@ module Stannum
|
|
15
15
|
autoload :Hashes, 'stannum/constraints/hashes'
|
16
16
|
autoload :Identity, 'stannum/constraints/identity'
|
17
17
|
autoload :Nothing, 'stannum/constraints/nothing'
|
18
|
+
autoload :Parameters, 'stannum/constraints/parameters'
|
18
19
|
autoload :Presence, 'stannum/constraints/presence'
|
20
|
+
autoload :Properties, 'stannum/constraints/properties'
|
19
21
|
autoload :Signature, 'stannum/constraints/signature'
|
20
22
|
autoload :Signatures, 'stannum/constraints/signatures'
|
21
23
|
autoload :Tuples, 'stannum/constraints/tuples'
|
@@ -18,6 +18,17 @@ module Stannum::Contracts
|
|
18
18
|
# @return [Stannum::Contract] The contract to which constraints are added.
|
19
19
|
attr_reader :contract
|
20
20
|
|
21
|
+
# Concatenate the constraints from the given other contract.
|
22
|
+
#
|
23
|
+
# @param other [Stannum::Contract] the other contract.
|
24
|
+
#
|
25
|
+
# @return [self] the contract builder.
|
26
|
+
#
|
27
|
+
# @see Stannum::Contracts::Base#concat.
|
28
|
+
def concat(other)
|
29
|
+
contract.concat(other)
|
30
|
+
end
|
31
|
+
|
21
32
|
# Adds a constraint to the contract.
|
22
33
|
#
|
23
34
|
# @overload constraint(constraint, **options)
|
@@ -47,8 +58,8 @@ module Stannum::Contracts
|
|
47
58
|
private
|
48
59
|
|
49
60
|
def ambiguous_values_error(constraint)
|
50
|
-
'expected either a block or a constraint instance, but received both a' \
|
51
|
-
"
|
61
|
+
'expected either a block or a constraint instance, but received both a ' \
|
62
|
+
"block and #{constraint.inspect}"
|
52
63
|
end
|
53
64
|
|
54
65
|
def resolve_constraint(constraint = nil, **options, &block)
|
@@ -121,6 +121,20 @@ module Stannum::Contracts
|
|
121
121
|
options[:value_type]
|
122
122
|
end
|
123
123
|
|
124
|
+
protected
|
125
|
+
|
126
|
+
def map_errors(errors, **options)
|
127
|
+
return super unless options[:property_type] == :key
|
128
|
+
|
129
|
+
property_name = options.fetch(:property_name, options[:property])
|
130
|
+
property_name = property_name.nil? ? [nil] : Array(property_name)
|
131
|
+
property_name = property_name.map do |key|
|
132
|
+
Stannum::Support::Coercion.error_key(key)
|
133
|
+
end
|
134
|
+
|
135
|
+
errors.dig(*property_name)
|
136
|
+
end
|
137
|
+
|
124
138
|
private
|
125
139
|
|
126
140
|
def add_type_constraint
|
@@ -74,5 +74,18 @@ module Stannum::Contracts
|
|
74
74
|
actual.fetch(property) { actual[property.to_s] }
|
75
75
|
end
|
76
76
|
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def add_extra_keys_constraint
|
81
|
+
return if options[:allow_extra_keys]
|
82
|
+
|
83
|
+
keys = -> { expected_keys }
|
84
|
+
|
85
|
+
add_constraint(
|
86
|
+
Stannum::Constraints::Hashes::IndifferentExtraKeys.new(keys),
|
87
|
+
concatenatable: false
|
88
|
+
)
|
89
|
+
end
|
77
90
|
end
|
78
91
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'stannum/constraints/parameters/extra_arguments'
|
3
4
|
require 'stannum/contracts/parameters'
|
4
5
|
require 'stannum/support/coercion'
|
5
6
|
|
@@ -8,9 +9,6 @@ module Stannum::Contracts::Parameters
|
|
8
9
|
#
|
9
10
|
# An ArgumentsContract constrains the arguments given for a method.
|
10
11
|
class ArgumentsContract < Stannum::Contracts::TupleContract
|
11
|
-
# The :type of the error generated for extra arguments.
|
12
|
-
EXTRA_ARGUMENTS_TYPE = 'stannum.constraints.parameters.extra_arguments'
|
13
|
-
|
14
12
|
# Value used when arguments array does not have a value for the given index.
|
15
13
|
UNDEFINED = Object.new.freeze
|
16
14
|
|
@@ -154,10 +152,7 @@ module Stannum::Contracts::Parameters
|
|
154
152
|
count = -> { expected_count }
|
155
153
|
|
156
154
|
@variadic_constraint = Stannum::Constraints::Delegator.new(
|
157
|
-
Stannum::Constraints::
|
158
|
-
count,
|
159
|
-
type: EXTRA_ARGUMENTS_TYPE
|
160
|
-
)
|
155
|
+
Stannum::Constraints::Parameters::ExtraArguments.new(count)
|
161
156
|
)
|
162
157
|
|
163
158
|
add_constraint @variadic_constraint
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'stannum/constraints/parameters/extra_keywords'
|
3
4
|
require 'stannum/contracts/indifferent_hash_contract'
|
4
5
|
require 'stannum/contracts/parameters'
|
5
6
|
|
@@ -8,9 +9,6 @@ module Stannum::Contracts::Parameters
|
|
8
9
|
#
|
9
10
|
# A KeywordsContract constrains the keywords given for a method.
|
10
11
|
class KeywordsContract < Stannum::Contracts::IndifferentHashContract
|
11
|
-
# The :type of the error generated for extra keywords.
|
12
|
-
EXTRA_KEYWORDS_TYPE = 'stannum.constraints.parameters.extra_keywords'
|
13
|
-
|
14
12
|
# Value used when keywords hash does not have a value for the given key.
|
15
13
|
UNDEFINED = Object.new.freeze
|
16
14
|
|
@@ -156,10 +154,7 @@ module Stannum::Contracts::Parameters
|
|
156
154
|
keys = -> { expected_keys }
|
157
155
|
|
158
156
|
@variadic_constraint = Stannum::Constraints::Delegator.new(
|
159
|
-
Stannum::Constraints::
|
160
|
-
keys,
|
161
|
-
type: EXTRA_KEYWORDS_TYPE
|
162
|
-
)
|
157
|
+
Stannum::Constraints::Parameters::ExtraKeywords.new(keys)
|
163
158
|
)
|
164
159
|
|
165
160
|
add_constraint @variadic_constraint
|