shoulda-matchers 4.1.2 → 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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/{MIT-LICENSE → LICENSE} +1 -1
  3. data/README.md +168 -86
  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 +31 -29
  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 -30
  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 +9 -8
  30. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +28 -46
  31. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +33 -9
  32. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +71 -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 +31 -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 -23
  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 +100 -44
  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 +14 -15
  46. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +30 -8
  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 +185 -0
  55. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +40 -18
  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 +106 -0
  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 +83 -0
  60. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +30 -9
  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 +80 -73
  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.rb +0 -1
  75. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +14 -13
  76. data/lib/shoulda/matchers/integrations/configuration.rb +1 -1
  77. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
  78. data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -2
  79. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
  80. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
  81. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
  82. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
  83. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
  84. data/lib/shoulda/matchers/rails_shim.rb +10 -21
  85. data/lib/shoulda/matchers/util.rb +16 -4
  86. data/lib/shoulda/matchers/util/word_wrap.rb +8 -8
  87. data/lib/shoulda/matchers/version.rb +1 -1
  88. data/lib/shoulda/matchers/warn.rb +3 -3
  89. data/shoulda-matchers.gemspec +10 -7
  90. metadata +11 -9
  91. data/lib/shoulda/matchers/independent/delegate_method_matcher/stubbed_target.rb +0 -37
@@ -232,13 +232,34 @@ module Shoulda
232
232
  # it { should validate_length_of(:bio).is_at_least(15).allow_nil }
233
233
  # end
234
234
  #
235
- # # Test::Unit
235
+ # # Minitest (Shoulda)
236
236
  # class UserTest < ActiveSupport::TestCase
237
237
  # should validate_length_of(:bio).is_at_least(15).allow_nil
238
238
  # end
239
239
  #
240
240
  # @return [ValidateLengthOfMatcher]
241
241
  #
242
+ # # ##### allow_blank
243
+ #
244
+ # Use `allow_blank` to assert that the attribute allows blank.
245
+ #
246
+ # class User
247
+ # include ActiveModel::Model
248
+ # attr_accessor :bio
249
+ #
250
+ # validates_length_of :bio, minimum: 15, allow_blank: true
251
+ # end
252
+ #
253
+ # # RSpec
254
+ # describe User do
255
+ # it { should validate_length_of(:bio).is_at_least(15).allow_blank }
256
+ # end
257
+ #
258
+ # # Minitest (Shoulda)
259
+ # class UserTest < ActiveSupport::TestCase
260
+ # should validate_length_of(:bio).is_at_least(15).allow_blank
261
+ # end
262
+ #
242
263
  def validate_length_of(attr)
243
264
  ValidateLengthOfMatcher.new(attr)
244
265
  end
@@ -331,7 +352,8 @@ module Shoulda
331
352
 
332
353
  lower_bound_matches? &&
333
354
  upper_bound_matches? &&
334
- allow_nil_matches?
355
+ allow_nil_matches? &&
356
+ allow_blank_matches?
335
357
  end
336
358
 
337
359
  def does_not_match?(subject)
@@ -339,7 +361,8 @@ module Shoulda
339
361
 
340
362
  lower_bound_does_not_match? ||
341
363
  upper_bound_does_not_match? ||
342
- allow_nil_does_not_match?
364
+ allow_nil_does_not_match? ||
365
+ allow_blank_does_not_match?
343
366
  end
344
367
 
345
368
  private
@@ -369,16 +392,17 @@ module Shoulda
369
392
  @options[:minimum] > 0 &&
370
393
  allows_length_of?(
371
394
  @options[:minimum] - 1,
372
- translated_short_message
395
+ translated_short_message,
373
396
  )
374
397
  end
375
398
 
376
399
  def disallows_lower_length?
377
400
  !@options.key?(:minimum) ||
378
401
  @options[:minimum] == 0 ||
402
+ (@options[:minimum] == 1 && expects_to_allow_blank?) ||
379
403
  disallows_length_of?(
380
404
  @options[:minimum] - 1,
381
- translated_short_message
405
+ translated_short_message,
382
406
  )
383
407
  end
384
408
 
@@ -386,7 +410,7 @@ module Shoulda
386
410
  @options.key?(:maximum) &&
387
411
  allows_length_of?(
388
412
  @options[:maximum] + 1,
389
- translated_long_message
413
+ translated_long_message,
390
414
  )
391
415
  end
392
416
 
@@ -394,7 +418,7 @@ module Shoulda
394
418
  !@options.key?(:maximum) ||
395
419
  disallows_length_of?(
396
420
  @options[:maximum] + 1,
397
- translated_long_message
421
+ translated_long_message,
398
422
  )
