shoulda-matchers 4.4.0 → 5.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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +22 -0
  3. data/README.md +18 -18
  4. data/lib/shoulda/matchers.rb +12 -13
  5. data/lib/shoulda/matchers/action_controller.rb +13 -13
  6. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +4 -89
  7. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +3 -2
  8. data/lib/shoulda/matchers/action_controller/flash_store.rb +2 -4
  9. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +29 -27
  10. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +6 -8
  11. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +6 -8
  12. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +16 -13
  13. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +2 -1
  14. data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -6
  15. data/lib/shoulda/matchers/action_controller/route_params.rb +1 -1
  16. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +19 -13
  17. data/lib/shoulda/matchers/active_model.rb +25 -15
  18. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +29 -36
  19. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +1 -1
  20. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +5 -5
  21. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +2 -2
  22. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +1 -1
  23. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +1 -1
  24. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +1 -1
  25. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +51 -25
  26. data/lib/shoulda/matchers/active_model/helpers.rb +2 -2
  27. data/lib/shoulda/matchers/active_model/numericality_matchers.rb +0 -5
  28. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +32 -34
  29. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +1 -1
  30. data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +1 -1
  31. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +10 -2
  32. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +2 -2
  33. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +8 -7
  34. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +26 -25
  35. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +6 -6
  36. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +40 -27
  37. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +4 -4
  38. data/lib/shoulda/matchers/active_model/validation_matcher.rb +6 -8
  39. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +2 -4
  40. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +2 -4
  41. data/lib/shoulda/matchers/active_model/validator.rb +4 -9
  42. data/lib/shoulda/matchers/active_record.rb +26 -14
  43. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +6 -3
  44. data/lib/shoulda/matchers/active_record/association_matcher.rb +101 -48
  45. data/lib/shoulda/matchers/active_record/association_matchers.rb +0 -12
  46. data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +5 -2
  47. data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -4
  48. data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +1 -1
  49. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +11 -6
  50. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +2 -9
  51. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +12 -7
  52. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +23 -5
  53. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +3 -3
  54. data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +1 -1
  55. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +4 -4
  56. data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +3 -2
  57. data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +7 -5
  58. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +18 -9
  59. data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +46 -8
  60. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +39 -17
  61. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
  62. data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +7 -7
  63. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +12 -10
  64. data/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +11 -7
  65. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +2 -0
  66. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +13 -9
  67. data/lib/shoulda/matchers/active_record/uniqueness.rb +4 -4
  68. data/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +1 -3
  69. data/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +0 -2
  70. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +78 -71
  71. data/lib/shoulda/matchers/doublespeak.rb +9 -9
  72. data/lib/shoulda/matchers/doublespeak/double.rb +1 -1
  73. data/lib/shoulda/matchers/doublespeak/double_collection.rb +3 -3
  74. data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +8 -5
  75. data/lib/shoulda/matchers/doublespeak/object_double.rb +1 -1
  76. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +1 -5
  77. data/lib/shoulda/matchers/doublespeak/world.rb +2 -2
  78. data/lib/shoulda/matchers/error.rb +1 -1
  79. data/lib/shoulda/matchers/independent.rb +1 -0
  80. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +14 -16
  81. data/lib/shoulda/matchers/integrations.rb +6 -6
  82. data/lib/shoulda/matchers/integrations/configuration.rb +1 -1
  83. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
  84. data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -2
  85. data/lib/shoulda/matchers/integrations/test_frameworks.rb +2 -4
  86. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
  87. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
  88. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
  89. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
  90. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
  91. data/lib/shoulda/matchers/rails_shim.rb +5 -42
  92. data/lib/shoulda/matchers/util.rb +9 -2
  93. data/lib/shoulda/matchers/util/word_wrap.rb +7 -7
  94. data/lib/shoulda/matchers/version.rb +1 -1
  95. data/lib/shoulda/matchers/warn.rb +3 -3
  96. data/shoulda-matchers.gemspec +12 -9
  97. metadata +14 -14
  98. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +0 -159
@@ -26,12 +26,7 @@ module Shoulda
26
26
 
27
27
  def join_table_name
28
28
  join_table_name =
29
- if has_and_belongs_to_many_name_table_name
30
- has_and_belongs_to_many_name_table_name
31
- else
32
- reflection.join_table
33
- end
34
-
29
+ has_and_belongs_to_many_name_table_name || reflection.join_table
35
30
  join_table_name.to_s
36
31
  end
37
32
 
@@ -82,9 +77,7 @@ module Shoulda
82
77
  private
83
78
 
84
79
  def has_and_belongs_to_many_name_table_name
