shoulda-matchers 5.3.0 → 6.0.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/LICENSE +1 -1
- data/README.md +22 -7
- data/lib/shoulda/matchers/action_controller/permit_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +9 -0
- data/lib/shoulda/matchers/active_model/comparison_matcher.rb +162 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +21 -6
- data/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +534 -0
- data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +64 -9
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +32 -86
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +6 -0
- data/lib/shoulda/matchers/active_model/validator.rb +4 -0
- data/lib/shoulda/matchers/active_model.rb +2 -1
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +0 -8
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +46 -6
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +14 -3
- data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +3 -5
- data/lib/shoulda/matchers/active_record/normalize_matcher.rb +151 -0
- data/lib/shoulda/matchers/active_record.rb +1 -0
- data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +1 -1
- data/lib/shoulda/matchers/rails_shim.rb +8 -6
- data/lib/shoulda/matchers/util/word_wrap.rb +1 -1
- data/lib/shoulda/matchers/util.rb +1 -1
- data/lib/shoulda/matchers/version.rb +1 -1
- data/lib/shoulda/matchers.rb +2 -2
- data/shoulda-matchers.gemspec +1 -1
- metadata +10 -8
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +0 -136
@@ -3,7 +3,7 @@ module Shoulda
|
|
3
3
|
module ActiveModel
|
4
4
|
# The `validate_length_of` matcher tests usage of the
|
5
5
|
# `validates_length_of` matcher. Note that this matcher is intended to be
|
6
|
-
# used against string columns and not integer columns.
|
6
|
+
# used against string columns and associations and not integer columns.
|
7
7
|
#
|
8
8
|
# #### Qualifiers
|
9
9
|
#
|
@@ -36,7 +36,8 @@ module Shoulda
|
|
36
36
|
#
|
37
37
|
# Use `is_at_least` to test usage of the `:minimum` option. This asserts
|
38
38
|
# that the attribute can take a string which is equal to or longer than
|
39
|
-
# the given length and cannot take a string which is shorter.
|
39
|
+
# the given length and cannot take a string which is shorter. This qualifier
|
40
|
+
# also works for associations.
|
40
41
|
#
|
41
42
|
# class User
|
42
43
|
# include ActiveModel::Model
|
@@ -61,7 +62,8 @@ module Shoulda
|
|
61
62
|
#
|
62
63
|
# Use `is_at_most` to test usage of the `:maximum` option. This asserts
|
63
64
|
# that the attribute can take a string which is equal to or shorter than
|
64
|
-
# the given length and cannot take a string which is longer.
|
65
|
+
# the given length and cannot take a string which is longer. This qualifier
|
66
|
+
# also works for associations.
|
65
67
|
#
|
66
68
|
# class User
|
67
69
|
# include ActiveModel::Model
|
@@ -84,7 +86,8 @@ module Shoulda
|
|
84
86
|
#
|
85
87
|
# Use `is_equal_to` to test usage of the `:is` option. This asserts that
|
86
88
|
# the attribute can take a string which is exactly equal to the given
|
87
|
-
# length and cannot take a string which is shorter or longer.
|
89
|
+
# length and cannot take a string which is shorter or longer. This qualifier
|
90
|
+
# also works for associations.
|
88
91
|
#
|
89
92
|
# class User
|
90
93
|
# include ActiveModel::Model
|
@@ -106,7 +109,7 @@ module Shoulda
|
|
106
109
|
# ##### is_at_least + is_at_most
|
107
110
|
#
|
108
111
|
# Use `is_at_least` and `is_at_most` together to test usage of the `:in`
|
109
|
-
# option.
|
112
|
+
# option. This qualifies also works for associations.
|
110
113
|
#
|
111
114
|
# class User
|
112
115
|
# include ActiveModel::Model
|
@@ -260,6 +263,29 @@ module Shoulda
|
|
260
263
|
# should validate_length_of(:bio).is_at_least(15).allow_blank
|
261
264
|
# end
|
262
265
|
#
|
266
|
+
# ##### as_array
|
267
|
+
#
|
268
|
+
# Use `as_array` if you have an ActiveModel model and the attribute being validated
|
269
|
+
# is designed to store an array. (This is not necessary if you have an ActiveRecord
|
270
|
+
# model with an array column, as the matcher will detect this automatically.)
|
271
|
+
#
|
272
|
+
# class User
|
273
|
+
# include ActiveModel::Model
|
274
|
+
# attribute :arr, array: true
|
275
|
+
#
|
276
|
+
# validates_length_of :arr, minimum: 15
|
277
|
+
# end
|
278
|
+
#
|
279
|
+
# # RSpec
|
280
|
+
# describe User do
|
281
|
+
# it { should validate_length_of(:arr).as_array.is_at_least(15) }
|
282
|
+
# end
|
283
|
+
#
|
284
|
+
# # Minitest (Shoulda)
|
285
|
+
# class UserTest < ActiveSupport::TestCase
|
286
|
+
# should validate_length_of(:arr).as_array.is_at_least(15)
|
287
|
+
# end
|
288
|
+
#
|
263
289
|
def validate_length_of(attr)
|
264
290
|
ValidateLengthOfMatcher.new(attr)
|
265
291
|
end
|
@@ -275,6 +301,11 @@ module Shoulda
|
|
275
301
|
@long_message = nil
|
276
302
|
end
|
277
303
|
|
304
|
+
def as_array
|
305
|
+
@options[:array] = true
|
306
|
+
self
|
307
|
+
end
|
308
|
+
|
278
309
|
def is_at_least(length)
|
279
310
|
@options[:minimum] = length
|
280
311
|
@short_message ||= :too_short
|
@@ -451,15 +482,39 @@ module Shoulda
|
|
451
482
|
end
|
452
483
|
|
453
484
|
def allows_length_of?(length, message)
|
454
|
-
allows_value_of(
|
485
|
+
allows_value_of(value_of_length(length), message)
|
455
486
|
end
|
456
487
|
|
457
488
|
def disallows_length_of?(length, message)
|
458
|
-
disallows_value_of(
|
489
|
+
disallows_value_of(value_of_length(length), message)
|
490
|
+
end
|
491
|
+
|
492
|
+
def value_of_length(length)
|
493
|
+
if array_column?
|
494
|
+
['x'] * length
|
495
|
+
elsif collection_association?
|
496
|
+
Array.new(length) { association_reflection.klass.new }
|
497
|
+
else
|
498
|
+
'x' * length
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
def array_column?
|
503
|
+
@options[:array] || super
|
504
|
+
end
|
505
|
+
|
506
|
+
def collection_association?
|
507
|
+
association? && [:has_many, :has_and_belongs_to_many].include?(
|
508
|
+
association_reflection.macro,
|
509
|
+
)
|
510
|
+
end
|
511
|
+
|
512
|
+
def association?
|
513
|
+
association_reflection.present?
|
459
514
|
end
|
460
515
|
|
461
|
-
def
|
462
|
-
|
516
|
+
def association_reflection
|
517
|
+
model.try(:reflect_on_association, @attribute)
|
463
518
|
end
|
464
519
|
|
465
520
|
def translated_short_message
|
@@ -357,51 +357,33 @@ module Shoulda
|
|
357
357
|
end
|
358
358
|
|
359
359
|
# @private
|
360
|
-
class ValidateNumericalityOfMatcher
|
360
|
+
class ValidateNumericalityOfMatcher < ValidationMatcher
|
361
361
|
NUMERIC_NAME = 'number'.freeze
|
362
362
|
DEFAULT_DIFF_TO_COMPARE = 1
|
363
363
|
|
364
|
-
include Qualifiers::IgnoringInterferenceByWriter
|
365
|
-
|
366
364
|
attr_reader :diff_to_compare
|
367
365
|
|
368
366
|
def initialize(attribute)
|
369
367
|
super
|
370
|
-
@attribute = attribute
|
371
368
|
@submatchers = []
|
372
369
|
@diff_to_compare = DEFAULT_DIFF_TO_COMPARE
|
373
|
-
@expects_custom_validation_message = false
|
374
370
|
@expects_to_allow_nil = false
|
375
|
-
@expects_strict = false
|
376
371
|
@allowed_type_adjective = nil
|
377
372
|
@allowed_type_name = 'number'
|
378
|
-
@context = nil
|
379
|
-
@expected_message = nil
|
380
|
-
end
|
381
373
|
|
382
|
-
|
383
|
-
@expects_strict = true
|
384
|
-
self
|
385
|
-
end
|
386
|
-
|
387
|
-
def expects_strict?
|
388
|
-
@expects_strict
|
374
|
+
add_disallow_non_numeric_value_matcher
|
389
375
|
end
|
390
376
|
|
391
377
|
def only_integer
|
392
378
|
prepare_submatcher(
|
393
|
-
NumericalityMatchers::OnlyIntegerMatcher.new(self,
|
379
|
+
NumericalityMatchers::OnlyIntegerMatcher.new(self, attribute),
|
394
380
|
)
|
395
381
|
self
|
396
382
|
end
|
397
383
|
|
398
384
|
def allow_nil
|
399
385
|
@expects_to_allow_nil = true
|
400
|
-
prepare_submatcher(
|
401
|
-
AllowValueMatcher.new(nil).
|
402
|
-
for(@attribute).
|
403
|
-
with_message(:not_a_number),
|
404
|
-
)
|
386
|
+
prepare_submatcher(allow_value_matcher(nil, :not_a_number))
|
405
387
|
self
|
406
388
|
end
|
407
389
|
|
@@ -411,70 +393,55 @@ module Shoulda
|
|
411
393
|
|
412
394
|
def odd
|
413
395
|
prepare_submatcher(
|
414
|
-
NumericalityMatchers::OddNumberMatcher.new(self,
|
396
|
+
NumericalityMatchers::OddNumberMatcher.new(self, attribute),
|
415
397
|
)
|
416
398
|
self
|
417
399
|
end
|
418
400
|
|
419
401
|
def even
|
420
402
|
prepare_submatcher(
|
421
|
-
NumericalityMatchers::EvenNumberMatcher.new(self,
|
403
|
+
NumericalityMatchers::EvenNumberMatcher.new(self, attribute),
|
422
404
|
)
|
423
405
|
self
|
424
406
|
end
|
425
407
|
|
426
408
|
def is_greater_than(value)
|
427
|
-
prepare_submatcher(comparison_matcher_for(value, :>).for(
|
409
|
+
prepare_submatcher(comparison_matcher_for(value, :>).for(attribute))
|
428
410
|
self
|
429
411
|
end
|
430
412
|
|
431
413
|
def is_greater_than_or_equal_to(value)
|
432
|
-
prepare_submatcher(comparison_matcher_for(value, :>=).for(
|
414
|
+
prepare_submatcher(comparison_matcher_for(value, :>=).for(attribute))
|
433
415
|
self
|
434
416
|
end
|
435
417
|
|
436
418
|
def is_equal_to(value)
|
437
|
-
prepare_submatcher(comparison_matcher_for(value, :==).for(
|
419
|
+
prepare_submatcher(comparison_matcher_for(value, :==).for(attribute))
|
438
420
|
self
|
439
421
|
end
|
440
422
|
|
441
423
|
def is_less_than(value)
|
442
|
-
prepare_submatcher(comparison_matcher_for(value, :<).for(
|
424
|
+
prepare_submatcher(comparison_matcher_for(value, :<).for(attribute))
|
443
425
|
self
|
444
426
|
end
|
445
427
|
|
446
428
|
def is_less_than_or_equal_to(value)
|
447
|
-
prepare_submatcher(comparison_matcher_for(value, :<=).for(
|
429
|
+
prepare_submatcher(comparison_matcher_for(value, :<=).for(attribute))
|
448
430
|
self
|
449
431
|
end
|
450
432
|
|
451
433
|
def is_other_than(value)
|
452
|
-
prepare_submatcher(comparison_matcher_for(value, :!=).for(
|
434
|
+
prepare_submatcher(comparison_matcher_for(value, :!=).for(attribute))
|
453
435
|
self
|
454
436
|
end
|
455
437
|
|
456
438
|
def is_in(range)
|
457
439
|
prepare_submatcher(
|
458
|
-
NumericalityMatchers::RangeMatcher.new(self,
|
440
|
+
NumericalityMatchers::RangeMatcher.new(self, attribute, range),
|
459
441
|
)
|
460
442
|
self
|
461
443
|
end
|
462
444
|
|
463
|
-
def with_message(message)
|
464
|
-
@expects_custom_validation_message = true
|
465
|
-
@expected_message = message
|
466
|
-
self
|
467
|
-
end
|
468
|
-
|
469
|
-
def expects_custom_validation_message?
|
470
|
-
@expects_custom_validation_message
|
471
|
-
end
|
472
|
-
|
473
|
-
def on(context)
|
474
|
-
@context = context
|
475
|
-
self
|
476
|
-
end
|
477
|
-
|
478
445
|
def matches?(subject)
|
479
446
|
matches_or_does_not_match?(subject)
|
480
447
|
first_submatcher_that_fails_to_match.nil?
|
@@ -488,7 +455,7 @@ module Shoulda
|
|
488
455
|
def simple_description
|
489
456
|
description = ''
|
490
457
|
|
491
|
-
description << "validate that :#{
|
458
|
+
description << "validate that :#{attribute} looks like "
|
492
459
|
description << Shoulda::Matchers::Util.a_or_an(full_allowed_type)
|
493
460
|
|
494
461
|
if range_description.present?
|
@@ -502,10 +469,6 @@ module Shoulda
|
|
502
469
|
description
|
503
470
|
end
|
504
471
|
|
505
|
-
def description
|
506
|
-
ValidationMatcher::BuildDescription.call(self, simple_description)
|
507
|
-
end
|
508
|
-
|
509
472
|
def failure_message
|
510
473
|
overall_failure_message.dup.tap do |message|
|
511
474
|
message << "\n"
|
@@ -532,44 +495,29 @@ module Shoulda
|
|
532
495
|
@subject = subject
|
533
496
|
@number_of_submatchers = @submatchers.size
|
534
497
|
|
535
|
-
add_disallow_value_matcher
|
536
498
|
qualify_submatchers
|
537
499
|
end
|
538
500
|
|
539
|
-
def overall_failure_message
|
540
|
-
Shoulda::Matchers.word_wrap(
|
541
|
-
"Expected #{model.name} to #{description}, but this could not "\
|
542
|
-
'be proved.',
|
543
|
-
)
|
544
|
-
end
|
545
|
-
|
546
|
-
def overall_failure_message_when_negated
|
547
|
-
Shoulda::Matchers.word_wrap(
|
548
|
-
"Expected #{model.name} not to #{description}, but this could not "\
|
549
|
-
'be proved.',
|
550
|
-
)
|
551
|
-
end
|
552
|
-
|
553
501
|
def attribute_is_active_record_column?
|
554
|
-
columns_hash.key?(
|
502
|
+
columns_hash.key?(attribute.to_s)
|
555
503
|
end
|
556
504
|
|
557
505
|
def column_type
|
558
|
-
columns_hash[
|
506
|
+
columns_hash[attribute.to_s].type
|
559
507
|
end
|
560
508
|
|
561
509
|
def columns_hash
|
562
|
-
if
|
563
|
-
|
510
|
+
if subject.class.respond_to?(:columns_hash)
|
511
|
+
subject.class.columns_hash
|
564
512
|
else
|
565
513
|
{}
|
566
514
|
end
|
567
515
|
end
|
568
516
|
|
569
|
-
def
|
517
|
+
def add_disallow_non_numeric_value_matcher
|
570
518
|
disallow_value_matcher = DisallowValueMatcher.
|
571
519
|
new(non_numeric_value).
|
572
|
-
for(
|
520
|
+
for(attribute).
|
573
521
|
with_message(:not_a_number)
|
574
522
|
|
575
523
|
add_submatcher(disallow_value_matcher)
|
@@ -581,9 +529,9 @@ module Shoulda
|
|
581
529
|
end
|
582
530
|
|
583
531
|
def comparison_matcher_for(value, operator)
|
584
|
-
|
532
|
+
ComparisonMatcher.
|
585
533
|
new(self, value, operator).
|
586
|
-
for(
|
534
|
+
for(attribute)
|
587
535
|
end
|
588
536
|
|
589
537
|
def add_submatcher(submatcher)
|
@@ -615,8 +563,8 @@ module Shoulda
|
|
615
563
|
submatcher.with_message(@expected_message)
|
616
564
|
end
|
617
565
|
|
618
|
-
if
|
619
|
-
submatcher.on(
|
566
|
+
if context
|
567
|
+
submatcher.on(context)
|
620
568
|
end
|
621
569
|
|
622
570
|
submatcher.ignoring_interference_by_writer(
|
@@ -634,23 +582,25 @@ module Shoulda
|
|
634
582
|
end
|
635
583
|
|
636
584
|
def has_been_qualified?
|
637
|
-
@submatchers.any?
|
638
|
-
|
639
|
-
|
640
|
-
|
585
|
+
@submatchers.any? { |submatcher| submatcher_qualified?(submatcher) }
|
586
|
+
end
|
587
|
+
|
588
|
+
def submatcher_qualified?(submatcher)
|
589
|
+
Shoulda::Matchers::RailsShim.parent_of(submatcher.class) ==
|
590
|
+
NumericalityMatchers || submatcher.instance_of?(ComparisonMatcher)
|
641
591
|
end
|
642
592
|
|
643
593
|
def first_submatcher_that_fails_to_match
|
644
594
|
@_first_submatcher_that_fails_to_match ||=
|
645
595
|
@submatchers.detect do |submatcher|
|
646
|
-
!submatcher.matches?(
|
596
|
+
!submatcher.matches?(subject)
|
647
597
|
end
|
648
598
|
end
|
649
599
|
|
650
600
|
def first_submatcher_that_fails_to_not_match
|
651
601
|
@_first_submatcher_that_fails_to_not_match ||=
|
652
602
|
@submatchers.detect do |submatcher|
|
653
|
-
!submatcher.does_not_match?(
|
603
|
+
!submatcher.does_not_match?(subject)
|
654
604
|
end
|
655
605
|
end
|
656
606
|
|
@@ -719,10 +669,6 @@ module Shoulda
|
|
719
669
|
range_submatcher&.range_description
|
720
670
|
end
|
721
671
|
|
722
|
-
def model
|
723
|
-
@subject.class
|
724
|
-
end
|
725
|
-
|
726
672
|
def non_numeric_value
|
727
673
|
'abcd'
|
728
674
|
end
|
@@ -186,6 +186,12 @@ module Shoulda
|
|
186
186
|
def blank_values
|
187
187
|
['', ' ', "\n", "\r", "\t", "\f"]
|
188
188
|
end
|
189
|
+
|
190
|
+
def array_column?
|
191
|
+
@subject.class.respond_to?(:columns_hash) &&
|
192
|
+
@subject.class.columns_hash[@attribute.to_s].respond_to?(:array) &&
|
193
|
+
@subject.class.columns_hash[@attribute.to_s].array
|
194
|
+
end
|
189
195
|
end
|
190
196
|
end
|
191
197
|
end
|
@@ -21,8 +21,9 @@ require 'shoulda/matchers/active_model/validate_presence_of_matcher'
|
|
21
21
|
require 'shoulda/matchers/active_model/validate_acceptance_of_matcher'
|
22
22
|
require 'shoulda/matchers/active_model/validate_confirmation_of_matcher'
|
23
23
|
require 'shoulda/matchers/active_model/validate_numericality_of_matcher'
|
24
|
+
require 'shoulda/matchers/active_model/validate_comparison_of_matcher'
|
25
|
+
require 'shoulda/matchers/active_model/comparison_matcher'
|
24
26
|
require 'shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher'
|
25
|
-
require 'shoulda/matchers/active_model/numericality_matchers/comparison_matcher'
|
26
27
|
require 'shoulda/matchers/active_model/numericality_matchers/odd_number_matcher'
|
27
28
|
require 'shoulda/matchers/active_model/numericality_matchers/even_number_matcher'
|
28
29
|
require 'shoulda/matchers/active_model/numericality_matchers/only_integer_matcher'
|
@@ -227,14 +227,6 @@ module Shoulda
|
|
227
227
|
self
|
228
228
|
end
|
229
229
|
|
230
|
-
def with(expected_enum_values)
|
231
|
-
Shoulda::Matchers.warn_about_deprecated_method(
|
232
|
-
'The `with` qualifier on `define_enum_for`',
|
233
|
-
'`with_values`',
|
234
|
-
)
|
235
|
-
with_values(expected_enum_values)
|
236
|
-
end
|
237
|
-
|
238
230
|
def with_prefix(expected_prefix = true)
|
239
231
|
options[:prefix] = expected_prefix
|
240
232
|
self
|
@@ -48,6 +48,30 @@ module Shoulda
|
|
48
48
|
# should have_db_column(:camera_aperture).of_type(:decimal)
|
49
49
|
# end
|
50
50
|
#
|
51
|
+
# ##### of_sql_type
|
52
|
+
#
|
53
|
+
# Use `of_sql_type` to assert that a column is defined as a certain sql_type.
|
54
|
+
#
|
55
|
+
# class CreatePhones < ActiveRecord::Migration
|
56
|
+
# def change
|
57
|
+
# create_table :phones do |t|
|
58
|
+
# t.string :camera_aperture, limit: 36
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# # RSpec
|
64
|
+
# RSpec.describe Phone, type: :model do
|
65
|
+
# it do
|
66
|
+
# should have_db_column(:camera_aperture).of_sql_type('varchar(36)')
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# # Minitest (Shoulda)
|
71
|
+
# class PhoneTest < ActiveSupport::TestCase
|
72
|
+
# should have_db_column(:camera_aperture).of_sql_type('varchar(36)')
|
73
|
+
# end
|
74
|
+
#
|
51
75
|
# ##### with_options
|
52
76
|
#
|
53
77
|
# Use `with_options` to assert that a column has been defined with
|
@@ -96,6 +120,11 @@ module Shoulda
|
|
96
120
|
self
|
97
121
|
end
|
98
122
|
|
123
|
+
def of_sql_type(sql_column_type)
|
124
|
+
@options[:sql_column_type] = sql_column_type
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
99
128
|
def with_options(opts = {})
|
100
129
|
validate_options(opts)
|
101
130
|
OPTIONS.each do |attribute|
|
@@ -110,6 +139,7 @@ module Shoulda
|
|
110
139
|
@subject = subject
|
111
140
|
column_exists? &&
|
112
141
|
correct_column_type? &&
|
142
|
+
correct_sql_column_type? &&
|
113
143
|
correct_precision? &&
|
114
144
|
correct_limit? &&
|
115
145
|
correct_default? &&
|
@@ -129,12 +159,9 @@ module Shoulda
|
|
129
159
|
|
130
160
|
def description
|
131
161
|
desc = "have db column named #{@column}"
|
132
|
-
if @options.key?(:column_type)
|
133
|
-
|
134
|
-
|
135
|
-
if @options.key?(:precision)
|
136
|
-
desc << " of precision #{@options[:precision]}"
|
137
|
-
end
|
162
|
+
desc << " of type #{@options[:column_type]}" if @options.key?(:column_type)
|
163
|
+
desc << " of sql_type #{@options[:sql_column_type]}" if @options.key?(:sql_column_type)
|
164
|
+
desc << " of precision #{@options[:precision]}" if @options.key?(:precision)
|
138
165
|
desc << " of limit #{@options[:limit]}" if @options.key?(:limit)
|
139
166
|
desc << " of default #{@options[:default]}" if @options.key?(:default)
|
140
167
|
desc << " of null #{@options[:null]}" if @options.key?(:null)
|
@@ -178,6 +205,19 @@ module Shoulda
|
|
178
205
|
end
|
179
206
|
end
|
180
207
|
|
208
|
+
def correct_sql_column_type?
|
209
|
+
return true unless @options.key?(:sql_column_type)
|
210
|
+
|
211
|
+
if matched_column.sql_type.to_s == @options[:sql_column_type].to_s
|
212
|
+
true
|
213
|
+
else
|
214
|
+
@missing =
|
215
|
+
"#{model_class} has a db column named #{@column} " <<
|
216
|
+
"of sql type #{matched_column.sql_type}, not #{@options[:sql_column_type]}."
|
217
|
+
false
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
181
221
|
def correct_precision?
|
182
222
|
return true unless @options.key?(:precision)
|
183
223
|
|
@@ -197,17 +197,28 @@ module Shoulda
|
|
197
197
|
def matched_index
|
198
198
|
@_matched_index ||=
|
199
199
|
if expected_columns.one?
|
200
|
-
|
200
|
+
sorted_indexes.detect do |index|
|
201
201
|
Array.wrap(index.columns) == expected_columns
|
202
202
|
end
|
203
203
|
else
|
204
|
-
|
204
|
+
sorted_indexes.detect do |index|
|
205
205
|
index.columns == expected_columns
|
206
206
|
end
|
207
207
|
end
|
208
208
|
end
|
209
209
|
|
210
|
-
def
|
210
|
+
def sorted_indexes
|
211
|
+
if qualifiers.include?(:unique)
|
212
|
+
# return indexes with unique matching the qualifier first
|
213
|
+
unsorted_indexes.sort_by do |index|
|
214
|
+
index.unique == qualifiers[:unique] ? 0 : 1
|
215
|
+
end
|
216
|
+
else
|
217
|
+
unsorted_indexes
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def unsorted_indexes
|
211
222
|
model.connection.indexes(table_name)
|
212
223
|
end
|
213
224
|
|
@@ -2,7 +2,7 @@ module Shoulda
|
|
2
2
|
module Matchers
|
3
3
|
module ActiveRecord
|
4
4
|
# The `have_implicit_order_column` matcher tests that the model has `implicit_order_column`
|
5
|
-
# assigned to one of the table columns.
|
5
|
+
# assigned to one of the table columns.
|
6
6
|
#
|
7
7
|
# class Product < ApplicationRecord
|
8
8
|
# self.implicit_order_column = :created_at
|
@@ -20,10 +20,8 @@ module Shoulda
|
|
20
20
|
#
|
21
21
|
# @return [HaveImplicitOrderColumnMatcher]
|
22
22
|
#
|
23
|
-
|
24
|
-
|
25
|
-
HaveImplicitOrderColumnMatcher.new(column_name)
|
26
|
-
end
|
23
|
+
def have_implicit_order_column(column_name)
|
24
|
+
HaveImplicitOrderColumnMatcher.new(column_name)
|
27
25
|
end
|
28
26
|
|
29
27
|
# @private
|