shoulda-matchers 4.4.1 → 4.5.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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +22 -0
  3. data/README.md +7 -9
  4. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +4 -2
  5. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +3 -2
  6. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +26 -21
  7. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +6 -8
  8. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +6 -8
  9. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +16 -13
  10. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +2 -1
  11. data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -6
  12. data/lib/shoulda/matchers/action_controller/route_params.rb +1 -1
  13. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +19 -13
  14. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +18 -16
  15. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +29 -27
  16. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +1 -1
  17. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +5 -5
  18. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +2 -2
  19. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +1 -1
  20. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +1 -1
  21. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +1 -1
  22. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +51 -25
  23. data/lib/shoulda/matchers/active_model/helpers.rb +1 -1
  24. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +32 -34
  25. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +1 -1
  26. data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +1 -1
  27. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +9 -1
  28. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +2 -2
  29. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +8 -7
  30. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +26 -25
  31. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +6 -6
  32. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +39 -26
  33. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +2 -2
  34. data/lib/shoulda/matchers/active_model/validation_matcher.rb +6 -6
  35. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +2 -4
  36. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +2 -4
  37. data/lib/shoulda/matchers/active_model/validator.rb +3 -3
  38. data/lib/shoulda/matchers/active_record.rb +26 -26
  39. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +6 -3
  40. data/lib/shoulda/matchers/active_record/association_matcher.rb +80 -40
  41. data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +5 -2
  42. data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -4
  43. data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +1 -1
  44. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +11 -6
  45. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +2 -9
  46. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +12 -7
  47. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +23 -5
  48. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +3 -3
  49. data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +1 -1
  50. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +3 -3
  51. data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +3 -2
  52. data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +7 -5
  53. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +8 -8
  54. data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +46 -8
  55. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +39 -17
  56. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
  57. data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +7 -7
  58. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +12 -10
  59. data/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +11 -7
  60. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +2 -0
  61. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +13 -9
  62. data/lib/shoulda/matchers/active_record/uniqueness.rb +1 -1
  63. data/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +1 -3
  64. data/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +0 -2
  65. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +78 -71
  66. data/lib/shoulda/matchers/doublespeak.rb +2 -1
  67. data/lib/shoulda/matchers/doublespeak/double.rb +1 -1
  68. data/lib/shoulda/matchers/doublespeak/double_collection.rb +3 -3
  69. data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +8 -5
  70. data/lib/shoulda/matchers/doublespeak/object_double.rb +1 -1
  71. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +1 -5
  72. data/lib/shoulda/matchers/doublespeak/world.rb +2 -2
  73. data/lib/shoulda/matchers/error.rb +1 -1
  74. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +14 -13
  75. data/lib/shoulda/matchers/integrations/configuration.rb +1 -1
  76. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
  77. data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -2
  78. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
  79. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
  80. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
  81. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
  82. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
  83. data/lib/shoulda/matchers/rails_shim.rb +5 -3
  84. data/lib/shoulda/matchers/util.rb +7 -2
  85. data/lib/shoulda/matchers/util/word_wrap.rb +7 -7
  86. data/lib/shoulda/matchers/version.rb +1 -1
  87. data/lib/shoulda/matchers/warn.rb +3 -3
  88. data/shoulda-matchers.gemspec +10 -7
  89. metadata +11 -10
@@ -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
@@ -156,7 +156,7 @@ module Shoulda
156
156
 
157
157
  description <<
158
158
  if qualifiers.include?(:unique)
159
- Shoulda::Matchers::Util.a_or_an(index_type) + ' '
159
+ "#{Shoulda::Matchers::Util.a_or_an(index_type)} "
160
160
  else
161
161
  'an '
162
162
  end
@@ -39,22 +39,22 @@ module Shoulda
39
39
  check_column_exists!
40
40
  check_implicit_order_column_matches!
41
41
  true
42
- rescue SecondaryCheckFailedError => error
42
+ rescue SecondaryCheckFailedError => e
43
43
  @failure_message = Shoulda::Matchers.word_wrap(
44
44
  "Expected #{model.name} to #{expectation}, " +
45
- "but that could not be proved: #{error.message}."
45
+ "but that could not be proved: #{e.message}.",
46
46
  )
47
47
  false