85
- if has_and_belongs_to_many_reflection
86
- has_and_belongs_to_many_reflection.table_name
87
- end
80
+ has_and_belongs_to_many_reflection&.table_name
88
81
  end
89
82
 
90
83
  def has_and_belongs_to_many_reflection
@@ -12,13 +12,13 @@ module Shoulda
12
12
  :join_table_name,
13
13
  :polymorphic?,
14
14
  :validate_inverse_of_through_association!,
15
- to: :reflection
15
+ to: :reflection,
16
16
  )
17
17
 
18
18
  delegate(
19
19
  :through?,
20
20
  to: :reflection,
21
- allow_nil: true
21
+ allow_nil: true,
22
22
  )
23
23
 
24
24
  def initialize(subject, name)
@@ -31,7 +31,7 @@ module Shoulda
31
31
  end
32
32
 
33
33
  def reflection
34
- @reflection ||= reflect_on_association(name)
34
+ @_reflection ||= reflect_on_association(name)
35
35
  end
36
36
 
37
37
  def reflect_on_association(name)
@@ -48,9 +48,12 @@ module Shoulda
48
48
 
49
49
  def build_relation_with_clause(name, value)
50
50
  case name
51
- when :conditions then associated_class.where(value)
52
- when :order then associated_class.order(value)
53
- else raise ArgumentError, "Unknown clause '#{name}'"
51
+ when :conditions
52
+ associated_class.where(value)
53
+ when :order
54
+ associated_class.order(value)
55
+ else
56
+ raise ArgumentError, "Unknown clause '#{name}'"
54
57
  end
55
58
  end
56
59
 
@@ -59,7 +62,9 @@ module Shoulda
59
62
  when :conditions
60
63
  relation.where_values_hash
61
64
  when :order
62
- relation.order_values.map { |value| value_as_sql(value) }.join(', ')
65
+ relation.order_values.map do |value|
66
+ value_as_sql(value)
67
+ end.join(', ')
63
68
  else
64
69
  raise ArgumentError, "Unknown clause '#{name}'"
65
70
  end
@@ -6,7 +6,12 @@ module Shoulda
6
6
  class OptionVerifier
7
7
  delegate :reflection, to: :reflector
8
8
 
9
- RELATION_OPTIONS = [:conditions, :order]
9
+ DEFAULT_VALUE_OF_OPTIONS = {
10
+ has_many: {
11
+ validate: true,
12
+ },
13
+ }.freeze
14
+ RELATION_OPTIONS = [:conditions, :order].freeze
10
15
 
11
16
  def initialize(reflector)
12
17
  @reflector = reflector
@@ -40,7 +45,7 @@ module Shoulda
40
45
  else
41
46
  type_cast_expected_value = type_cast(
42
47
  type,
43
- expected_value_for(type, name, expected_value)
48
+ expected_value_for(type, name, expected_value),
44
49
  )
45
50
  actual_value = type_cast(type, actual_value_for(name))
46
51
  type_cast_expected_value == actual_value
@@ -55,7 +60,7 @@ module Shoulda
55
60
  if respond_to?(method_name, true)
56
61
  __send__(method_name)
57
62
  else
58
- reflection.options[name]
63
+ actual_value_for_option(name)
59
64
  end
60
65
  end
61
66
  end
@@ -94,7 +99,7 @@ module Shoulda
94
99
 
95
100
  def expected_value_for_constant(name)
96
101
  namespace = Shoulda::Matchers::Util.deconstantize(
97
- reflector.model_class.to_s
102
+ reflector.model_class.to_s,
98
103
  )
99
104
 
100
105
  ["#{namespace}::#{name}", name].each do |path|
@@ -107,12 +112,25 @@ module Shoulda
107
112
  end
108
113
 
109
114
  def actual_value_for_relation_clause(name)
110
- reflector.extract_relation_clause_from(reflector.association_relation, name)
115
+ reflector.extract_relation_clause_from(
116
+ reflector.association_relation,
117
+ name,
118
+ )
111
119
  end
112
120
 
113
121
  def actual_value_for_class_name
114
122
  reflector.associated_class
115
123
  end
124
+
125
+ def actual_value_for_option(name)
126
+ option_value = reflection.options[name]
127
+
128
+ if option_value.nil?
129
+ DEFAULT_VALUE_OF_OPTIONS.dig(reflection.macro, name)
130
+ else
131
+ option_value
132
+ end
133
+ end
116
134
  end
117
135
  end
118
136
  end
@@ -32,9 +32,9 @@ module Shoulda
32
32
  end
33
33
 