399
423
  end
400
424
 
@@ -446,7 +470,7 @@ module Shoulda
446
470
  model_name: @subject.class.to_s.underscore,
447
471
  instance: @subject,
448
472
  attribute: @attribute,
449
- count: @options[:minimum]
473
+ count: @options[:minimum],
450
474
  )
451
475
  else
452
476
  @short_message
@@ -461,7 +485,7 @@ module Shoulda
461
485
  model_name: @subject.class.to_s.underscore,
462
486
  instance: @subject,
463
487
  attribute: @attribute,
464
- count: @options[:maximum]
488
+ count: @options[:maximum],
465
489
  )
466
490
  else
467
491
  @long_message
@@ -204,6 +204,33 @@ module Shoulda
204
204
  # is_greater_than(21)
205
205
  # end
206
206
  #
207
+ # ##### is_other_than
208
+ #
209
+ # Use `is_other_than` to test usage of the `:other_than` option.
210
+ # This asserts that the attribute can take a number which is not equal to
211
+ # the given value.
212
+ #
213
+ # class Person
214
+ # include ActiveModel::Model
215
+ # attr_accessor :legal_age
216
+ #
217
+ # validates_numericality_of :legal_age, other_than: 21
218
+ # end
219
+ #
220
+ # # RSpec
221
+ # RSpec.describe Person, type: :model do
222
+ # it do
223
+ # should validate_numericality_of(:legal_age).
224
+ # is_other_than(21)
225
+ # end
226
+ # end
227
+ #
228
+ # # Minitest (Shoulda)
229
+ # class PersonTest < ActiveSupport::TestCase
230
+ # should validate_numericality_of(:legal_age).
231
+ # is_other_than(21)
232
+ # end
233
+ #
207
234
  # ##### even
208
235
  #
209
236
  # Use `even` to test usage of the `:even` option. This asserts that the
@@ -304,8 +331,7 @@ module Shoulda
304
331
 
305
332
  # @private
306
333
  class ValidateNumericalityOfMatcher
307
- NUMERIC_NAME = 'number'
308
- NON_NUMERIC_VALUE = 'abcd'
334
+ NUMERIC_NAME = 'number'.freeze
309
335
  DEFAULT_DIFF_TO_COMPARE = 1
310
336
 
311
337
  include Qualifiers::IgnoringInterferenceByWriter
@@ -337,7 +363,7 @@ module Shoulda
337
363
 
338
364
  def only_integer
339
365
  prepare_submatcher(
340
- NumericalityMatchers::OnlyIntegerMatcher.new(self, @attribute)
366
+ NumericalityMatchers::OnlyIntegerMatcher.new(self, @attribute),
341
367
  )
342
368
  self
343
369
  end
@@ -345,9 +371,9 @@ module Shoulda
345
371
  def allow_nil
346
372
  @expects_to_allow_nil = true
347
373
  prepare_submatcher(
348
- AllowValueMatcher.new(nil)
349
- .for(@attribute)
350
- .with_message(:not_a_number)
374
+ AllowValueMatcher.new(nil).
375
+ for(@attribute).
376
+ with_message(:not_a_number),
351
377
  )
352
378
  self
353
379
  end
@@ -358,14 +384,14 @@ module Shoulda
358
384
 
359
385
  def odd
360
386
  prepare_submatcher(
361
- NumericalityMatchers::OddNumberMatcher.new(self, @attribute)
387
+ NumericalityMatchers::OddNumberMatcher.new(self, @attribute),
362
388
  )
363
389
  self
364
390
  end
365
391
 
366
392
  def even
367
393
  prepare_submatcher(
368
- NumericalityMatchers::EvenNumberMatcher.new(self, @attribute)
394
+ NumericalityMatchers::EvenNumberMatcher.new(self, @attribute),
369
395
  )
370
396
  self
371
397
  end
@@ -395,6 +421,11 @@ module Shoulda
395
421
  self
396
422
  end
397
423
 
424
+ def is_other_than(value)
425
+ prepare_submatcher(comparison_matcher_for(value, :!=).for(@attribute))
426
+ self
427
+ end
428
+
398
429
  def with_message(message)
399
430
  @expects_custom_validation_message = true
400
431
  @expected_message = message
@@ -427,7 +458,7 @@ module Shoulda
427
458
  description << Shoulda::Matchers::Util.a_or_an(full_allowed_type)
428
459
 
429
460
  if comparison_descriptions.present?
430
- description << ' ' + comparison_descriptions
461
+ description << " #{comparison_descriptions}"
431
462
  end
