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
@@ -253,40 +253,50 @@ module Shoulda
|
|
253
253
|
self
|
254
254
|
end
|
255
255
|
|
256
|
-
def
|
256
|
+
def with_message(message)
|
257
257
|
if message
|
258
|
+
@expects_custom_validation_message = true
|
258
259
|
@short_message = message
|
260
|
+
@long_message = message
|
259
261
|
end
|
262
|
+
|
260
263
|
self
|
261
264
|
end
|
262
265
|
|
263
|
-
def
|
266
|
+
def with_short_message(message)
|
264
267
|
if message
|
265
|
-
@
|
268
|
+
@expects_custom_validation_message = true
|
269
|
+
@short_message = message
|
266
270
|
end
|
271
|
+
|
267
272
|
self
|
268
273
|
end
|
269
274
|
|
270
|
-
def
|
275
|
+
def with_long_message(message)
|
271
276
|
if message
|
272
|
-
@
|
277
|
+
@expects_custom_validation_message = true
|
273
278
|
@long_message = message
|
274
279
|
end
|
280
|
+
|
275
281
|
self
|
276
282
|
end
|
277
283
|
|
278
|
-
def
|
279
|
-
description =
|
284
|
+
def simple_description
|
285
|
+
description = "validate that the length of :#{@attribute}"
|
286
|
+
|
280
287
|
if @options.key?(:minimum) && @options.key?(:maximum)
|
281
288
|
if @options[:minimum] == @options[:maximum]
|
282
|
-
description << "
|
289
|
+
description << " is #{@options[:minimum]}"
|
283
290
|
else
|
284
|
-
description << "between #{@options[:minimum]}
|
291
|
+
description << " is between #{@options[:minimum]}"
|
292
|
+
description << " and #{@options[:maximum]}"
|
285
293
|
end
|
286
|
-
|
287
|
-
description << "
|
288
|
-
|
294
|
+
elsif @options.key?(:minimum)
|
295
|
+
description << " is at least #{@options[:minimum]}"
|
296
|
+
elsif @options.key?(:maximum)
|
297
|
+
description << " is at most #{@options[:maximum]}"
|
289
298
|
end
|
299
|
+
|
290
300
|
description
|
291
301
|
end
|
292
302
|
|
@@ -279,7 +279,7 @@ module Shoulda
|
|
279
279
|
#
|
280
280
|
# Use `allow_nil` to assert that the attribute allows nil.
|
281
281
|
#
|
282
|
-
# class
|
282
|
+
# class Post
|
283
283
|
# include ActiveModel::Model
|
284
284
|
# attr_accessor :age
|
285
285
|
#
|
@@ -304,27 +304,37 @@ module Shoulda
|
|
304
304
|
|
305
305
|
# @private
|
306
306
|
class ValidateNumericalityOfMatcher
|
307
|
-
NUMERIC_NAME = '
|
307
|
+
NUMERIC_NAME = 'number'
|
308
308
|
NON_NUMERIC_VALUE = 'abcd'
|
309
309
|
DEFAULT_DIFF_TO_COMPARE = 1
|
310
310
|
|
311
|
+
include Qualifiers::IgnoringInterferenceByWriter
|
312
|
+
|
311
313
|
attr_reader :diff_to_compare
|
312
314
|
|
313
315
|
def initialize(attribute)
|
316
|
+
super
|
314
317
|
@attribute = attribute
|
315
318
|
@submatchers = []
|
316
319
|
@diff_to_compare = DEFAULT_DIFF_TO_COMPARE
|
317
|
-
@
|
318
|
-
|
319
|
-
|
320
|
+
@expects_custom_validation_message = false
|
321
|
+
@expects_to_allow_nil = false
|
322
|
+
@expects_strict = false
|
323
|
+
@allowed_type_adjective = nil
|
324
|
+
@allowed_type_name = 'number'
|
325
|
+
@context = nil
|
326
|
+
@expected_message = nil
|
320
327
|
end
|
321
328
|
|
322
329
|
def strict
|
323
|
-
@
|
324
|
-
@submatchers.each(&:strict)
|
330
|
+
@expects_strict = true
|
325
331
|
self
|
326
332
|
end
|
327
333
|
|
334
|
+
def expects_strict?
|
335
|
+
@expects_strict
|
336
|
+
end
|
337
|
+
|
328
338
|
def only_integer
|
329
339
|
prepare_submatcher(
|
330
340
|
NumericalityMatchers::OnlyIntegerMatcher.new(self, @attribute)
|
@@ -333,6 +343,7 @@ module Shoulda
|
|
333
343
|
end
|
334
344
|
|
335
345
|
def allow_nil
|
346
|
+
@expects_to_allow_nil = true
|
336
347
|
prepare_submatcher(
|
337
348
|
AllowValueMatcher.new(nil)
|
338
349
|
.for(@attribute)
|
@@ -341,6 +352,10 @@ module Shoulda
|
|
341
352
|
self
|
342
353
|
end
|
343
354
|
|
355
|
+
def expects_to_allow_nil?
|
356
|
+
@expects_to_allow_nil
|
357
|
+
end
|
358
|
+
|
344
359
|
def odd
|
345
360
|
prepare_submatcher(
|
346
361
|
NumericalityMatchers::OddNumberMatcher.new(self, @attribute)
|
@@ -381,120 +396,216 @@ module Shoulda
|
|
381
396
|
end
|
382
397
|
|
383
398
|
def with_message(message)
|
384
|
-
@
|
399
|
+
@expects_custom_validation_message = true
|
400
|
+
@expected_message = message
|
385
401
|
self
|
386
402
|
end
|
387
403
|
|
404
|
+
def expects_custom_validation_message?
|
405
|
+
@expects_custom_validation_message
|
406
|
+
end
|
407
|
+
|
388
408
|
def on(context)
|
389
|
-
@
|
409
|
+
@context = context
|
390
410
|
self
|
391
411
|
end
|
392
412
|
|
393
413
|
def matches?(subject)
|
394
414
|
@subject = subject
|
415
|
+
@number_of_submatchers = @submatchers.size
|
395
416
|
|
396
|
-
|
397
|
-
|
398
|
-
end
|
399
|
-
|
400
|
-
if @submatchers.empty?
|
401
|
-
raise IneffectiveTestError.create(
|
402
|
-
model: @subject.class,
|
403
|
-
attribute: @attribute,
|
404
|
-
column_type: column_type
|
405
|
-
)
|
406
|
-
end
|
417
|
+
add_disallow_value_matcher
|
418
|
+
qualify_submatchers
|
407
419
|
|
408
420
|
first_failing_submatcher.nil?
|
409
421
|
end
|
410
422
|
|
411
|
-
def
|
412
|
-
|
423
|
+
def simple_description
|
424
|
+
description = ''
|
425
|
+
|
426
|
+
description << "validate that :#{@attribute} looks like "
|
427
|
+
description << Shoulda::Matchers::Util.a_or_an(full_allowed_type)
|
413
428
|
|
414
429
|
if comparison_descriptions.present?
|
415
|
-
|
430
|
+
description << ' ' + comparison_descriptions
|
416
431
|
end
|
417
432
|
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
end
|
433
|
+
description
|
434
|
+
end
|
435
|
+
|
436
|
+
def description
|
437
|
+
ValidationMatcher::BuildDescription.call(self, simple_description)
|
424
438
|
end
|
425
439
|
|
426
440
|
def failure_message
|
427
|
-
|
441
|
+
overall_failure_message.dup.tap do |message|
|
442
|
+
message << "\n"
|
443
|
+
message << failure_message_for_first_failing_submatcher
|
444
|
+
end
|
428
445
|
end
|
429
446
|
|
430
447
|
def failure_message_when_negated
|
431
|
-
|
448
|
+
overall_failure_message_when_negated.dup.tap do |message|
|
449
|
+
if submatcher_failure_message_when_negated.present?
|
450
|
+
raise "hmm, this needs to be implemented."
|
451
|
+
message << "\n"
|
452
|
+
message << Shoulda::Matchers.word_wrap(
|
453
|
+
submatcher_failure_message_when_negated,
|
454
|
+
indent: 2
|
455
|
+
)
|
456
|
+
end
|
457
|
+
end
|
432
458
|
end
|
433
459
|
|
434
460
|
def given_numeric_column?
|
435
|
-
|
461
|
+
attribute_is_active_record_column? &&
|
462
|
+
[:integer, :float, :decimal].include?(column_type)
|
436
463
|
end
|
437
464
|
|
438
465
|
private
|
439
466
|
|
467
|
+
def model
|
468
|
+
@subject.class
|
469
|
+
end
|
470
|
+
|
471
|
+
def overall_failure_message
|
472
|
+
Shoulda::Matchers.word_wrap(
|
473
|
+
"#{model.name} did not properly #{description}."
|
474
|
+
)
|
475
|
+
end
|
476
|
+
|
477
|
+
def overall_failure_message_when_negated
|
478
|
+
Shoulda::Matchers.word_wrap(
|
479
|
+
"Expected #{model.name} not to #{description}, but it did."
|
480
|
+
)
|
481
|
+
end
|
482
|
+
|
483
|
+
def attribute_is_active_record_column?
|
484
|
+
columns_hash.key?(@attribute.to_s)
|
485
|
+
end
|
486
|
+
|
440
487
|
def column_type
|
488
|
+
columns_hash[@attribute.to_s].type
|
489
|
+
end
|
490
|
+
|
491
|
+
def columns_hash
|
441
492
|
if @subject.class.respond_to?(:columns_hash)
|
442
|
-
@subject.class.columns_hash
|
493
|
+
@subject.class.columns_hash
|
494
|
+
else
|
495
|
+
{}
|
443
496
|
end
|
444
497
|
end
|
445
498
|
|
446
499
|
def add_disallow_value_matcher
|
447
|
-
disallow_value_matcher = DisallowValueMatcher.
|
500
|
+
disallow_value_matcher = DisallowValueMatcher.
|
501
|
+
new(NON_NUMERIC_VALUE).
|
448
502
|
for(@attribute).
|
449
503
|
with_message(:not_a_number)
|
450
504
|
|
451
505
|
add_submatcher(disallow_value_matcher)
|
452
506
|
end
|
453
507
|
|
454
|
-
def remove_disallow_value_matcher
|
455
|
-
@submatchers.shift
|
456
|
-
end
|
457
|
-
|
458
508
|
def prepare_submatcher(submatcher)
|
459
509
|
add_submatcher(submatcher)
|
460
|
-
|
461
|
-
if submatcher.respond_to?(:diff_to_compare)
|
462
|
-
update_diff_to_compare(submatcher)
|
463
|
-
end
|
510
|
+
submatcher
|
464
511
|
end
|
465
512
|
|
466
513
|
def comparison_matcher_for(value, operator)
|
467
|
-
NumericalityMatchers::ComparisonMatcher
|
468
|
-
|
469
|
-
|
514
|
+
NumericalityMatchers::ComparisonMatcher.
|
515
|
+
new(self, value, operator).
|
516
|
+
for(@attribute)
|
470
517
|
end
|
471
518
|
|
472
519
|
def add_submatcher(submatcher)
|
520
|
+
if submatcher.respond_to?(:allowed_type_name)
|
521
|
+
@allowed_type_name = submatcher.allowed_type_name
|
522
|
+
end
|
523
|
+
|
524
|
+
if submatcher.respond_to?(:allowed_type_adjective)
|
525
|
+
@allowed_type_adjective = submatcher.allowed_type_adjective
|
526
|
+
end
|
527
|
+
|
528
|
+
if submatcher.respond_to?(:diff_to_compare)
|
529
|
+
@diff_to_compare = [@diff_to_compare, submatcher.diff_to_compare].max
|
530
|
+
end
|
531
|
+
|
473
532
|
@submatchers << submatcher
|
474
533
|
end
|
475
534
|
|
476
|
-
def
|
477
|
-
@
|
535
|
+
def qualify_submatchers
|
536
|
+
@submatchers.each do |submatcher|
|
537
|
+
if @expects_strict
|
538
|
+
submatcher.strict(@expects_strict)
|
539
|
+
end
|
540
|
+
|
541
|
+
if @expected_message.present?
|
542
|
+
submatcher.with_message(@expected_message)
|
543
|
+
end
|
544
|
+
|
545
|
+
if @context
|
546
|
+
submatcher.on(@context)
|
547
|
+
end
|
548
|
+
|
549
|
+
submatcher.ignoring_interference_by_writer(
|
550
|
+
ignore_interference_by_writer
|
551
|
+
)
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
def number_of_submatchers_for_failure_message
|
556
|
+
if has_been_qualified?
|
557
|
+
@submatchers.size - 1
|
558
|
+
else
|
559
|
+
@submatchers.size
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
def has_been_qualified?
|
564
|
+
@submatchers.any? do |submatcher|
|
565
|
+
submatcher.class.parent == NumericalityMatchers
|
566
|
+
end
|
478
567
|
end
|
479
568
|
|
480
569
|
def first_failing_submatcher
|
481
|
-
@
|
570
|
+
@_failing_submatchers ||= @submatchers.detect do |submatcher|
|
482
571
|
!submatcher.matches?(@subject)
|
483
572
|
end
|
484
573
|
end
|
485
574
|
|
486
|
-
def
|
487
|
-
|
488
|
-
allowed_array.empty? ? NUMERIC_NAME : allowed_array.join(', ')
|
575
|
+
def submatcher_failure_message
|
576
|
+
first_failing_submatcher.failure_message
|
489
577
|
end
|
490
578
|
|
491
|
-
def
|
492
|
-
|
579
|
+
def submatcher_failure_message_when_negated
|
580
|
+
first_failing_submatcher.failure_message_when_negated
|
581
|
+
end
|
582
|
+
|
583
|
+
def failure_message_for_first_failing_submatcher
|
584
|
+
submatcher = first_failing_submatcher
|
585
|
+
|
586
|
+
if number_of_submatchers_for_failure_message > 1
|
587
|
+
submatcher_description = submatcher.simple_description.
|
588
|
+
sub(/\bvalidate that\b/, 'validates').
|
589
|
+
sub(/\bdisallow\b/, 'disallows').
|
590
|
+
sub(/\ballow\b/, 'allows')
|
591
|
+
submatcher_message =
|
592
|
+
"In checking that #{model.name} #{submatcher_description}, " +
|
593
|
+
submatcher.failure_message[0].downcase +
|
594
|
+
submatcher.failure_message[1..-1]
|
595
|
+
else
|
596
|
+
submatcher_message = submatcher.failure_message
|
597
|
+
end
|
598
|
+
|
599
|
+
Shoulda::Matchers.word_wrap(submatcher_message, indent: 2)
|
600
|
+
end
|
601
|
+
|
602
|
+
def full_allowed_type
|
603
|
+
"#{@allowed_type_adjective} #{@allowed_type_name}".strip
|
493
604
|
end
|
494
605
|
|
495
606
|
def comparison_descriptions
|
496
607
|
description_array = submatcher_comparison_descriptions
|
497
|
-
description_array.empty? ? '' :
|
608
|
+
description_array.empty? ? '' : submatcher_comparison_descriptions.join(' and ')
|
498
609
|
end
|
499
610
|
|
500
611
|
def submatcher_comparison_descriptions
|
@@ -505,39 +616,6 @@ module Shoulda
|
|
505
616
|
arr
|
506
617
|
end
|
507
618
|
end
|
508
|
-
|
509
|
-
class IneffectiveTestError < Shoulda::Matchers::Error
|
510
|
-
attr_accessor :model, :attribute, :column_type
|
511
|
-
|
512
|
-
def message
|
513
|
-
Shoulda::Matchers.word_wrap <<-MESSAGE
|
514
|
-
You are attempting to use validate_numericality_of, but the attribute you're
|
515
|
-
testing, :#{attribute}, is #{a_or_an(column_type)} column. One of the things
|
516
|
-
that the numericality matcher does is to assert that setting :#{attribute} to a
|
517
|
-
string that doesn't look like #{a_or_an(column_type)} will cause your
|
518
|
-
#{humanized_model_name} to become invalid. In this case, it's impossible to make
|
519
|
-
this assertion since :#{attribute} will typecast any incoming value to
|
520
|
-
#{a_or_an(column_type)}. This means that it's already guaranteed to be numeric!
|
521
|
-
Since this matcher isn't doing anything, you can remove it from your model
|
522
|
-
tests, and in fact, you can remove the validation from your model as it isn't
|
523
|
-
doing anything either.
|
524
|
-
MESSAGE
|
525
|
-
end
|
526
|
-
|
527
|
-
private
|
528
|
-
|
529
|
-
def humanized_model_name
|
530
|
-
model.name.humanize.downcase
|
531
|
-
end
|
532
|
-
|
533
|
-
def a_or_an(next_word)
|
534
|
-
if next_word =~ /[aeiou]/
|
535
|
-
"an #{next_word}"
|
536
|
-
else
|
537
|
-
"a #{next_word}"
|
538
|
-
end
|
539
|
-
end
|
540
|
-
end
|
541
619
|
end
|
542
620
|
end
|
543
621
|
end
|
@@ -111,24 +111,24 @@ module Shoulda
|
|
111
111
|
|
112
112
|
# @private
|
113
113
|
class ValidatePresenceOfMatcher < ValidationMatcher
|
114
|
-
def
|
115
|
-
|
116
|
-
|
114
|
+
def initialize(attribute)
|
115
|
+
super
|
116
|
+
@expected_message = :blank
|
117
117
|
end
|
118
118
|
|
119
119
|
def matches?(subject)
|
120
120
|
super(subject)
|
121
|
-
@expected_message ||= :blank
|
122
121
|
|
123
122
|
if secure_password_being_validated?
|
123
|
+
ignore_interference_by_writer.default_to(when: :blank?)
|
124
124
|
disallows_and_double_checks_value_of!(blank_value, @expected_message)
|
125
125
|
else
|
126
126
|
disallows_original_or_typecast_value?(blank_value, @expected_message)
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
-
def
|
131
|
-
"
|
130
|
+
def simple_description
|
131
|
+
"validate that :#{@attribute} cannot be empty/falsy"
|
132
132
|
end
|
133
133
|
|
134
134
|
private
|
@@ -141,14 +141,12 @@ module Shoulda
|
|
141
141
|
|
142
142
|
def disallows_and_double_checks_value_of!(value, message)
|
143
143
|
disallows_value_of(value, message)
|
144
|
-
rescue ActiveModel::AllowValueMatcher::
|
144
|
+
rescue ActiveModel::AllowValueMatcher::AttributeChangedValueError
|
145
145
|
raise ActiveModel::CouldNotSetPasswordError.create(@subject.class)
|
146
146
|
end
|
147
147
|
|
148
148
|
def disallows_original_or_typecast_value?(value, message)
|
149
149
|
disallows_value_of(blank_value, @expected_message)
|
150
|
-
rescue ActiveModel::AllowValueMatcher::CouldNotSetAttributeError => error
|
151
|
-
error.actual_value.blank?
|
152
150
|
end
|
153
151
|
|
154
152
|
def blank_value
|