34
34
  missing_option << (
35
- 'fail validation if ' +
36
- ":#{attribute_name} is unset; i.e., either the association " +
37
- 'should have been defined with `optional: ' +
35
+ 'fail validation if '\
36
+ ":#{attribute_name} is unset; i.e., either the association "\
37
+ 'should have been defined with `optional: '\
38
38
  "#{optional.inspect}`, or there "
39
39
  )
40
40
 
@@ -32,7 +32,7 @@ module Shoulda
32
32
  attr_accessor :subject, :order, :name
33
33
 
34
34
  def option_verifier
35
- @option_verifier ||= OptionVerifier.new(subject)
35
+ @_option_verifier ||= OptionVerifier.new(subject)
36
36
  end
37
37
  end
38
38
  end
@@ -33,9 +33,9 @@ module Shoulda
33
33
  end
34
34
 
35
35
  missing_option << (
36
- 'fail validation if ' +
37
- ":#{attribute_name} is unset; i.e., either the association " +
38
- 'should have been defined with `required: ' +
36
+ 'fail validation if '\
37
+ ":#{attribute_name} is unset; i.e., either the association "\
38
+ 'should have been defined with `required: '\
39
39
  "#{required.inspect}`, or there "
40
40
  )
41
41
 
@@ -65,7 +65,7 @@ module Shoulda
65
65
  end
66
66
 
67
67
  def validation_message_key
68
- RailsShim.validation_message_key_for_association_required_option
68
+ :required
69
69
  end
70
70
  end
71
71
  end
@@ -22,7 +22,8 @@ module Shoulda
22
22
  if option_verifier.correct_for_string?(:source, source)
23
23
  true
24
24
  else
25
- self.missing_option = "#{name} should have #{source} as source option"
25
+ self.missing_option =
26
+ "#{name} should have #{source} as source option"
26
27
  false
27
28
  end
28
29
  end
@@ -32,7 +33,7 @@ module Shoulda
32
33
  attr_accessor :subject, :source, :name
33
34
 
34
35
  def option_verifier
35
- @option_verifier ||= OptionVerifier.new(subject)
36
+ @_option_verifier ||= OptionVerifier.new(subject)
36
37
  end
37
38
  end
38
39
  end
@@ -29,13 +29,14 @@ module Shoulda
29
29
  if through_reflection.present?
30
30
  true
31
31
  else
32
- self.missing_option = "#{name} does not have any relationship to #{through}"
32
+ self.missing_option =
33
+ "#{name} does not have any relationship to #{through}"
33
34
  false
34
35
  end
35
36
  end
36
37
 
37
38
  def through_reflection
38
- @through_reflection ||= subject.reflect_on_association(through)
39
+ @_through_reflection ||= subject.reflect_on_association(through)
39
40
  end
40
41
 
41
42
  def through_association_correct?
@@ -43,8 +44,9 @@ module Shoulda
43
44
  true
44
45
  else
45
46
  self.missing_option =
46
- "Expected #{name} to have #{name} through #{through}, " +
47
- "but got it through #{option_verifier.actual_value_for(:through)}"
47
+ "Expected #{name} to have #{name} through #{through}, "\
48
+ 'but got it through ' +
49
+ option_verifier.actual_value_for(:through).to_s
48
50
  false
49
51
  end
50
52
  end
@@ -54,7 +56,7 @@ module Shoulda
54
56
  attr_accessor :through, :name, :subject
55
57
 
56
58
  def option_verifier
57
- @option_verifier ||= OptionVerifier.new(subject)
59
+ @_option_verifier ||= OptionVerifier.new(subject)
58
60
  end
59
61
  end
60
62
  end
@@ -6,16 +6,22 @@ module Shoulda
6
6
  #
7
7
  # class Process < ActiveRecord::Base
8
8
  # enum status: [:running, :stopped, :suspended]
9
+ #
10
+ # alias_attribute :kind, :SomeLegacyField
11
+ #
12
+ # enum kind: [:foo, :bar]
9
13
  # end
10
14
  #
11
15
  # # RSpec
12
16
  # RSpec.describe Process, type: :model do
13
17
  # it { should define_enum_for(:status) }
18
+ # it { should define_enum_for(:kind) }
14
19
  # end
15
20
  #
16
21
  # # Minitest (Shoulda)
17
22
  # class ProcessTest < ActiveSupport::TestCase
18
23
  # should define_enum_for(:status)
24
+ # should define_enum_for(:kind)
19
25
  # end
20
26
  #
21
27
  # #### Qualifiers
@@ -237,7 +243,7 @@ module Shoulda
237
243
  "Expected #{model} to #{expectation}, but "