432
463
 
433
464
  description
@@ -447,7 +478,8 @@ module Shoulda
447
478
  def failure_message_when_negated
448
479
  overall_failure_message_when_negated.dup.tap do |message|
449
480
  message << "\n"
450
- message << failure_message_for_first_submatcher_that_fails_to_not_match
481
+ message <<
482
+ failure_message_for_first_submatcher_that_fails_to_not_match
451
483
  end
452
484
  end
453
485
 
@@ -468,15 +500,15 @@ module Shoulda
468
500
 
469
501
  def overall_failure_message
470
502
  Shoulda::Matchers.word_wrap(
471
- "Expected #{model.name} to #{description}, but this could not " +
472
- 'be proved.'
503
+ "Expected #{model.name} to #{description}, but this could not "\
504
+ 'be proved.',
473
505
  )
474
506
  end
475
507
 
476
508
  def overall_failure_message_when_negated
477
509
  Shoulda::Matchers.word_wrap(
478
- "Expected #{model.name} not to #{description}, but this could not " +
479
- 'be proved.'
510
+ "Expected #{model.name} not to #{description}, but this could not "\
511
+ 'be proved.',
480
512
  )
481
513
  end
482
514
 
@@ -498,7 +530,7 @@ module Shoulda
498
530
 
499
531
  def add_disallow_value_matcher
500
532
  disallow_value_matcher = DisallowValueMatcher.
501
- new(NON_NUMERIC_VALUE).
533
+ new(non_numeric_value).
502
534
  for(@attribute).
503
535
  with_message(:not_a_number)
504
536
 
@@ -526,7 +558,10 @@ module Shoulda
526
558
  end
527
559
 
528
560
  if submatcher.respond_to?(:diff_to_compare)
529
- @diff_to_compare = [@diff_to_compare, submatcher.diff_to_compare].max
561
+ @diff_to_compare = [
562
+ @diff_to_compare,
563
+ submatcher.diff_to_compare,
564
+ ].max
530
565
  end
531
566
 
532
567
  @submatchers << submatcher
@@ -547,7 +582,7 @@ module Shoulda
547
582
  end
548
583
 
549
584
  submatcher.ignoring_interference_by_writer(
550
- ignore_interference_by_writer
585
+ ignore_interference_by_writer,
551
586
  )
552
587
  end
553
588
  end
@@ -568,28 +603,30 @@ module Shoulda
568
603
  end
569
604
 
570
605
  def first_submatcher_that_fails_to_match
571
- @_failing_submatchers ||= @submatchers.detect do |submatcher|
572
- !submatcher.matches?(@subject)
573
- end
606
+ @_first_submatcher_that_fails_to_match ||=
607
+ @submatchers.detect do |submatcher|
608
+ !submatcher.matches?(@subject)
609
+ end
574
610
  end
575
611
 
576
612
  def first_submatcher_that_fails_to_not_match
577
- @_failing_submatchers ||= @submatchers.detect do |submatcher|
578
- !submatcher.does_not_match?(@subject)
579
- end
613
+ @_first_submatcher_that_fails_to_not_match ||=
614
+ @submatchers.detect do |submatcher|
615
+ !submatcher.does_not_match?(@subject)
616
+ end
580
617
  end
581
618
 
582
619
  def failure_message_for_first_submatcher_that_fails_to_match
583
620
  build_submatcher_failure_message_for(
584
621
  first_submatcher_that_fails_to_match,
585
- :failure_message
622
+ :failure_message,
586
623
  )
587
624
  end
588
625
 
589
626
  def failure_message_for_first_submatcher_that_fails_to_not_match
590
627
  build_submatcher_failure_message_for(
591
628
  first_submatcher_that_fails_to_not_match,
592
- :failure_message_when_negated
629
+ :failure_message_when_negated,
593
630
  )
594
631
  end
595
632
 
@@ -620,7 +657,11 @@ module Shoulda
620
657
 
621
658
  def comparison_descriptions
622
659
  description_array = submatcher_comparison_descriptions
623
- description_array.empty? ? '' : submatcher_comparison_descriptions.join(' and ')
660
+ if description_array.empty?
661
+ ''
662
+ else
663
+ submatcher_comparison_descriptions.join(' and ')
664
+ end
624
665
  end
625
666
 
626
667
  def submatcher_comparison_descriptions
@@ -635,6 +676,10 @@ module Shoulda
635
676
  def model
636
677
  @subject.class
637
678
  end
679
+
680
+ def non_numeric_value
681
+ 'abcd'
682
+ end
638
683
  end
639
684
  end
640
685
  end