48
- rescue PrimaryCheckFailedError => error
48
+ rescue PrimaryCheckFailedError => e
49
49
  @failure_message = Shoulda::Matchers.word_wrap(
50
- "Expected #{model.name} to #{expectation}, but #{error.message}."
50
+ "Expected #{model.name} to #{expectation}, but #{e.message}.",
51
51
  )
52
52
  false
53
53
  end
54
54
 
55
55
  def failure_message_when_negated
56
56
  Shoulda::Matchers.word_wrap(
57
- "Expected #{model.name} not to #{expectation}, but it did."
57
+ "Expected #{model.name} not to #{expectation}, but it did.",
58
58
  )
59
59
  end
60
60
 
@@ -72,7 +72,7 @@ module Shoulda
72
72
  if !matcher.matches?(@subject)
73
73
  raise SecondaryCheckFailedError.new(
74
74
  "The :#{model.table_name} table does not have a " +
75
- ":#{column_name} column"
75
+ ":#{column_name} column",
76
76
  )
77
77
  end
78
78
  end
@@ -81,7 +81,7 @@ module Shoulda
81
81
  if model.implicit_order_column.to_s != column_name.to_s
82
82
  message =
83
83
  if model.implicit_order_column.nil?
84
- "implicit_order_column is not set"
84
+ 'implicit_order_column is not set'
85
85
  else
86
86
  "it is :#{model.implicit_order_column}"
87
87
  end
@@ -35,17 +35,19 @@ module Shoulda
35
35
  def matches?(subject)
36
36
  @subject = subject
37
37
  if readonly_attributes.include?(@attribute)
38
- @failure_message_when_negated = "Did not expect #{@attribute} to be read-only"
38
+ @failure_message_when_negated = "Did not expect #{@attribute}"\
39
+ ' to be read-only'
39
40
  true
40
41
  else
41
- if readonly_attributes.empty?
42
- @failure_message = "#{class_name} attribute #{@attribute} " <<
43
- 'is not read-only'
44
- else
45
- @failure_message = "#{class_name} is making " <<
46
- "#{readonly_attributes.to_a.to_sentence} " <<
47
- "read-only, but not #{@attribute}."
48
- end
42
+ @failure_message =
43
+ if readonly_attributes.empty?
44
+ "#{class_name} attribute #{@attribute} " <<
45
+ 'is not read-only'
46
+ else
47
+ "#{class_name} is making " <<
48
+ "#{readonly_attributes.to_a.to_sentence} " <<
49
+ "read-only, but not #{@attribute}."
50
+ end
49
51
  false
50
52
  end
51
53
  end
@@ -57,7 +59,7 @@ module Shoulda
57
59
  private
58
60
 
59
61
  def readonly_attributes
60
- @readonly_attributes ||= (@subject.class.readonly_attributes || [])
62
+ @_readonly_attributes ||= (@subject.class.readonly_attributes || [])
61
63
  end
62
64
 
63
65
  def class_name
@@ -12,7 +12,7 @@ module Shoulda
12
12
  #
13
13
  # # RSpec
14
14
  # RSpec.describe Post, type: :model do
15
- # it { is_expected.to have_rich_text(:content) }
15
+ # it { should have_rich_text(:content) }
16
16
  # end
17
17
  #
18
18
  # # Minitest (Shoulda)
@@ -20,20 +20,21 @@ module Shoulda
20
20
  # should have_rich_text(:content)
21
21
  # end
22
22
  #
23
- # @return [HaveRichText]
23
+ # @return [HaveRichTextMatcher]
24
24
  #
25
25
  def have_rich_text(rich_text_attribute)
26
- HaveRichText.new(rich_text_attribute)
26
+ HaveRichTextMatcher.new(rich_text_attribute)
27
27
  end
28
28
 
29
29
  # @private
30
- class HaveRichText
30
+ class HaveRichTextMatcher
31
31
  def initialize(rich_text_attribute)
32
32
  @rich_text_attribute = rich_text_attribute
33
33
  end
34
34
 
35
35
  def description
36
- "have configured :#{rich_text_attribute} as a ActionText::RichText association"
36
+ "have configured :#{rich_text_attribute} as a "\
37
+ 'ActionText::RichText association'
37
38
  end
38
39
 
39
40
  def failure_message
@@ -41,7 +42,8 @@ module Shoulda
41
42
  end
