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
@@ -66,88 +66,193 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
66
66
|
end
|
67
67
|
|
68
68
|
context 'when too narrow of a scope is specified' do
|
69
|
-
it 'rejects' do
|
69
|
+
it 'rejects with an appropriate failure message' do
|
70
70
|
record = build_record_validating_uniqueness(
|
71
71
|
scopes: [
|
72
72
|
build_attribute(name: :scope1),
|
73
|
-
|
73
|
+
build_attribute(name: :scope2)
|
74
74
|
],
|
75
|
+
additional_attributes: [:other]
|
75
76
|
)
|
76
|
-
|
77
|
-
|
78
|
-
|
77
|
+
|
78
|
+
assertion = lambda do
|
79
|
+
expect(record).
|
80
|
+
to validate_uniqueness.
|
81
|
+
scoped_to(:scope1, :scope2, :other)
|
82
|
+
end
|
83
|
+
|
84
|
+
message = <<-MESSAGE
|
85
|
+
Example did not properly validate that :attr is case-sensitively unique
|
86
|
+
within the scope of :scope1, :scope2, and :other.
|
87
|
+
Expected the validation to be scoped to :scope1, :scope2, and :other,
|
88
|
+
but it was scoped to :scope1 and :scope2 instead.
|
89
|
+
MESSAGE
|
90
|
+
|
91
|
+
expect(&assertion).to fail_with_message(message)
|
79
92
|
end
|
80
93
|
end
|
81
94
|
|
82
95
|
context 'when too broad of a scope is specified' do
|
83
|
-
it 'rejects' do
|
96
|
+
it 'rejects with an appropriate failure message' do
|
84
97
|
record = build_record_validating_uniqueness(
|
85
98
|
scopes: [
|
86
99
|
build_attribute(name: :scope1),
|
87
|
-
|
100
|
+
build_attribute(name: :scope2)
|
88
101
|
],
|
89
102
|
)
|
90
|
-
|
91
|
-
|
92
|
-
|
103
|
+
|
104
|
+
assertion = lambda do
|
105
|
+
expect(record).
|
106
|
+
to validate_uniqueness.
|
107
|
+
scoped_to(:scope1)
|
108
|
+
end
|
109
|
+
|
110
|
+
message = <<-MESSAGE
|
111
|
+
Example did not properly validate that :attr is case-sensitively unique
|
112
|
+
within the scope of :scope1.
|
113
|
+
Expected the validation to be scoped to :scope1, but it was scoped to
|
114
|
+
:scope1 and :scope2 instead.
|
115
|
+
MESSAGE
|
116
|
+
|
117
|
+
expect(&assertion).to fail_with_message(message)
|
93
118
|
end
|
94
119
|
end
|
95
120
|
|
96
121
|
context 'when a different scope is specified' do
|
97
|
-
it 'rejects' do
|
122
|
+
it 'rejects with an appropriate failure message' do
|
98
123
|
record = build_record_validating_uniqueness(
|
99
|
-
scopes: [ build_attribute(name: :
|
100
|
-
additional_attributes: [:
|
124
|
+
scopes: [ build_attribute(name: :other) ],
|
125
|
+
additional_attributes: [:scope]
|
101
126
|
)
|
102
|
-
|
103
|
-
|
104
|
-
|
127
|
+
assertion = lambda do
|
128
|
+
expect(record).
|
129
|
+
to validate_uniqueness.
|
130
|
+
scoped_to(:scope)
|
131
|
+
end
|
132
|
+
|
133
|
+
message = <<-MESSAGE
|
134
|
+
Example did not properly validate that :attr is case-sensitively unique
|
135
|
+
within the scope of :scope.
|
136
|
+
Expected the validation to be scoped to :scope, but it was scoped to
|
137
|
+
:other instead.
|
138
|
+
MESSAGE
|
139
|
+
|
140
|
+
expect(&assertion).to fail_with_message(message)
|
105
141
|
end
|
106
142
|
end
|
107
143
|
|
108
144
|
context 'when no scope is specified' do
|
109
|
-
it 'rejects' do
|
145
|
+
it 'rejects with an appropriate failure message' do
|
110
146
|
record = build_record_validating_uniqueness(
|
111
147
|
scopes: [ build_attribute(name: :scope) ]
|
112
148
|
)
|
113
|
-
|
149
|
+
|
150
|
+
assertion = lambda do
|
151
|
+
expect(record).to validate_uniqueness
|
152
|
+
end
|
153
|
+
|
154
|
+
message = <<-MESSAGE
|
155
|
+
Example did not properly validate that :attr is case-sensitively unique.
|
156
|
+
Expected the validation not to be scoped to anything, but it was
|
157
|
+
scoped to :scope instead.
|
158
|
+
MESSAGE
|
159
|
+
|
160
|
+
expect(&assertion).to fail_with_message(message)
|
114
161
|
end
|
115
162
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
163
|
+
context 'if the scope attribute is unset in the record given to the matcher' do
|
164
|
+
it 'rejects with an appropriate failure message' do
|
165
|
+
record = build_record_validating_uniqueness(
|
166
|
+
scopes: [ build_attribute(name: :scope, value: nil) ]
|
167
|
+
)
|
168
|
+
|
169
|
+
assertion = lambda do
|
170
|
+
expect(record).to validate_uniqueness
|
171
|
+
end
|
172
|
+
|
173
|
+
message = <<-MESSAGE
|
174
|
+
Example did not properly validate that :attr is case-sensitively unique.
|
175
|
+
Expected the validation not to be scoped to anything, but it was
|
176
|
+
scoped to :scope instead.
|
177
|
+
MESSAGE
|
178
|
+
|
179
|
+
expect(&assertion).to fail_with_message(message)
|
180
|
+
end
|
121
181
|
end
|
122
182
|
end
|
123
183
|
|
124
184
|
context 'when a non-existent attribute is specified as a scope' do
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
185
|
+
context 'when there is more than one scope' do
|
186
|
+
it 'rejects with an appropriate failure message (and does not raise an error)' do
|
187
|
+
record = build_record_validating_uniqueness(
|
188
|
+
scopes: [ build_attribute(name: :scope) ]
|
189
|
+
)
|
190
|
+
|
191
|
+
assertion = lambda do
|
192
|
+
expect(record).to validate_uniqueness.scoped_to(:non_existent)
|
193
|
+
end
|
194
|
+
|
195
|
+
message = <<-MESSAGE.strip
|
196
|
+
Example did not properly validate that :attr is case-sensitively unique
|
197
|
+
within the scope of :non_existent.
|
198
|
+
:non_existent does not seem to be an attribute on Example.
|
199
|
+
MESSAGE
|
200
|
+
|
201
|
+
expect(&assertion).to fail_with_message(message)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'when there is more than one scope' do
|
206
|
+
it 'rejects with an appropriate failure message (and does not raise an error)' do
|
207
|
+
record = build_record_validating_uniqueness(
|
208
|
+
scopes: [ build_attribute(name: :scope) ]
|
209
|
+
)
|
210
|
+
|
211
|
+
assertion = lambda do
|
212
|
+
expect(record).to validate_uniqueness.scoped_to(
|
213
|
+
:non_existent1,
|
214
|
+
:non_existent2
|
215
|
+
)
|
216
|
+
end
|
217
|
+
|
218
|
+
message = <<-MESSAGE.strip
|
219
|
+
Example did not properly validate that :attr is case-sensitively unique
|
220
|
+
within the scope of :non_existent1 and :non_existent2.
|
221
|
+
:non_existent1 and :non_existent2 do not seem to be attributes on
|
222
|
+
Example.
|
223
|
+
MESSAGE
|
224
|
+
|
225
|
+
expect(&assertion).to fail_with_message(message)
|
226
|
+
end
|
130
227
|
end
|
131
228
|
end
|
132
229
|
|
133
230
|
define_method(:build_attribute) do |attribute_options|
|
134
|
-
attribute_options.
|
231
|
+
attribute_options.deep_merge(
|
135
232
|
column_type: column_type,
|
136
233
|
value_type: value_type,
|
137
|
-
array: array
|
234
|
+
options: { array: array }
|
138
235
|
)
|
139
236
|
end
|
140
237
|
end
|
141
238
|
|
142
239
|
context 'when the model does not have a uniqueness validation' do
|
143
|
-
it 'rejects' do
|
144
|
-
model =
|
145
|
-
|
240
|
+
it 'rejects with an appropriate failure message' do
|
241
|
+
model = define_model_without_validation
|
242
|
+
model.create!(attribute_name => 'value')
|
243
|
+
|
244
|
+
assertion = lambda do
|
245
|
+
expect(model.new).to validate_uniqueness_of(attribute_name)
|
146
246
|
end
|
147
247
|
|
148
|
-
|
248
|
+
message = <<-MESSAGE
|
249
|
+
Example did not properly validate that :attr is case-sensitively unique.
|
250
|
+
Given an existing Example whose :attr is ‹"value"›, after making a new
|
251
|
+
Example and setting its :attr to ‹"value"› as well, the matcher
|
252
|
+
expected the new Example to be invalid, but it was valid instead.
|
253
|
+
MESSAGE
|
149
254
|
|
150
|
-
expect(
|
255
|
+
expect(&assertion).to fail_with_message(message)
|
151
256
|
end
|
152
257
|
end
|
153
258
|
|
@@ -179,13 +284,25 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
179
284
|
end
|
180
285
|
|
181
286
|
context 'when the validation has no scope and a scope is specified' do
|
182
|
-
it 'rejects' do
|
287
|
+
it 'rejects with an appropriate failure message' do
|
183
288
|
model = define_model_validating_uniqueness(
|
184
289
|
additional_attributes: [:other]
|
185
290
|
)
|
186
291
|
create_record_from(model)
|
187
292
|
record = build_record_from(model)
|
188
|
-
|
293
|
+
|
294
|
+
assertion = lambda do
|
295
|
+
expect(record).to validate_uniqueness.scoped_to(:other)
|
296
|
+
end
|
297
|
+
|
298
|
+
message = <<-MESSAGE
|
299
|
+
Example did not properly validate that :attr is case-sensitively unique
|
300
|
+
within the scope of :other.
|
301
|
+
Expected the validation to be scoped to :other, but it was not scoped
|
302
|
+
to anything.
|
303
|
+
MESSAGE
|
304
|
+
|
305
|
+
expect(&assertion).to fail_with_message(message)
|
189
306
|
end
|
190
307
|
end
|
191
308
|
end
|
@@ -219,23 +336,60 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
219
336
|
|
220
337
|
context 'and the validation has a custom message' do
|
221
338
|
context 'when no message is specified' do
|
222
|
-
it 'rejects' do
|
339
|
+
it 'rejects with an appropriate failure message' do
|
223
340
|
record = build_record_validating_uniqueness(
|
341
|
+
attribute_value: 'some value',
|
224
342
|
validation_options: { message: 'bad value' }
|
225
343
|
)
|
226
|
-
|
344
|
+
|
345
|
+
assertion = lambda do
|
346
|
+
expect(record).to validate_uniqueness
|
347
|
+
end
|
348
|
+
|
349
|
+
message = <<-MESSAGE
|
350
|
+
Example did not properly validate that :attr is case-sensitively unique.
|
351
|
+
After taking the given Example, whose :attr is ‹"some value"›, and
|
352
|
+
saving it as the existing record, then making a new Example and
|
353
|
+
setting its :attr to ‹"some value"› as well, the matcher expected the
|
354
|
+
new Example to be invalid and to produce the validation error "has
|
355
|
+
already been taken" on :attr. The record was indeed invalid, but it
|
356
|
+
produced these validation errors instead:
|
357
|
+
|
358
|
+
* attr: ["bad value"]
|
359
|
+
MESSAGE
|
360
|
+
|
361
|
+
expect(&assertion).to fail_with_message(message)
|
227
362
|
end
|
228
363
|
end
|
229
364
|
|
230
365
|
context 'given a string' do
|
231
366
|
context 'when the given and actual messages do not match' do
|
232
|
-
it 'rejects' do
|
367
|
+
it 'rejects with an appropriate failure message' do
|
233
368
|
record = build_record_validating_uniqueness(
|
234
|
-
|
369
|
+
attribute_value: 'some value',
|
370
|
+
validation_options: { message: 'something else entirely' }
|
235
371
|
)
|
236
|
-
|
237
|
-
|
238
|
-
|
372
|
+
|
373
|
+
assertion = lambda do
|
374
|
+
expect(record).
|
375
|
+
to validate_uniqueness.
|
376
|
+
with_message('some message')
|
377
|
+
end
|
378
|
+
|
379
|
+
message = <<-MESSAGE
|
380
|
+
Example did not properly validate that :attr is case-sensitively unique,
|
381
|
+
producing a custom validation error on failure.
|
382
|
+
After taking the given Example, whose :attr is ‹"some value"›, and
|
383
|
+
saving it as the existing record, then making a new Example and
|
384
|
+
setting its :attr to ‹"some value"› as well, the matcher expected the
|
385
|
+
new Example to be invalid and to produce the validation error "some
|
386
|
+
message" on :attr. The record was indeed invalid, but it produced
|
387
|
+
these validation errors instead:
|
388
|
+
|
389
|
+
* attr: ["something else entirely"]
|
390
|
+
MESSAGE
|
391
|
+
|
392
|
+
expect(&assertion).to fail_with_message(message)
|
239
393
|
end
|
240
394
|
end
|
241
395
|
|
@@ -253,13 +407,32 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
253
407
|
|
254
408
|
context 'given a regex' do
|
255
409
|
context 'when the given and actual messages do not match' do
|
256
|
-
it 'rejects' do
|
410
|
+
it 'rejects with an appropriate failure message' do
|
257
411
|
record = build_record_validating_uniqueness(
|
258
|
-
|
412
|
+
attribute_value: 'some value',
|
413
|
+
validation_options: { message: 'something else entirely' }
|
259
414
|
)
|
260
|
-
|
261
|
-
|
262
|
-
|
415
|
+
|
416
|
+
assertion = lambda do
|
417
|
+
expect(record).
|
418
|
+
to validate_uniqueness.
|
419
|
+
with_message(/some message/)
|
420
|
+
end
|
421
|
+
|
422
|
+
message = <<-MESSAGE
|
423
|
+
Example did not properly validate that :attr is case-sensitively unique,
|
424
|
+
producing a custom validation error on failure.
|
425
|
+
After taking the given Example, whose :attr is ‹"some value"›, and
|
426
|
+
saving it as the existing record, then making a new Example and
|
427
|
+
setting its :attr to ‹"some value"› as well, the matcher expected the
|
428
|
+
new Example to be invalid and to produce a validation error matching
|
429
|
+
‹/some message/› on :attr. The record was indeed invalid, but it
|
430
|
+
produced these validation errors instead:
|
431
|
+
|
432
|
+
* attr: ["something else entirely"]
|
433
|
+
MESSAGE
|
434
|
+
|
435
|
+
expect(&assertion).to fail_with_message(message)
|
263
436
|
end
|
264
437
|
end
|
265
438
|
|
@@ -275,6 +448,36 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
275
448
|
end
|
276
449
|
end
|
277
450
|
end
|
451
|
+
|
452
|
+
it_supports(
|
453
|
+
'ignoring_interference_by_writer',
|
454
|
+
tests: {
|
455
|
+
reject_if_qualified_but_changing_value_interferes: {
|
456
|
+
model_name: 'Example',
|
457
|
+
attribute_name: :attr,
|
458
|
+
default_value: 'some value',
|
459
|
+
changing_values_with: :next_value,
|
460
|
+
expected_message: <<-MESSAGE.strip
|
461
|
+
Example did not properly validate that :attr is case-sensitively unique.
|
462
|
+
After taking the given Example, whose :attr is ‹"some valuf"›, and
|
463
|
+
saving it as the existing record, then making a new Example and
|
464
|
+
setting its :attr to ‹"some valuf"› (read back as ‹"some valug"›) as
|
465
|
+
well, the matcher expected the new Example to be invalid, but it was
|
466
|
+
valid instead.
|
467
|
+
|
468
|
+
As indicated in the message above, :attr seems to be changing certain
|
469
|
+
values as they are set, and this could have something to do with why
|
470
|
+
this test is failing. If you or something else has overridden the
|
471
|
+
writer method for this attribute to normalize values by changing their
|
472
|
+
case in any way (for instance, ensuring that the attribute is always
|
473
|
+
downcased), then try adding `ignoring_case_sensitivity` onto the end
|
474
|
+
of the uniqueness matcher. Otherwise, you may need to write the test
|
475
|
+
yourself, or do something different altogether.
|
476
|
+
|
477
|
+
MESSAGE
|
478
|
+
}
|
479
|
+
}
|
480
|
+
)
|
278
481
|
end
|
279
482
|
|
280
483
|
context 'when the model has a scoped uniqueness validation' do
|
@@ -334,27 +537,49 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
334
537
|
end
|
335
538
|
|
336
539
|
context 'when too narrow of a scope is specified' do
|
337
|
-
it 'rejects' do
|
540
|
+
it 'rejects with an appropriate failure message' do
|
338
541
|
record = build_record_validating_scoped_uniqueness_with_enum(
|
339
542
|
enum_scope: :scope1,
|
340
543
|
additional_scopes: [:scope2],
|
341
544
|
additional_attributes: [:other]
|
342
545
|
)
|
343
|
-
|
344
|
-
|
345
|
-
|
546
|
+
|
547
|
+
assertion = lambda do
|
548
|
+
expect(record).
|
549
|
+
to validate_uniqueness.
|
550
|
+
scoped_to(:scope1, :scope2, :other)
|
551
|
+
end
|
552
|
+
|
553
|
+
message = <<-MESSAGE
|
554
|
+
Example did not properly validate that :attr is case-sensitively unique
|
555
|
+
within the scope of :scope1, :scope2, and :other.
|
556
|
+
Expected the validation to be scoped to :scope1, :scope2, and :other,
|
557
|
+
but it was scoped to :scope1 and :scope2 instead.
|
558
|
+
MESSAGE
|
559
|
+
|
560
|
+
expect(&assertion).to fail_with_message(message)
|
346
561
|
end
|
347
562
|
end
|
348
563
|
|
349
564
|
context 'when too broad of a scope is specified' do
|
350
|
-
it 'rejects' do
|
565
|
+
it 'rejects with an appropriate failure message' do
|
351
566
|
record = build_record_validating_scoped_uniqueness_with_enum(
|
352
567
|
enum_scope: :scope1,
|
353
568
|
additional_scopes: [:scope2]
|
354
569
|
)
|
355
|
-
|
356
|
-
|
357
|
-
scoped_to(:scope1)
|
570
|
+
|
571
|
+
assertion = lambda do
|
572
|
+
expect(record).to validate_uniqueness.scoped_to(:scope1)
|
573
|
+
end
|
574
|
+
|
575
|
+
message = <<-MESSAGE
|
576
|
+
Example did not properly validate that :attr is case-sensitively unique
|
577
|
+
within the scope of :scope1.
|
578
|
+
Expected the validation to be scoped to :scope1, but it was scoped to
|
579
|
+
:scope1 and :scope2 instead.
|
580
|
+
MESSAGE
|
581
|
+
|
582
|
+
expect(&assertion).to fail_with_message(message)
|
358
583
|
end
|
359
584
|
end
|
360
585
|
end
|
@@ -467,26 +692,55 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
467
692
|
end
|
468
693
|
|
469
694
|
context 'when the matcher is qualified with case_insensitive' do
|
470
|
-
it 'rejects' do
|
695
|
+
it 'rejects with an appropriate failure message' do
|
471
696
|
record = build_record_validating_uniqueness(
|
472
697
|
attribute_type: :string,
|
698
|
+
attribute_value: 'some value',
|
473
699
|
validation_options: { case_sensitive: true }
|
474
700
|
)
|
475
701
|
|
476
|
-
|
702
|
+
assertion = lambda do
|
703
|
+
expect(record).to validate_uniqueness.case_insensitive
|
704
|
+
end
|
705
|
+
|
706
|
+
message = <<-MESSAGE
|
707
|
+
Example did not properly validate that :attr is case-insensitively
|
708
|
+
unique.
|
709
|
+
After taking the given Example, whose :attr is ‹"some value"›, and
|
710
|
+
saving it as the existing record, then making a new Example and
|
711
|
+
setting its :attr to a different value, ‹"SOME VALUE"›, the matcher
|
712
|
+
expected the new Example to be invalid, but it was valid instead.
|
713
|
+
MESSAGE
|
714
|
+
|
715
|
+
expect(&assertion).to fail_with_message(message)
|
477
716
|
end
|
478
717
|
end
|
479
718
|
end
|
480
719
|
|
481
720
|
context 'when the model has a case-insensitive validation' do
|
482
721
|
context 'when case_insensitive is not specified' do
|
483
|
-
it 'rejects' do
|
722
|
+
it 'rejects with an appropriate failure message' do
|
484
723
|
record = build_record_validating_uniqueness(
|
485
724
|
attribute_type: :string,
|
486
725
|
validation_options: { case_sensitive: false }
|
487
726
|
)
|
488
727
|
|
489
|
-
|
728
|
+
assertion = lambda do
|
729
|
+
expect(record).to validate_uniqueness
|
730
|
+
end
|
731
|
+
|
732
|
+
message = <<-MESSAGE
|
733
|
+
Example did not properly validate that :attr is case-sensitively unique.
|
734
|
+
After taking the given Example, setting its :attr to ‹"an arbitrary
|
735
|
+
value"›, and saving it as the existing record, then making a new
|
736
|
+
Example and setting its :attr to a different value, ‹"AN ARBITRARY
|
737
|
+
VALUE"›, the matcher expected the new Example to be valid, but it was
|
738
|
+
invalid instead, producing these validation errors:
|
739
|
+
|
740
|
+
* attr: ["has already been taken"]
|
741
|
+
MESSAGE
|
742
|
+
|
743
|
+
expect(&assertion).to fail_with_message(message)
|
490
744
|
end
|
491
745
|
end
|
492
746
|
|
@@ -499,6 +753,44 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
499
753
|
|
500
754
|
expect(record).to validate_uniqueness.case_insensitive
|
501
755
|
end
|
756
|
+
|
757
|
+
it_supports(
|
758
|
+
'ignoring_interference_by_writer',
|
759
|
+
tests: {
|
760
|
+
reject_if_qualified_but_changing_value_interferes: {
|
761
|
+
model_name: 'Example',
|
762
|
+
attribute_name: :attr,
|
763
|
+
default_value: 'some value',
|
764
|
+
changing_values_with: :next_value,
|
765
|
+
expected_message: <<-MESSAGE.strip
|
766
|
+
Example did not properly validate that :attr is case-insensitively
|
767
|
+
unique.
|
768
|
+
After taking the given Example, whose :attr is ‹"some valuf"›, and
|
769
|
+
saving it as the existing record, then making a new Example and
|
770
|
+
setting its :attr to ‹"some valuf"› (read back as ‹"some valug"›) as
|
771
|
+
well, the matcher expected the new Example to be invalid, but it was
|
772
|
+
valid instead.
|
773
|
+
|
774
|
+
As indicated in the message above, :attr seems to be changing certain
|
775
|
+
values as they are set, and this could have something to do with why
|
776
|
+
this test is failing. If you or something else has overridden the
|
777
|
+
writer method for this attribute to normalize values by changing their
|
778
|
+
case in any way (for instance, ensuring that the attribute is always
|
779
|
+
downcased), then try adding `ignoring_case_sensitivity` onto the end
|
780
|
+
of the uniqueness matcher. Otherwise, you may need to write the test
|
781
|
+
yourself, or do something different altogether.
|
782
|
+
MESSAGE
|
783
|
+
}
|
784
|
+
}
|
785
|
+
)
|
786
|
+
|
787
|
+
def validation_matcher_scenario_args
|
788
|
+
super.deep_merge(validation_options: { case_sensitive: false })
|
789
|
+
end
|
790
|
+
|
791
|
+
def configure_validation_matcher(matcher)
|
792
|
+
super(matcher).case_insensitive
|
793
|
+
end
|
502
794
|
end
|
503
795
|
end
|
504
796
|
|
@@ -543,18 +835,50 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
543
835
|
|
544
836
|
context 'when the validation is not declared with allow_nil' do
|
545
837
|
context 'given a new record whose attribute is nil' do
|
546
|
-
it 'rejects' do
|
838
|
+
it 'rejects with an appropriate failure message' do
|
547
839
|
model = define_model_validating_uniqueness
|
548
840
|
record = build_record_from(model, attribute_name => nil)
|
549
|
-
|
841
|
+
|
842
|
+
assertion = lambda do
|
843
|
+
expect(record).to validate_uniqueness.allow_nil
|
844
|
+
end
|
845
|
+
|
846
|
+
message = <<-MESSAGE
|
847
|
+
Example did not properly validate that :attr is case-sensitively unique,
|
848
|
+
but only if it is not nil.
|
849
|
+
After taking the given Example, setting its :attr to ‹nil›, and saving
|
850
|
+
it as the existing record, then making a new Example and setting its
|
851
|
+
:attr to ‹nil› as well, the matcher expected the new Example to be
|
852
|
+
valid, but it was invalid instead, producing these validation errors:
|
853
|
+
|
854
|
+
* attr: ["has already been taken"]
|
855
|
+
MESSAGE
|
856
|
+
|
857
|
+
expect(&assertion).to fail_with_message(message)
|
550
858
|
end
|
551
859
|
end
|
552
860
|
|
553
861
|
context 'given an existing record whose attribute is nil' do
|
554
|
-
it 'rejects' do
|
862
|
+
it 'rejects with an appropriate failure message' do
|
555
863
|
model = define_model_validating_uniqueness
|
556
864
|
record = create_record_from(model, attribute_name => nil)
|
557
|
-
|
865
|
+
|
866
|
+
assertion = lambda do
|
867
|
+
expect(record).to validate_uniqueness.allow_nil
|
868
|
+
end
|
869
|
+
|
870
|
+
message = <<-MESSAGE
|
871
|
+
Example did not properly validate that :attr is case-sensitively unique,
|
872
|
+
but only if it is not nil.
|
873
|
+
Given an existing Example, after setting its :attr to ‹nil›, then
|
874
|
+
making a new Example and setting its :attr to ‹nil› as well, the
|
875
|
+
matcher expected the new Example to be valid, but it was invalid
|
876
|
+
instead, producing these validation errors:
|
877
|
+
|
878
|
+
* attr: ["has already been taken"]
|
879
|
+
MESSAGE
|
880
|
+
|
881
|
+
expect(&assertion).to fail_with_message(message)
|
558
882
|
end
|
559
883
|
end
|
560
884
|
end
|
@@ -640,38 +964,102 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
640
964
|
|
641
965
|
context 'when the validation is not declared with allow_blank' do
|
642
966
|
context 'given a new record whose attribute is nil' do
|
643
|
-
it 'rejects' do
|
967
|
+
it 'rejects with an appropriate failure message' do
|
644
968
|
model = define_model_validating_uniqueness
|
645
969
|
record = build_record_from(model, attribute_name => nil)
|
646
|
-
|
970
|
+
|
971
|
+
assertion = lambda do
|
972
|
+
expect(record).to validate_uniqueness.allow_blank
|
973
|
+
end
|
974
|
+
|
975
|
+
message = <<-MESSAGE
|
976
|
+
Example did not properly validate that :attr is case-sensitively unique,
|
977
|
+
but only if it is not blank.
|
978
|
+
After taking the given Example, setting its :attr to ‹""›, and saving
|
979
|
+
it as the existing record, then making a new Example and setting its
|
980
|
+
:attr to ‹""› as well, the matcher expected the new Example to be
|
981
|
+
valid, but it was invalid instead, producing these validation errors:
|
982
|
+
|
983
|
+
* attr: ["has already been taken"]
|
984
|
+
MESSAGE
|
985
|
+
|
986
|
+
expect(&assertion).to fail_with_message(message)
|
647
987
|
end
|
648
988
|
end
|
649
989
|
|
650
990
|
context 'given an existing record whose attribute is nil' do
|
651
|
-
it 'rejects' do
|
991
|
+
it 'rejects with an appropriate failure message' do
|
652
992
|
model = define_model_validating_uniqueness
|
653
993
|
record = create_record_from(model, attribute_name => nil)
|
654
|
-
|
994
|
+
|
995
|
+
assertion = lambda do
|
996
|
+
expect(record).to validate_uniqueness.allow_blank
|
997
|
+
end
|
998
|
+
|
999
|
+
message = <<-MESSAGE
|
1000
|
+
Example did not properly validate that :attr is case-sensitively unique,
|
1001
|
+
but only if it is not blank.
|
1002
|
+
Given an existing Example, after setting its :attr to ‹""›, then
|
1003
|
+
making a new Example and setting its :attr to ‹""› as well, the
|
1004
|
+
matcher expected the new Example to be valid, but it was invalid
|
1005
|
+
instead, producing these validation errors:
|
1006
|
+
|
1007
|
+
* attr: ["has already been taken"]
|
1008
|
+
MESSAGE
|
1009
|
+
|
1010
|
+
expect(&assertion).to fail_with_message(message)
|
655
1011
|
end
|
656
1012
|
end
|
657
1013
|
|
658
1014
|
context 'given a new record whose attribute is empty' do
|
659
|
-
it 'rejects' do
|
1015
|
+
it 'rejects with an appropriate failure message' do
|
660
1016
|
model = define_model_validating_uniqueness(
|
661
1017
|
attribute_type: :string
|
662
1018
|
)
|
663
1019
|
record = build_record_from(model, attribute_name => '')
|
664
|
-
|
1020
|
+
|
1021
|
+
assertion = lambda do
|
1022
|
+
expect(record).to validate_uniqueness.allow_blank
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
message = <<-MESSAGE
|
1026
|
+
Example did not properly validate that :attr is case-sensitively unique,
|
1027
|
+
but only if it is not blank.
|
1028
|
+
After taking the given Example, setting its :attr to ‹""›, and saving
|
1029
|
+
it as the existing record, then making a new Example and setting its
|
1030
|
+
:attr to ‹""› as well, the matcher expected the new Example to be
|
1031
|
+
valid, but it was invalid instead, producing these validation errors:
|
1032
|
+
|
1033
|
+
* attr: ["has already been taken"]
|
1034
|
+
MESSAGE
|
1035
|
+
|
1036
|
+
expect(&assertion).to fail_with_message(message)
|
665
1037
|
end
|
666
1038
|
end
|
667
1039
|
|
668
1040
|
context 'given an existing record whose attribute is empty' do
|
669
|
-
it 'rejects' do
|
1041
|
+
it 'rejects with an appropriate failure message' do
|
670
1042
|
model = define_model_validating_uniqueness(
|
671
1043
|
attribute_type: :string
|
672
1044
|
)
|
673
1045
|
record = create_record_from(model, attribute_name => '')
|
674
|
-
|
1046
|
+
|
1047
|
+
assertion = lambda do
|
1048
|
+
expect(record).to validate_uniqueness.allow_blank
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
message = <<-MESSAGE
|
1052
|
+
Example did not properly validate that :attr is case-sensitively unique,
|
1053
|
+
but only if it is not blank.
|
1054
|
+
Given an existing Example, after setting its :attr to ‹""›, then
|
1055
|
+
making a new Example and setting its :attr to ‹""› as well, the
|
1056
|
+
matcher expected the new Example to be valid, but it was invalid
|
1057
|
+
instead, producing these validation errors:
|
1058
|
+
|
1059
|
+
* attr: ["has already been taken"]
|
1060
|
+
MESSAGE
|
1061
|
+
|
1062
|
+
expect(&assertion).to fail_with_message(message)
|
675
1063
|
end
|
676
1064
|
end
|
677
1065
|
end
|
@@ -726,26 +1114,129 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
726
1114
|
end
|
727
1115
|
end
|
728
1116
|
|
1117
|
+
context 'when the model does not have the attribute being tested' do
|
1118
|
+
it 'fails with an appropriate failure message' do
|
1119
|
+
model = define_model(:example)
|
1120
|
+
|
1121
|
+
assertion = lambda do
|
1122
|
+
expect(model.new).to validate_uniqueness_of(:attr)
|
1123
|
+
end
|
1124
|
+
|
1125
|
+
message = <<-MESSAGE.strip
|
1126
|
+
Example did not properly validate that :attr is case-sensitively unique.
|
1127
|
+
:attr does not seem to be an attribute on Example.
|
1128
|
+
MESSAGE
|
1129
|
+
|
1130
|
+
expect(&assertion).to fail_with_message(message)
|
1131
|
+
end
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
context 'when the writer method for the attribute changes the case of incoming values' do
|
1135
|
+
context 'when the validation is case-sensitive' do
|
1136
|
+
context 'and the matcher is ensuring that the validation is case-sensitive' do
|
1137
|
+
it 'rejects with an appropriate failure message' do
|
1138
|
+
model = define_model_validating_uniqueness(
|
1139
|
+
attribute_name: :name
|
1140
|
+
)
|
1141
|
+
|
1142
|
+
model.class_eval do
|
1143
|
+
def name=(name)
|
1144
|
+
super(name.upcase)
|
1145
|
+
end
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
assertion = lambda do
|
1149
|
+
expect(model.new).to validate_uniqueness_of(:name)
|
1150
|
+
end
|
1151
|
+
|
1152
|
+
message = <<-MESSAGE.strip
|
1153
|
+
Example did not properly validate that :name is case-sensitively unique.
|
1154
|
+
After taking the given Example, setting its :name to ‹"an arbitrary
|
1155
|
+
value"› (read back as ‹"AN ARBITRARY VALUE"›), and saving it as the
|
1156
|
+
existing record, then making a new Example and setting its :name to
|
1157
|
+
‹"an arbitrary value"› (read back as ‹"AN ARBITRARY VALUE"›) as well,
|
1158
|
+
the matcher expected the new Example to be valid, but it was invalid
|
1159
|
+
instead, producing these validation errors:
|
1160
|
+
|
1161
|
+
* name: ["has already been taken"]
|
1162
|
+
|
1163
|
+
As indicated in the message above, :name seems to be changing certain
|
1164
|
+
values as they are set, and this could have something to do with why
|
1165
|
+
this test is failing. If you or something else has overridden the
|
1166
|
+
writer method for this attribute to normalize values by changing their
|
1167
|
+
case in any way (for instance, ensuring that the attribute is always
|
1168
|
+
downcased), then try adding `ignoring_case_sensitivity` onto the end
|
1169
|
+
of the uniqueness matcher. Otherwise, you may need to write the test
|
1170
|
+
yourself, or do something different altogether.
|
1171
|
+
MESSAGE
|
1172
|
+
|
1173
|
+
expect(&assertion).to fail_with_message(message)
|
1174
|
+
end
|
1175
|
+
end
|
1176
|
+
|
1177
|
+
context 'and the matcher is ignoring case sensitivity' do
|
1178
|
+
it 'accepts (and not raise an error)' do
|
1179
|
+
model = define_model_validating_uniqueness(
|
1180
|
+
attribute_name: :name
|
1181
|
+
)
|
1182
|
+
|
1183
|
+
model.class_eval do
|
1184
|
+
def name=(name)
|
1185
|
+
super(name.upcase)
|
1186
|
+
end
|
1187
|
+
end
|
1188
|
+
|
1189
|
+
expect(model.new).
|
1190
|
+
to validate_uniqueness_of(:name).
|
1191
|
+
ignoring_case_sensitivity
|
1192
|
+
end
|
1193
|
+
end
|
1194
|
+
end
|
1195
|
+
|
1196
|
+
context 'when the validation is case-insensitive' do
|
1197
|
+
context 'and the matcher is ensuring that the validation is case-insensitive' do
|
1198
|
+
it 'accepts (and does not raise an error)' do
|
1199
|
+
model = define_model_validating_uniqueness(
|
1200
|
+
attribute_name: :name,
|
1201
|
+
validation_options: { case_sensitive: false },
|
1202
|
+
)
|
1203
|
+
|
1204
|
+
model.class_eval do
|
1205
|
+
def name=(name)
|
1206
|
+
super(name.downcase)
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
expect(model.new).
|
1211
|
+
to validate_uniqueness_of(:name).
|
1212
|
+
case_insensitive
|
1213
|
+
end
|
1214
|
+
end
|
1215
|
+
end
|
1216
|
+
end
|
1217
|
+
|
729
1218
|
let(:model_attributes) { {} }
|
730
1219
|
|
731
1220
|
def default_attribute
|
732
1221
|
{
|
733
1222
|
value_type: :string,
|
734
1223
|
column_type: :string,
|
735
|
-
array: false
|
1224
|
+
options: { array: false, null: true }
|
736
1225
|
}
|
737
1226
|
end
|
738
1227
|
|
739
1228
|
def normalize_attribute(attribute)
|
740
1229
|
if attribute.is_a?(Hash)
|
741
|
-
|
742
|
-
|
743
|
-
|
1230
|
+
attribute_copy = attribute.dup
|
1231
|
+
|
1232
|
+
if attribute_copy.key?(:type)
|
1233
|
+
attribute_copy[:value_type] = attribute_copy[:type]
|
1234
|
+
attribute_copy[:column_type] = attribute_copy[:type]
|
744
1235
|
end
|
745
1236
|
|
746
|
-
default_attribute.
|
1237
|
+
default_attribute.deep_merge(attribute_copy)
|
747
1238
|
else
|
748
|
-
default_attribute.
|
1239
|
+
default_attribute.deep_merge(name: attribute)
|
749
1240
|
end
|
750
1241
|
end
|
751
1242
|
|
@@ -757,15 +1248,10 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
757
1248
|
|
758
1249
|
def column_options_from(attributes)
|
759
1250
|
attributes.inject({}) do |options, attribute|
|
760
|
-
|
1251
|
+
options[attribute[:name]] = {
|
761
1252
|
type: attribute[:column_type],
|
762
1253
|
options: attribute.fetch(:options, {})
|
763
1254
|
}
|
764
|
-
|
765
|
-
if attribute[:array]
|
766
|
-
options_for_attribute[:options][:array] = attribute[:array]
|
767
|
-
end
|
768
|
-
|
769
1255
|
options
|
770
1256
|
end
|
771
1257
|
end
|
@@ -773,10 +1259,14 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
773
1259
|
def attributes_with_values_for(model)
|
774
1260
|
model_attributes[model].each_with_object({}) do |attribute, attrs|
|
775
1261
|
attrs[attribute[:name]] = attribute.fetch(:value) do
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
1262
|
+
if attribute[:options][:null]
|
1263
|
+
nil
|
1264
|
+
else
|
1265
|
+
dummy_value_for(
|
1266
|
+
attribute[:value_type],
|
1267
|
+
array: attribute[:options][:array]
|
1268
|
+
)
|
1269
|
+
end
|
780
1270
|
end
|
781
1271
|
end
|
782
1272
|
end
|
@@ -835,25 +1325,21 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
835
1325
|
end
|
836
1326
|
end
|
837
1327
|
|
838
|
-
def determine_scope_attribute_names_from(scope_attributes)
|
839
|
-
scope_attributes.map do |attribute|
|
840
|
-
if attribute.is_a?(Hash)
|
841
|
-
attribute[:name]
|
842
|
-
else
|
843
|
-
attribute
|
844
|
-
end
|
845
|
-
end
|
846
|
-
end
|
847
|
-
|
848
1328
|
def define_model_validating_uniqueness(options = {}, &block)
|
1329
|
+
attribute_name = options.fetch(:attribute_name) { self.attribute_name }
|
849
1330
|
attribute_type = options.fetch(:attribute_type, :string)
|
850
1331
|
attribute_options = options.fetch(:attribute_options, {})
|
851
|
-
attribute =
|
1332
|
+
attribute = normalize_attribute(
|
852
1333
|
name: attribute_name,
|
853
1334
|
value_type: attribute_type,
|
854
1335
|
column_type: attribute_type,
|
855
1336
|
options: attribute_options
|
856
|
-
|
1337
|
+
)
|
1338
|
+
|
1339
|
+
if options.key?(:attribute_value)
|
1340
|
+
attribute[:value] = options[:attribute_value]
|
1341
|
+
end
|
1342
|
+
|
857
1343
|
scope_attributes = normalize_attributes(options.fetch(:scopes, []))
|
858
1344
|
scope_attribute_names = scope_attributes.map { |attr| attr[:name] }
|
859
1345
|
additional_attributes = normalize_attributes(
|
@@ -909,6 +1395,12 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
909
1395
|
build_record_from(model)
|
910
1396
|
end
|
911
1397
|
|
1398
|
+
def define_model_without_validation
|
1399
|
+
define_model(:example, attribute_name => :string) do |model|
|
1400
|
+
model.attr_accessible(attribute_name)
|
1401
|
+
end
|
1402
|
+
end
|
1403
|
+
|
912
1404
|
def validate_uniqueness
|
913
1405
|
validate_uniqueness_of(attribute_name)
|
914
1406
|
end
|
@@ -916,4 +1408,11 @@ describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :mo
|
|
916
1408
|
def attribute_name
|
917
1409
|
:attr
|
918
1410
|
end
|
1411
|
+
|
1412
|
+
def validation_matcher_scenario_args
|
1413
|
+
super.deep_merge(
|
1414
|
+
matcher_name: :validate_uniqueness_of,
|
1415
|
+
model_creator: :"active_record/uniqueness_matcher"
|
1416
|
+
)
|
1417
|
+
end
|
919
1418
|
end
|