shoulda-matchers 5.3.0 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|