42
43
 
43
44
  def failure_message_when_negated
44
- "Did not expect #{subject.class} to have ActionText::RichText :#{rich_text_attribute}"
45
+ "Did not expect #{subject.class} to have ActionText::RichText"\
46
+ " :#{rich_text_attribute}"
45
47
  end
46
48
 
47
49
  def matches?(subject)
@@ -67,7 +69,9 @@ module Shoulda
67
69
  end
68
70
 
69
71
  def has_expected_action_text?
70
- @subject.send(rich_text_attribute).class.name == 'ActionText::RichText'
72
+ defined?(ActionText::RichText) &&
73
+ @subject.send(rich_text_attribute).
74
+ instance_of?(ActionText::RichText)
71
75
  end
72
76
 
73
77
  def error_description
@@ -63,12 +63,14 @@ module Shoulda
63
63
 
64
64
  def failure_message
65
65
  return if !@errors
66
+
66
67
  "Expected #{@subject.class} to #{description} but the following " \
67
68
  "errors were found: #{@errors.join(', ')}"
68
69
  end
69
70
 
70
71
  def failure_message_when_negated
71
72
  return if !@errors
73
+
72
74
  "Did not expect #{@subject.class} to have secure token " \
73
75
  ":#{token_attribute}"
74
76
  end
@@ -121,7 +121,9 @@ module Shoulda
121
121
 
122
122
  def description
123
123
  description = "serialize :#{@name}"
124
- description += " class_name => #{@options[:type]}" if @options.key?(:type)
124
+ if @options.key?(:type)
125
+ description += " class_name => #{@options[:type]}"
126
+ end
125
127
  description
126
128
  end
127
129
 
@@ -141,13 +143,12 @@ module Shoulda
141
143
  klass = serialization_coder
142
144
  if klass == @options[:type]
143
145
  true
146
+ elsif klass.respond_to?(:object_class) &&
147
+ klass.object_class == @options[:type]
148
+ true
144
149
  else
145
- if klass.respond_to?(:object_class) && klass.object_class == @options[:type]
146
- true
147
- else
148
- @missing = ":#{@name} should be a type of #{@options[:type]}"
149
- false
150
- end
150
+ @missing = ":#{@name} should be a type of #{@options[:type]}"
151
+ false
151
152
  end
152
153
  else
153
154
  true
@@ -176,9 +177,12 @@ module Shoulda
176
177
  end
177
178
 
178
179
  def expectation
179
- expectation = "#{model_class.name} to serialize the attribute called :#{@name}"
180
+ expectation = "#{model_class.name} to serialize the attribute called"\
181
+ " :#{@name}"
180
182
  expectation += " with a type of #{@options[:type]}" if @options[:type]
181
- expectation += " with an instance of #{@options[:instance_type]}" if @options[:instance_type]
183
+ if @options[:instance_type]
184
+ expectation += " with an instance of #{@options[:instance_type]}"
185
+ end
182
186
  expectation
183
187
  end
184
188
 
@@ -1,6 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
- module ActiveModel
3
+ module ActiveRecord
4
4
  # @private
5
5
  module Uniqueness
6
6
  end
@@ -1,5 +1,3 @@
1
- require 'thread'
2
-
3
1
  module Shoulda
4
2
  module Matchers
5
3
  module ActiveRecord
@@ -37,7 +35,7 @@ module Shoulda
37
35
  def new_model
38
36
  @_new_model ||= Model.next_unique_copy_of(
39
37
  model_name_without_namespace,
40
- namespace
38
+ namespace,
41
39
  )
42
40
  end
43
41
 
@@ -1,5 +1,3 @@
1
- require 'thread'
2
-
3
1
  module Shoulda
4
2
  module Matchers
5
3
  module ActiveRecord
@@ -80,7 +80,7 @@ module Shoulda
80
80
  #
81
81
  # RSpec.describe Post, type: :model do
82
82
  # describe "validations" do
83
- # subject { Post.create(content: "Here is the content") }
83
+ # subject { Post.new(content: "Here is the content") }
84
84
  # it { should validate_uniqueness_of(:title) }
85
85
  # end
86
86
  # end
@@ -92,7 +92,7 @@ module Shoulda
92
92
  #
93
93
  # RSpec.describe Post, type: :model do
94
94
  # describe "validations" do
