shoulda-matchers 3.0.1 → 3.1.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/.gitignore +1 -0
- data/.travis.yml +3 -3
- data/CONTRIBUTING.md +60 -28
- data/Gemfile +1 -0
- data/Gemfile.lock +15 -12
- data/NEWS.md +111 -0
- data/README.md +94 -6
- data/Rakefile +10 -8
- data/custom_plan.rb +88 -0
- data/gemfiles/4.0.0.gemfile +1 -0
- data/gemfiles/4.0.0.gemfile.lock +21 -18
- data/gemfiles/4.0.1.gemfile +1 -0
- data/gemfiles/4.0.1.gemfile.lock +21 -18
- data/gemfiles/4.1.gemfile +1 -0
- data/gemfiles/4.1.gemfile.lock +21 -18
- data/gemfiles/4.2.gemfile +1 -0
- data/gemfiles/4.2.gemfile.lock +24 -21
- data/lib/shoulda/matchers/action_controller/permit_matcher.rb +6 -11
- data/lib/shoulda/matchers/active_model.rb +10 -1
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +258 -180
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +236 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +34 -14
- data/lib/shoulda/matchers/active_model/helpers.rb +9 -17
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +13 -6
- data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +13 -2
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +19 -35
- data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +13 -2
- data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +12 -2
- data/lib/shoulda/matchers/active_model/qualifiers.rb +12 -0
- data/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
- data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +30 -32
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +5 -8
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +22 -22
- data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +27 -16
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +58 -15
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +22 -12
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +165 -87
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +7 -9
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +111 -49
- data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +60 -0
- data/lib/shoulda/matchers/active_model/validator.rb +71 -52
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +19 -5
- data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +450 -124
- data/lib/shoulda/matchers/util.rb +43 -0
- data/lib/shoulda/matchers/util/word_wrap.rb +59 -31
- data/lib/shoulda/matchers/version.rb +1 -1
- data/script/update_gem_in_all_appraisals +1 -1
- data/script/update_gems_in_all_appraisals +1 -1
- data/spec/acceptance/multiple_libraries_integration_spec.rb +5 -2
- data/spec/acceptance/rails_integration_spec.rb +6 -2
- data/spec/spec_helper.rb +1 -3
- data/spec/support/acceptance/helpers/step_helpers.rb +4 -1
- data/spec/support/tests/current_bundle.rb +21 -7
- data/spec/support/unit/active_record/create_table.rb +54 -0
- data/spec/support/unit/attribute.rb +47 -0
- data/spec/support/unit/capture.rb +6 -0
- data/spec/support/unit/change_value.rb +111 -0
- data/spec/support/unit/create_model_arguments/basic.rb +135 -0
- data/spec/support/unit/create_model_arguments/has_many.rb +15 -0
- data/spec/support/unit/create_model_arguments/uniqueness_matcher.rb +74 -0
- data/spec/support/unit/helpers/active_record_versions.rb +1 -1
- data/spec/support/unit/helpers/class_builder.rb +61 -47
- data/spec/support/unit/helpers/database_helpers.rb +5 -3
- data/spec/support/unit/helpers/model_builder.rb +77 -97
- data/spec/support/unit/helpers/validation_matcher_scenario_helpers.rb +44 -0
- data/spec/support/unit/load_environment.rb +12 -0
- data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +2 -2
- data/spec/support/unit/matchers/fail_with_message_matcher.rb +12 -1
- data/spec/support/unit/model_creation_strategies/active_model.rb +111 -0
- data/spec/support/unit/model_creation_strategies/active_record.rb +77 -0
- data/spec/support/unit/model_creators.rb +19 -0
- data/spec/support/unit/model_creators/active_model.rb +39 -0
- data/spec/support/unit/model_creators/active_record.rb +43 -0
- data/spec/support/unit/model_creators/active_record/has_and_belongs_to_many.rb +95 -0
- data/spec/support/unit/model_creators/active_record/has_many.rb +67 -0
- data/spec/support/unit/model_creators/active_record/uniqueness_matcher.rb +42 -0
- data/spec/support/unit/model_creators/basic.rb +97 -0
- data/spec/support/unit/rails_application.rb +1 -1
- data/spec/support/unit/record_validating_confirmation_builder.rb +3 -7
- data/spec/support/unit/shared_examples/ignoring_interference_by_writer.rb +79 -0
- data/spec/support/unit/validation_matcher_scenario.rb +62 -0
- data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +4 -0
- data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +575 -140
- data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +115 -15
- data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +42 -4
- data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +92 -6
- data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +122 -10
- data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +306 -58
- data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +122 -3
- data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +805 -131
- data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +196 -29
- data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +82 -40
- data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +600 -101
- data/spec/unit/shoulda/matchers/util/word_wrap_spec.rb +88 -33
- data/spec/unit_spec_helper.rb +10 -22
- data/zeus.json +11 -0
- metadata +64 -23
- data/lib/shoulda/matchers/active_model/strict_validator.rb +0 -51
- data/spec/support/unit/shared_examples/numerical_type_submatcher.rb +0 -15
- data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +0 -288
- data/spec/unit/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +0 -100
- data/spec/unit/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +0 -100
- data/spec/unit/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +0 -100
@@ -0,0 +1,45 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel
|
4
|
+
class AllowValueMatcher
|
5
|
+
# @private
|
6
|
+
class AttributeChangedValueError < Shoulda::Matchers::Error
|
7
|
+
attr_accessor :matcher_name, :model, :attribute_name, :value_written,
|
8
|
+
:value_read
|
9
|
+
|
10
|
+
def message
|
11
|
+
Shoulda::Matchers.word_wrap <<-MESSAGE
|
12
|
+
The #{matcher_name} matcher attempted to set :#{attribute_name} on
|
13
|
+
#{model.name} to #{value_written.inspect}, but when the attribute was
|
14
|
+
read back, it had stored #{value_read.inspect} instead.
|
15
|
+
|
16
|
+
This creates a problem because it means that the model is behaving in a
|
17
|
+
way that is interfering with the test -- there's a mismatch between the
|
18
|
+
test that you wrote and test that we actually ran.
|
19
|
+
|
20
|
+
There are a couple of reasons why this could be happening:
|
21
|
+
|
22
|
+
* ActiveRecord is typecasting the incoming value.
|
23
|
+
* The writer method for :#{attribute_name} has been overridden so that
|
24
|
+
incoming values are changed in some way.
|
25
|
+
|
26
|
+
If this exception makes sense to you and you wish to bypass it, try
|
27
|
+
adding the `ignoring_interference_by_writer` qualifier onto the end of
|
28
|
+
your matcher. If the test still does not pass after that, then you may
|
29
|
+
need to do something different.
|
30
|
+
|
31
|
+
If you need help, feel free to ask a question on the shoulda-matchers
|
32
|
+
issues list:
|
33
|
+
|
34
|
+
http://github.com/thoughtbot/shoulda-matchers/issues
|
35
|
+
MESSAGE
|
36
|
+
end
|
37
|
+
|
38
|
+
def successful?
|
39
|
+
false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel
|
4
|
+
class AllowValueMatcher
|
5
|
+
# @private
|
6
|
+
class AttributeDoesNotExistError < Shoulda::Matchers::Error
|
7
|
+
attr_accessor :model, :attribute_name, :value
|
8
|
+
|
9
|
+
def message
|
10
|
+
Shoulda::Matchers.word_wrap <<-MESSAGE
|
11
|
+
The matcher attempted to set :#{attribute_name} on the #{model.name} to
|
12
|
+
#{value.inspect}, but that attribute does not exist.
|
13
|
+
MESSAGE
|
14
|
+
end
|
15
|
+
|
16
|
+
def successful?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel
|
4
|
+
class AllowValueMatcher
|
5
|
+
# @private
|
6
|
+
class AttributeSetter
|
7
|
+
def self.set(args)
|
8
|
+
new(args).set
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader(
|
12
|
+
:attribute_name,
|
13
|
+
:result_of_checking,
|
14
|
+
:result_of_setting,
|
15
|
+
:value_written,
|
16
|
+
)
|
17
|
+
|
18
|
+
def initialize(args)
|
19
|
+
@args = args
|
20
|
+
@matcher_name = args.fetch(:matcher_name)
|
21
|
+
@object = args.fetch(:object)
|
22
|
+
@attribute_name = args.fetch(:attribute_name)
|
23
|
+
@value_written = args.fetch(:value)
|
24
|
+
@ignore_interference_by_writer = args.fetch(
|
25
|
+
:ignore_interference_by_writer,
|
26
|
+
Qualifiers::IgnoreInterferenceByWriter.new
|
27
|
+
)
|
28
|
+
@after_set_callback = args.fetch(:after_set_callback, -> { })
|
29
|
+
|
30
|
+
@result_of_checking = nil
|
31
|
+
@result_of_setting = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def description
|
35
|
+
description = ":#{attribute_name} to "
|
36
|
+
description << Shoulda::Matchers::Util.inspect_value(value_written)
|
37
|
+
|
38
|
+
if attribute_changed_value?
|
39
|
+
description << " -- which was read back as "
|
40
|
+
description << Shoulda::Matchers::Util.inspect_value(value_read)
|
41
|
+
description << " --"
|
42
|
+
end
|
43
|
+
|
44
|
+
description
|
45
|
+
end
|
46
|
+
|
47
|
+
def run
|
48
|
+
check && set
|
49
|
+
end
|
50
|
+
|
51
|
+
def run!
|
52
|
+
check && set!
|
53
|
+
end
|
54
|
+
|
55
|
+
def check
|
56
|
+
if attribute_exists?
|
57
|
+
@result_of_checking = successful_check
|
58
|
+
true
|
59
|
+
else
|
60
|
+
@result_of_checking = attribute_does_not_exist_error
|
61
|
+
false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def set!
|
66
|
+
if attribute_exists?
|
67
|
+
set
|
68
|
+
|
69
|
+
unless result_of_setting.successful?
|
70
|
+
raise result_of_setting
|
71
|
+
end
|
72
|
+
|
73
|
+
@result_of_checking = successful_check
|
74
|
+
@result_of_setting = successful_setting
|
75
|
+
|
76
|
+
true
|
77
|
+
else
|
78
|
+
attribute_does_not_exist!
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def set
|
83
|
+
object.public_send("#{attribute_name}=", value_written)
|
84
|
+
after_set_callback.call
|
85
|
+
|
86
|
+
@result_of_checking = successful_check
|
87
|
+
|
88
|
+
if raise_attribute_changed_value_error?
|
89
|
+
@result_of_setting = attribute_changed_value_error
|
90
|
+
false
|
91
|
+
else
|
92
|
+
@result_of_setting = successful_setting
|
93
|
+
true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def failure_message
|
98
|
+
if successful?
|
99
|
+
raise "We're not supposed to be here!"
|
100
|
+
elsif result_of_setting
|
101
|
+
result_of_setting.message
|
102
|
+
else
|
103
|
+
result_of_checking.message
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def successful?
|
108
|
+
successfully_checked? && successfully_set?
|
109
|
+
end
|
110
|
+
|
111
|
+
def unsuccessful?
|
112
|
+
!successful?
|
113
|
+
end
|
114
|
+
|
115
|
+
def checked?
|
116
|
+
!result_of_checking.nil?
|
117
|
+
end
|
118
|
+
|
119
|
+
def successfully_checked?
|
120
|
+
checked? && result_of_checking.successful?
|
121
|
+
end
|
122
|
+
|
123
|
+
def unsuccessfully_checked?
|
124
|
+
!successfully_checked?
|
125
|
+
end
|
126
|
+
|
127
|
+
def set?
|
128
|
+
!result_of_setting.nil?
|
129
|
+
end
|
130
|
+
|
131
|
+
def successfully_set?
|
132
|
+
set? && result_of_setting.successful?
|
133
|
+
end
|
134
|
+
|
135
|
+
def value_read
|
136
|
+
@_value_read ||= object.public_send(attribute_name)
|
137
|
+
end
|
138
|
+
|
139
|
+
def attribute_changed_value?
|
140
|
+
value_written != value_read
|
141
|
+
end
|
142
|
+
|
143
|
+
protected
|
144
|
+
|
145
|
+
attr_reader :args, :matcher_name, :object, :after_set_callback
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def model
|
150
|
+
object.class
|
151
|
+
end
|
152
|
+
|
153
|
+
def attribute_exists?
|
154
|
+
if active_resource_object?
|
155
|
+
object.known_attributes.include?(attribute_name.to_s)
|
156
|
+
else
|
157
|
+
object.respond_to?("#{attribute_name}=")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def ignore_interference_by_writer
|
162
|
+
@ignore_interference_by_writer
|
163
|
+
end
|
164
|
+
|
165
|
+
def raise_attribute_changed_value_error?
|
166
|
+
attribute_changed_value? &&
|
167
|
+
!(attribute_is_an_enum? && value_read_is_expected_for_an_enum?) &&
|
168
|
+
!ignore_interference_by_writer.considering?(value_read)
|
169
|
+
end
|
170
|
+
|
171
|
+
def attribute_is_an_enum?
|
172
|
+
enum_values.any?
|
173
|
+
end
|
174
|
+
|
175
|
+
def value_read_is_expected_for_an_enum?
|
176
|
+
enum_values.key?(value_read) &&
|
177
|
+
enum_values[value_read] == value_written
|
178
|
+
end
|
179
|
+
|
180
|
+
def enum_values
|
181
|
+
defined_enums.fetch(attribute_name.to_s, {})
|
182
|
+
end
|
183
|
+
|
184
|
+
def defined_enums
|
185
|
+
if model.respond_to?(:defined_enums)
|
186
|
+
model.defined_enums
|
187
|
+
else
|
188
|
+
{}
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def successful_check
|
193
|
+
SuccessfulCheck.new
|
194
|
+
end
|
195
|
+
|
196
|
+
def successful_setting
|
197
|
+
SuccessfulSetting.new
|
198
|
+
end
|
199
|
+
|
200
|
+
def attribute_changed_value!
|
201
|
+
raise attribute_changed_value_error
|
202
|
+
end
|
203
|
+
|
204
|
+
def attribute_changed_value_error
|
205
|
+
AttributeChangedValueError.create(
|
206
|
+
model: object.class,
|
207
|
+
attribute_name: attribute_name,
|
208
|
+
value_written: value_written,
|
209
|
+
value_read: value_read
|
210
|
+
)
|
211
|
+
end
|
212
|
+
|
213
|
+
def attribute_does_not_exist!
|
214
|
+
raise attribute_does_not_exist_error
|
215
|
+
end
|
216
|
+
|
217
|
+
def attribute_does_not_exist_error
|
218
|
+
AttributeDoesNotExistError.create(
|
219
|
+
model: object.class,
|
220
|
+
attribute_name: attribute_name,
|
221
|
+
value: value_written
|
222
|
+
)
|
223
|
+
end
|
224
|
+
|
225
|
+
def active_resource_object?
|
226
|
+
object.respond_to?(:known_attributes)
|
227
|
+
end
|
228
|
+
|
229
|
+
def model
|
230
|
+
object.class
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Shoulda
|
4
|
+
module Matchers
|
5
|
+
module ActiveModel
|
6
|
+
class AllowValueMatcher
|
7
|
+
# @private
|
8
|
+
class AttributeSetterAndValidator
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def_delegators(
|
12
|
+
:allow_value_matcher,
|
13
|
+
:after_setting_value_callback,
|
14
|
+
:attribute_to_check_message_against,
|
15
|
+
:context,
|
16
|
+
:expected_message,
|
17
|
+
:expects_strict?,
|
18
|
+
:ignore_interference_by_writer,
|
19
|
+
:instance,
|
20
|
+
)
|
21
|
+
|
22
|
+
def initialize(allow_value_matcher, attribute_name, value)
|
23
|
+
@allow_value_matcher = allow_value_matcher
|
24
|
+
@attribute_name = attribute_name
|
25
|
+
@value = value
|
26
|
+
@_attribute_setter = nil
|
27
|
+
@_validator = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def attribute_setter
|
31
|
+
@_attribute_setter ||= AttributeSetter.new(
|
32
|
+
matcher_name: :allow_value,
|
33
|
+
object: instance,
|
34
|
+
attribute_name: attribute_name,
|
35
|
+
value: value,
|
36
|
+
ignore_interference_by_writer: ignore_interference_by_writer,
|
37
|
+
after_set_callback: after_setting_value_callback
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def attribute_setter_description
|
42
|
+
attribute_setter.description
|
43
|
+
end
|
44
|
+
|
45
|
+
def validator
|
46
|
+
@_validator ||= Validator.new(
|
47
|
+
instance,
|
48
|
+
attribute_to_check_message_against,
|
49
|
+
context: context,
|
50
|
+
expects_strict: expects_strict?,
|
51
|
+
expected_message: expected_message
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
attr_reader :allow_value_matcher, :attribute_name, :value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel
|
4
|
+
class AllowValueMatcher
|
5
|
+
# @private
|
6
|
+
class AttributeSetters
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def initialize(allow_value_matcher, values)
|
10
|
+
@tuples = values.map do |attribute_name, value|
|
11
|
+
AttributeSetterAndValidator.new(
|
12
|
+
allow_value_matcher,
|
13
|
+
attribute_name,
|
14
|
+
value
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def each(&block)
|
20
|
+
tuples.each(&block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def first_failing
|
24
|
+
tuples.detect(&method(:does_not_match?))
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
attr_reader :tuples
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def does_not_match?(tuple)
|
34
|
+
!tuple.attribute_setter.set!
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel
|
4
|
+
class AllowValueMatcher
|
5
|
+
# @private
|
6
|
+
class AttributeSettersAndValidators
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def initialize(allow_value_matcher, values)
|
10
|
+
@tuples = values.map do |attribute_name, value|
|
11
|
+
AttributeSetterAndValidator.new(
|
12
|
+
allow_value_matcher,
|
13
|
+
attribute_name,
|
14
|
+
value
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def each(&block)
|
20
|
+
tuples.each(&block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def first_passing
|
24
|
+
tuples.detect(&method(:matches?))
|
25
|
+
end
|
26
|
+
|
27
|
+
def first_failing
|
28
|
+
tuples.detect(&method(:does_not_match?))
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
attr_reader :tuples
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def matches?(tuple)
|
38
|
+
tuple.attribute_setter.set! && tuple.validator.call
|
39
|
+
end
|
40
|
+
|
41
|
+
def does_not_match?(tuple)
|
42
|
+
!matches?(tuple)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|