@@ -260,11 +260,11 @@ validation for you? Instead of using `validate_presence_of`, try
260
260
 
261
261
  def reason_for_existing_presence_validation
262
262
  if belongs_to_association_configured_to_be_required?
263
- "you've instructed your `belongs_to` association to add a " +
263
+ "you've instructed your `belongs_to` association to add a "\
264
264
  'presence validation to the attribute'
265
265
  else
266
266
  # assume ::ActiveRecord::Base.belongs_to_required_by_default == true
267
- 'ActiveRecord is configured to add a presence validation to all ' +
267
+ 'ActiveRecord is configured to add a presence validation to all '\
268
268
  '`belongs_to` associations, and this includes yours'
269
269
  end
270
270
  end
@@ -24,6 +24,11 @@ module Shoulda
24
24
  self
25
25
  end
26
26
 
27
+ def allow_blank
28
+ options[:allow_blank] = true
29
+ self
30
+ end
31
+
27
32
  def strict
28
33
  @expects_strict = true
29
34
  self
@@ -62,7 +67,7 @@ module Shoulda
62
67
  message << "\n"
63
68
  message << Shoulda::Matchers.word_wrap(
64
69
  failure_reason,
65
- indent: 2
70
+ indent: 2,
66
71
  )
67
72
  end
68
73
  end
@@ -74,7 +79,7 @@ module Shoulda
74
79
  message << "\n"
75
80
  message << Shoulda::Matchers.word_wrap(
76
81
  failure_reason,
77
- indent: 2
82
+ indent: 2,
78
83
  )
79
84
  end
80
85
  end
@@ -116,19 +121,31 @@ module Shoulda
116
121
  )
117
122
  end
118
123
 
124
+ def allow_blank_matches?
125
+ !expects_to_allow_blank? ||
126
+ blank_values.all? { |value| allows_value_of(value) }
127
+ end
128
+
129
+ def allow_blank_does_not_match?
130
+ expects_to_allow_blank? &&
131
+ blank_values.all? { |value| disallows_value_of(value) }
132
+ end
133
+
119
134
  private
120
135
 
136
+ attr_reader :options
137
+
121
138
  def overall_failure_message
122
139
  Shoulda::Matchers.word_wrap(
123
- "Expected #{model.name} to #{description}, but this could not be " +
124
- 'proved.'
140
+ "Expected #{model.name} to #{description}, but this could not be "\
141
+ 'proved.',
125
142
  )
126
143
  end
127
144
 
128
145
  def overall_failure_message_when_negated
129
146
  Shoulda::Matchers.word_wrap(
130
- "Expected #{model.name} not to #{description}, but this could " +
131
- 'not be proved.'
147
+ "Expected #{model.name} not to #{description}, but this could "\
148
+ 'not be proved.',
132
149
  )
133
150
  end
134
151
 
@@ -161,6 +178,14 @@ module Shoulda
161
178
  @last_submatcher_run = matcher
162
179
  matcher.matches?(subject)
163
180
  end
181
+
182
+ def expects_to_allow_blank?
183
+ options[:allow_blank]
184
+ end
185
+
186
+ def blank_values
187
+ ['', ' ', "\n", "\r", "\t", "\f"]
188
+ end
164
189
  end
165
190
  end
166
191
  end
@@ -15,10 +15,8 @@ module Shoulda
15
15
 
16
16
  def call
17
17
  if description_clauses_for_qualifiers.any?
18
- main_description +
19
- clause_for_allow_blank_or_nil +
20
- ', ' +
21
- description_clauses_for_qualifiers.to_sentence
18
+ "#{main_description}#{clause_for_allow_blank_or_nil},"\
19
+ " #{description_clauses_for_qualifiers.to_sentence}"
22
20
  else
23
21
  main_description + clause_for_allow_blank_or_nil
24
22
  end
@@ -5,7 +5,7 @@ module Shoulda
5
5
  class ValidationMessageFinder
6
6
  include Helpers
7
7
 
8
- def initialize(instance, attribute, context=nil)
8
+ def initialize(instance, attribute, context = nil)
9
9
  @instance = instance
10
10
  @attribute = attribute
11
11
  @context = context
@@ -50,7 +50,7 @@ module Shoulda
50
50
  end
51
51
 
52
52
  def validated_instance
53
- @validated_instance ||= validate_instance
53
+ @_validated_instance ||= validate_instance
54
54
  end
55
55
 
56
56
  def validate_instance
@@ -58,8 +58,6 @@ module Shoulda
58
58
  @instance
59
59
  end
60
60
  end
61
-
62
61
  end
63
62
  end
64
63
  end
65
-