95
- # subject { FactoryBot.create(:post) }
95
+ # subject { FactoryBot.build(:post) }
96
96
  # it { should validate_uniqueness_of(:title) }
97
97
  # end
98
98
  # end
@@ -157,6 +157,12 @@ module Shoulda
157
157
  # should validate_uniqueness_of(:slug).scoped_to(:journal_id)
158
158
  # end
159
159
  #
160
+ # NOTE: Support for testing uniqueness validation scoped to an array of
161
+ # associations is not available.
162
+ #
163
+ # For more information, please refer to
164
+ # https://github.com/thoughtbot/shoulda-matchers/issues/814
165
+ #
160
166
  # ##### case_insensitive
161
167
  #
162
168
  # Use `case_insensitive` to test usage of the `:case_sensitive` option
@@ -264,14 +270,14 @@ module Shoulda
264
270
  super(attribute)
265
271
  @expected_message = :taken
266
272
  @options = {
267
- case_sensitivity_strategy: :sensitive
273
+ case_sensitivity_strategy: :sensitive,
268
274
  }
269
275
  @existing_record_created = false
270
276
  @failure_reason = nil
271
277
  @failure_reason_when_negated = nil
272
278
  @attribute_setters = {
273
279
  existing_record: AttributeSetters.new,
274
- new_record: AttributeSetters.new
280
+ new_record: AttributeSetters.new,
275
281
  }
276
282
  end
277
283
 
@@ -407,11 +413,12 @@ module Shoulda
407
413
  else
408
414
  @failure_reason = 'Expected the validation '
409
415
 
410
- if expected_scopes.empty?
411
- @failure_reason << 'not to be scoped to anything, '
412
- else
413
- @failure_reason << "to be scoped to #{inspected_expected_scopes}, "
414
- end
416
+ @failure_reason <<
417
+ if expected_scopes.empty?
418
+ 'not to be scoped to anything, '
419
+ else
420
+ "to be scoped to #{inspected_expected_scopes}, "
421
+ end
415
422
 
416
423
  if actual_sets_of_scopes.any?
417
424
  @failure_reason << 'but it was scoped to '
@@ -455,7 +462,7 @@ module Shoulda
455
462
  def inspected_actual_scopes
456
463
  inspected_actual_sets_of_scopes.to_sentence(
457
464
  words_connector: ' and ',
458
- last_word_connector: ', and'
465
+ last_word_connector: ', and',
459
466
  )
460
467
  end
461
468
 
@@ -491,7 +498,9 @@ module Shoulda
491
498
  def does_not_match_allow_nil?
492
499
  expects_to_allow_nil? && (
493
500
  update_existing_record!(nil) &&
494
- (@failure_reason = nil || disallows_value_of(nil, @expected_message))
501
+ (@failure_reason = nil ||
502
+ disallows_value_of(nil, @expected_message)
503
+ )
495
504
  )
496
505
  end
497
506
 
@@ -527,21 +536,15 @@ module Shoulda
527
536
  end
528
537
 
529
538
  def find_existing_record
530
- record = model.first
531
-
532
- if record.present?
533
- record
534
- else
535
- nil
536
- end
539
+ model.first.presence
537
540
  end
538
541
 
539
542
  def create_existing_record
540
543
  @given_record.tap do |existing_record|
541
544
  existing_record.save(validate: false)
542
545
  end
543
- rescue ::ActiveRecord::StatementInvalid => error
544
- raise ExistingRecordInvalid.create(underlying_exception: error)
546
+ rescue ::ActiveRecord::StatementInvalid => e
547
+ raise ExistingRecordInvalid.create(underlying_exception: e)
545
548
  end
546
549
 
547
550
  def update_existing_record!(value)
@@ -577,7 +580,7 @@ module Shoulda
577
580
  attribute_names_under_test.each do |attribute_name|
578
581
  set_attribute_on_new_record!(
579
582
  attribute_name,
580
- existing_record.public_send(attribute_name)
583
+ existing_record.public_send(attribute_name),
581
584
  )
582
585
  end
583
586
 
@@ -619,11 +622,12 @@ module Shoulda
619
622
 
620
623
  reason << inspected_scopes.to_sentence
621
624
 