238
244
  end
239
245
 
240
- message << failure_message_continuation + '.'
246
+ message << "#{failure_message_continuation}."
241
247
 
242
248
  Shoulda::Matchers.word_wrap(message)
243
249
  end
@@ -252,7 +258,7 @@ module Shoulda
252
258
  attr_reader :attribute_name, :options, :record,
253
259
  :failure_message_continuation
254
260
 
255
- def expectation
261
+ def expectation # rubocop:disable Metrics/MethodLength
256
262
  if enum_defined?
257
263
  expectation = "#{simple_description} backed by "
258
264
  expectation << Shoulda::Matchers::Util.a_or_an(expected_column_type)
@@ -358,8 +364,8 @@ module Shoulda
358
364
  true
359
365
  else
360
366
  @failure_message_continuation =
361
- "However, #{attribute_name.inspect} is " +
362
- Shoulda::Matchers::Util.a_or_an(column.type) +
367
+ "However, #{attribute_name.inspect} is "\
368
+ "#{Shoulda::Matchers::Util.a_or_an(column.type)}"\
363
369
  ' column'
364
370
  false
365
371
  end
@@ -370,7 +376,10 @@ module Shoulda
370
376
  end
371
377
 
372
378
  def column
373
- model.columns_hash[attribute_name.to_s]
379
+ key = attribute_name.to_s
380
+ column_name = model.attribute_alias(key) || key
381
+
382
+ model.columns_hash[column_name]
374
383
  end
375
384
 
376
385
  def model
@@ -421,9 +430,9 @@ module Shoulda
421
430
  def expected_prefix
422
431
  if options.include?(:prefix)
423
432
  if options[:prefix] == true
424
- attribute_name#.to_sym
433
+ attribute_name
425
434
  else
426
- options[:prefix]#.to_sym
435
+ options[:prefix]
427
436
  end
428
437
  end
429
438
  end
@@ -431,9 +440,9 @@ module Shoulda
431
440
  def expected_suffix
432
441
  if options.include?(:suffix)
433
442
  if options[:suffix] == true
434
- attribute_name#.to_sym
443
+ attribute_name
435
444
  else
436
- options[:suffix]#.to_sym
445
+ options[:suffix]
437
446
  end
438
447
  end
439
448
  end
@@ -1,10 +1,52 @@
1
1
  module Shoulda
2
2
  module Matchers
3
3
  module ActiveRecord
4
+ # The `have_one_attached` matcher tests usage of the
5
+ # `has_one_attached` macro.
6
+ #
7
+ # #### Example
8
+ #
9
+ # class User < ApplicationRecord
10
+ # has_one_attached :avatar
11
+ # end
12
+ #
13
+ # # RSpec
14
+ # RSpec.describe User, type: :model do
15
+ # it { should have_one_attached(:avatar) }
16
+ # end
17
+ #
18
+ # # Minitest (Shoulda)
19
+ # class UserTest < ActiveSupport::TestCase
20
+ # should have_one_attached(:avatar)
21
+ # end
22
+ #
23
+ # @return [HaveAttachedMatcher]
24
+ #
4
25
  def have_one_attached(name)
5
26
  HaveAttachedMatcher.new(:one, name)
6
27
  end
7
28
 
29
+ # The `have_many_attached` matcher tests usage of the
30
+ # `has_many_attached` macro.
31
+ #
32
+ # #### Example
33
+ #
34
+ # class Message < ApplicationRecord
35
+ # has_many_attached :images
36
+ # end
37
+ #
38
+ # # RSpec
39
+ # RSpec.describe Message, type: :model do
40
+ # it { should have_many_attached(:images) }
41
+ # end
42
+ #
43
+ # # Minitest (Shoulda)
44
+ # class MessageTest < ActiveSupport::TestCase
45
+ # should have_many_attached(:images)
46
+ # end
47
+ #
48
+ # @return [HaveAttachedMatcher]
49
+ #
8
50
  def have_many_attached(name)
9
51
  HaveAttachedMatcher.new(:many, name)
10
52
  end
@@ -92,10 +134,8 @@ Did not expect #{expectation}, but it does.
92
134
 
93
135
  def attachments_association_name
94
136
  case macro
95
- when :one then
96
- "#{name}_attachment"
97
- when :many then
98
- "#{name}_attachments"
137
+ when :one then "#{name}_attachment"
138
+ when :many then "#{name}_attachments"
99
139
  end
100
140
  end
101
141
 
@@ -121,10 +161,8 @@ Did not expect #{expectation}, but it does.
121
161
 