622
- if inspected_scopes.many?
623
- reason << " do not seem to be attributes"
624
- else
625
- reason << " does not seem to be an attribute"
626
- end
625
+ reason <<
626
+ if inspected_scopes.many?
627
+ ' do not seem to be attributes'
628
+ else
629
+ ' does not seem to be an attribute'
630
+ end
627
631
 
628
632
  reason << " on #{model.name}."
629
633
 
@@ -643,11 +647,12 @@ module Shoulda
643
647
 
644
648
  reason << inspected_scopes.to_sentence
645
649
 
646
- if inspected_scopes.many?
647
- reason << " seem to be attributes"
648
- else
649
- reason << " seems to be an attribute"
650
- end
650
+ reason <<
651
+ if inspected_scopes.many?
652
+ ' seem to be attributes'
653
+ else
654
+ ' seems to be an attribute'
655
+ end
651
656
 
652
657
  reason << " on #{model.name}."
653
658
 
@@ -658,14 +663,14 @@ module Shoulda
658
663
  end
659
664
 
660
665
  def scopes_present_on_model
661
- @_present_scopes ||= expected_scopes.select do |scope|
666
+ @_scopes_present_on_model ||= expected_scopes.select do |scope|
662
667
  model.method_defined?("#{scope}=")
663
668
  end
664
669
  end
665
670
 
666
671
  def scopes_missing_on_model
667
- @_missing_scopes ||= expected_scopes.select do |scope|
668
- !model.method_defined?("#{scope}=")
672
+ @_scopes_missing_on_model ||= expected_scopes.reject do |scope|
673
+ model.method_defined?("#{scope}=")
669
674
  end
670
675
  end
671
676
 
@@ -697,7 +702,7 @@ module Shoulda
697
702
  raise NonCaseSwappableValueError.create(
698
703
  model: model,
699
704
  attribute: @attribute,
700
- value: value
705
+ value: value,
701
706
  )
702
707
  end
703
708
 
@@ -724,7 +729,7 @@ module Shoulda
724
729
  raise NonCaseSwappableValueError.create(
725
730
  model: model,
726
731
  attribute: @attribute,
727
- value: value
732
+ value: value,
728
733
  )
729
734
  end
730
735
 
@@ -789,7 +794,7 @@ module Shoulda
789
794
  column = column_for(scope)
790
795
 
791
796
  if column.respond_to?(:array) && column.array
792
- [ dummy_scalar_value_for(column) ]
797
+ [dummy_scalar_value_for(column)]
793
798
  else
794
799
  dummy_scalar_value_for(column)
795
800
  end
@@ -801,7 +806,7 @@ module Shoulda
801
806
 
802
807
  def next_value_for(scope, previous_value)
803
808
  if previous_value.is_a?(Array)
804
- [ next_scalar_value_for(scope, previous_value[0]) ]
809
+ [next_scalar_value_for(scope, previous_value[0])]
805
810
  else
806
811
  next_scalar_value_for(scope, previous_value)
807
812
  end
@@ -857,7 +862,7 @@ module Shoulda
857
862
  attribute_setter = build_attribute_setter(
858
863
  record,
859
864
  attribute_name,
860
- value
865
+ value,
861
866
  )
862
867
  attribute_setter.set!
863
868
 
@@ -869,7 +874,7 @@ module Shoulda
869
874
  :existing_record,
870
875
  existing_record,
871
876
  attribute_name,
872
- value
877
+ value,
873
878
  )
874
879
  end
875
880
 
@@ -878,7 +883,7 @@ module Shoulda
878
883
  :new_record,
879
884
  new_record,
880
885
  attribute_name,
881
- value
886
+ value,
882
887
  )
883
888
  end
884
889
 
@@ -896,13 +901,14 @@ module Shoulda
896
901
  end
897
902
 
898
903
  def build_attribute_setter(record, attribute_name, value)
899
- Shoulda::Matchers::ActiveModel::AllowValueMatcher::AttributeSetter.new(
900
- matcher_name: :validate_uniqueness_of,
901
- object: record,
902
- attribute_name: attribute_name,
903
- value: value,
904
- ignore_interference_by_writer: ignore_interference_by_writer
905
- )
904
+ Shoulda::Matchers::ActiveModel::AllowValueMatcher::AttributeSetter.
905
+ new(
906
+ matcher_name: :validate_uniqueness_of,
907
+ object: record,
908
+ attribute_name: attribute_name,
909
+ value: value,
910
+ ignore_interference_by_writer: ignore_interference_by_writer,
911
+ )
906
912
  end