122
162
  def blobs_association_name
123
163
  case macro
124
- when :one then
125
- "#{name}_blob"
126
- when :many then
127
- "#{name}_blobs"
164
+ when :one then "#{name}_blob"
165
+ when :many then "#{name}_blobs"
128
166
  end
129
167
  end
130
168
 
@@ -84,6 +84,8 @@ module Shoulda
84
84
 
85
85
  # @private
86
86
  class HaveDbColumnMatcher
87
+ OPTIONS = %i(precision limit default null scale primary).freeze
88
+
87
89
  def initialize(column)
88
90
  @column = column
89
91
  @options = {}
@@ -95,7 +97,8 @@ module Shoulda
95
97
  end
96
98
 
97
99
  def with_options(opts = {})
98
- %w(precision limit default null scale primary).each do |attribute|
100
+ validate_options(opts)
101
+ OPTIONS.each do |attribute|
99
102
  if opts.key?(attribute.to_sym)
100
103
  @options[attribute.to_sym] = opts[attribute.to_sym]
101
104
  end
@@ -125,23 +128,38 @@ module Shoulda
125
128
 
126
129
  def description
127
130
  desc = "have db column named #{@column}"
128
- desc << " of type #{@options[:column_type]}" if @options.key?(:column_type)
129
- desc << " of precision #{@options[:precision]}" if @options.key?(:precision)
130
- desc << " of limit #{@options[:limit]}" if @options.key?(:limit)
131
- desc << " of default #{@options[:default]}" if @options.key?(:default)
132
- desc << " of null #{@options[:null]}" if @options.key?(:null)
133
- desc << " of primary #{@options[:primary]}" if @options.key?(:primary)
134
- desc << " of scale #{@options[:scale]}" if @options.key?(:scale)
131
+ if @options.key?(:column_type)
132
+ desc << " of type #{@options[:column_type]}"
133
+ end
134
+ if @options.key?(:precision)
135
+ desc << " of precision #{@options[:precision]}"
136
+ end
137
+ desc << " of limit #{@options[:limit]}" if @options.key?(:limit)
138
+ desc << " of default #{@options[:default]}" if @options.key?(:default)
139
+ desc << " of null #{@options[:null]}" if @options.key?(:null)
140
+ desc << " of primary #{@options[:primary]}" if @options.key?(:primary)
141
+ desc << " of scale #{@options[:scale]}" if @options.key?(:scale)
135
142
  desc
136
143
  end
137
144
 
138
145
  protected
139
146
 
147
+ def validate_options(opts)
148
+ invalid_options = opts.keys.map(&:to_sym) - OPTIONS
149
+ if invalid_options.any?
150
+ raise(
151
+ ArgumentError,
152
+ "Unknown option(s): #{invalid_options.map(&:inspect).join(', ')}",
153
+ )
154
+ end
155
+ end
156
+
140
157
  def column_exists?
141
158
  if model_class.column_names.include?(@column.to_s)
142
159
  true
143
160
  else
144
- @missing = "#{model_class} does not have a db column named #{@column}."
161
+ @missing =
162
+ "#{model_class} does not have a db column named #{@column}."
145
163
  false
146
164
  end
147
165
  end
@@ -152,8 +170,9 @@ module Shoulda
152
170
  if matched_column.type.to_s == @options[:column_type].to_s
153
171
  true
154
172
  else
155
- @missing = "#{model_class} has a db column named #{@column} " <<
156
- "of type #{matched_column.type}, not #{@options[:column_type]}."
173
+ @missing =
174
+ "#{model_class} has a db column named #{@column} " <<
175
+ "of type #{matched_column.type}, not #{@options[:column_type]}."
157
176
  false
158
177
  end
159
178
  end
@@ -229,18 +248,21 @@ module Shoulda
229
248
  true
230
249
  else
231
250
  @missing = "#{model_class} has a db column named #{@column} "
232
- if @options[:primary]
233
- @missing << 'that is not primary, but should be'
234
- else
235
- @missing << 'that is primary, but should not be'
236
- end
251
+ @missing <<
252
+ if @options[:primary]
253
+ 'that is not primary, but should be'
254
+ else
255
+ 'that is primary, but should not be'
256
+ end
237
257
  false
238
258
  end
239
259
  end
240
260
 
241
261
  def matched_column
242
262
  @_matched_column ||= begin
243
- column = model_class.columns.detect { |each| each.name == @column.to_s }
263
+ column = model_class.columns.detect do |each|
264
+ each.name == @column.to_s
265
+ end
244
266
  DecoratedColumn.new(model_class, column)
245
267
  end
246
268
  end