907
913
 
908
914
  def existing_value_read
@@ -929,7 +935,7 @@ module Shoulda
929
935
  @given_record.class
930
936
  end
931
937
 
932
- def failure_message_preface
938
+ def failure_message_preface # rubocop:disable Metrics/MethodLength
933
939
  prefix = ''
934
940
 
935
941
  if @existing_record_created
@@ -938,30 +944,28 @@ module Shoulda
938
944
  if attribute_setter_for_existing_record
939
945
  prefix << ', setting '
940
946
  prefix << description_for_attribute_setter(
941
- attribute_setter_for_existing_record
947
+ attribute_setter_for_existing_record,
942
948
  )
943
949
  else
944
950
  prefix << ", whose :#{attribute} is "
945
951
  prefix << "‹#{existing_value_read.inspect}›"
946
952
  end
947
953
 
948
- prefix << ", and saving it as the existing record, then"
954
+ prefix << ', and saving it as the existing record, then'
955
+ elsif attribute_setter_for_existing_record
956
+ prefix << "Given an existing #{model.name},"
957
+ prefix << ' after setting '
958
+ prefix << description_for_attribute_setter(
959
+ attribute_setter_for_existing_record,
960
+ )
961
+ prefix << ', then'
949
962
  else
950
- if attribute_setter_for_existing_record
951
- prefix << "Given an existing #{model.name},"
952
- prefix << ' after setting '
953
- prefix << description_for_attribute_setter(
954
- attribute_setter_for_existing_record
955
- )
956
- prefix << ', then'
957
- else
958
- prefix << "Given an existing #{model.name} whose :#{attribute}"
959
- prefix << ' is '
960
- prefix << Shoulda::Matchers::Util.inspect_value(
961
- existing_value_read
962
- )
963
- prefix << ', after'
964
- end
963
+ prefix << "Given an existing #{model.name} whose :#{attribute}"
964
+ prefix << ' is '
965
+ prefix << Shoulda::Matchers::Util.inspect_value(
966
+ existing_value_read,
967
+ )
968
+ prefix << ', after'
965
969
  end
966
970
 
967
971
  prefix << " making a new #{model.name} and setting "
@@ -988,7 +992,10 @@ different altogether.
988
992
  MESSAGE
989
993
  end
990
994
 
991
- def description_for_attribute_setter(attribute_setter, same_as_existing: nil)
995
+ def description_for_attribute_setter(
996
+ attribute_setter,
997
+ same_as_existing: nil
998
+ )
992
999
  description = "its :#{attribute_setter.attribute_name} to "
993
1000
 
994
1001
  if same_as_existing == false
@@ -996,13 +1003,13 @@ different altogether.
996
1003
  end
997
1004
 
998
1005
  description << Shoulda::Matchers::Util.inspect_value(
999
- attribute_setter.value_written
1006
+ attribute_setter.value_written,
1000
1007
  )
1001
1008
 
1002
1009
  if attribute_setter.attribute_changed_value?
1003
1010
  description << ' (read back as '
1004
1011
  description << Shoulda::Matchers::Util.inspect_value(
1005
- attribute_setter.value_read
1012
+ attribute_setter.value_read,
1006
1013
  )
1007
1014
  description << ')'
1008
1015
  end
@@ -1026,7 +1033,7 @@ different altogether.
1026
1033
  )
1027
1034
  description_for_attribute_setter(
1028
1035
  attribute_setter,
1029
- same_as_existing: same_as_existing
1036
+ same_as_existing: same_as_existing,
1030
1037
  )
1031
1038
  end
1032
1039
  end
@@ -1109,7 +1116,7 @@ b) If you meant for the validation to be case-insensitive, then you need to
1109
1116
 
1110
1117
  For more information, please see:
1111
1118
 
1112
- http://matchers.shoulda.io/docs/v#{Shoulda::Matchers::VERSION}/file.NonCaseSwappableValueError.html
1119
+ https://matchers.shoulda.io/docs/v#{Shoulda::Matchers::VERSION}/file.NonCaseSwappableValueError.html
1113
1120
  MESSAGE
1114
1121
  end
1115
1122
  end