shoulda-matchers 3.1.3 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.hound/ruby.yml +336 -316
  3. data/.python-version +1 -0
  4. data/.rubocop.yml +3 -1
  5. data/.travis.yml +7 -6
  6. data/Appraisals +76 -44
  7. data/CONTRIBUTING.md +137 -66
  8. data/Gemfile +5 -5
  9. data/Gemfile.lock +30 -35
  10. data/MAINTAINING.md +250 -0
  11. data/MIT-LICENSE +1 -1
  12. data/NEWS.md +176 -4
  13. data/README.md +138 -200
  14. data/Rakefile +7 -0
  15. data/bin/setup +190 -0
  16. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +4 -0
  17. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -6
  18. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -17
  19. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +27 -0
  20. data/gemfiles/4.2.gemfile +21 -20
  21. data/gemfiles/4.2.gemfile.lock +143 -140
  22. data/gemfiles/5.0.gemfile +37 -0
  23. data/gemfiles/5.0.gemfile.lock +238 -0
  24. data/gemfiles/5.1.gemfile +38 -0
  25. data/gemfiles/5.1.gemfile.lock +254 -0
  26. data/gemfiles/5.2.gemfile +40 -0
  27. data/gemfiles/5.2.gemfile.lock +273 -0
  28. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +18 -6
  29. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +6 -1
  30. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +1 -1
  31. data/lib/shoulda/matchers/action_controller/route_matcher.rb +87 -27
  32. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +1 -0
  33. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +0 -4
  34. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +5 -0
  35. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +5 -0
  36. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +26 -11
  37. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +39 -4
  38. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +116 -47
  39. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +127 -38
  40. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +55 -37
  41. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +30 -1
  42. data/lib/shoulda/matchers/active_model/validation_matcher.rb +11 -4
  43. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +11 -6
  44. data/lib/shoulda/matchers/active_record.rb +3 -0
  45. data/lib/shoulda/matchers/active_record/association_matcher.rb +172 -22
  46. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +1 -1
  47. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +11 -6
  48. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +46 -0
  49. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +51 -0
  50. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +268 -38
  51. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
  52. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +111 -0
  53. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +207 -79
  54. data/lib/shoulda/matchers/doublespeak/object_double.rb +5 -1
  55. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +100 -21
  56. data/lib/shoulda/matchers/rails_shim.rb +133 -52
  57. data/lib/shoulda/matchers/routing.rb +2 -2
  58. data/lib/shoulda/matchers/util.rb +23 -1
  59. data/lib/shoulda/matchers/util/word_wrap.rb +6 -2
  60. data/lib/shoulda/matchers/version.rb +1 -1
  61. data/script/install_gems_in_all_appraisals +3 -1
  62. data/script/run_all_tests +3 -1
  63. data/script/supported_ruby_versions +7 -0
  64. data/script/update_gem_in_all_appraisals +3 -1
  65. data/script/update_gems_in_all_appraisals +3 -1
  66. data/shoulda-matchers.gemspec +3 -3
  67. data/spec/acceptance/independent_matchers_spec.rb +2 -2
  68. data/spec/acceptance/multiple_libraries_integration_spec.rb +1 -1
  69. data/spec/acceptance/rails_integration_spec.rb +2 -2
  70. data/spec/spec_helper.rb +2 -3
  71. data/spec/support/acceptance/helpers.rb +2 -0
  72. data/spec/support/acceptance/helpers/command_helpers.rb +17 -4
  73. data/spec/support/acceptance/helpers/rails_migration_helpers.rb +21 -0
  74. data/spec/support/acceptance/helpers/step_helpers.rb +1 -1
  75. data/spec/support/tests/current_bundle.rb +3 -9
  76. data/spec/support/tests/filesystem.rb +2 -2
  77. data/spec/support/unit/attribute.rb +0 -2
  78. data/spec/support/unit/capture.rb +9 -3
  79. data/spec/support/unit/helpers/action_pack_versions.rb +22 -0
  80. data/spec/support/unit/helpers/active_model_versions.rb +4 -0
  81. data/spec/support/unit/helpers/active_record_versions.rb +22 -2
  82. data/spec/support/unit/helpers/active_resource_builder.rb +2 -2
  83. data/spec/support/unit/helpers/controller_builder.rb +1 -1
  84. data/spec/support/unit/helpers/message_helpers.rb +19 -0
  85. data/spec/support/unit/helpers/rails_versions.rb +14 -0
  86. data/spec/support/unit/matchers/fail_with_message_matcher.rb +7 -5
  87. data/spec/support/unit/matchers/print_warning_including.rb +21 -13
  88. data/spec/support/unit/model_creation_strategies/active_record.rb +1 -1
  89. data/spec/support/unit/model_creators/active_record.rb +0 -1
  90. data/spec/support/unit/model_creators/basic.rb +7 -2
  91. data/spec/support/unit/rails_application.rb +25 -0
  92. data/spec/support/unit/record_validating_confirmation_builder.rb +5 -2
  93. data/spec/support/unit/validation_matcher_scenario.rb +0 -2
  94. data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +18 -18
  95. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +33 -5
  96. data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +1 -1
  97. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +80 -78
  98. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +7 -9
  99. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +28 -4
  100. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +19 -1
  101. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +27 -4
  102. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +62 -5
  103. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +52 -18
  104. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +51 -4
  105. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +99 -71
  106. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +41 -15
  107. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +445 -15
  108. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +615 -93
  109. data/spec/unit/shoulda/matchers/active_record/have_secure_token_matcher_spec.rb +169 -0
  110. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +167 -97
  111. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +2 -4
  112. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +152 -19
  113. data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +258 -94
  114. data/spec/unit_spec_helper.rb +9 -1
  115. data/zeus.json +1 -1
  116. metadata +31 -16
  117. data/gemfiles/4.0.0.gemfile +0 -38
  118. data/gemfiles/4.0.0.gemfile.lock +0 -223
  119. data/gemfiles/4.0.1.gemfile +0 -38
  120. data/gemfiles/4.0.1.gemfile.lock +0 -225
  121. data/gemfiles/4.1.gemfile +0 -38
  122. data/gemfiles/4.1.gemfile.lock +0 -220
  123. data/script/SUPPORTED_VERSIONS +0 -1
@@ -82,18 +82,18 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do
82
82
  end
83
83
 
84
84
  it 'accepts an association with a valid :inverse_of option' do
85
- expect(belonging_to_parent(inverse_of: :children))
86
- .to belong_to(:parent).inverse_of(:children)
85
+ expect(belonging_to_with_inverse(:parent, :children)).
86
+ to belong_to(:parent).inverse_of(:children)
87
87
  end
88
88
 
89
89
  it 'rejects an association with a bad :inverse_of option' do
90
- expect(belonging_to_parent(inverse_of: :other_children))
91
- .not_to belong_to(:parent).inverse_of(:children)
90
+ expect(belonging_to_with_inverse(:parent, :other_children)).
91
+ not_to belong_to(:parent).inverse_of(:children)
92
92
  end
93
93
 
94
94
  it 'rejects an association that has no :inverse_of option' do
95
- expect(belonging_to_parent)
96
- .not_to belong_to(:parent).inverse_of(:children)
95
+ expect(belonging_to_parent).
96
+ not_to belong_to(:parent).inverse_of(:children)
97
97
  end
98
98
 
99
99
  it 'accepts an association with a valid :conditions option' do
@@ -279,11 +279,373 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do
279
279
  end
280
280
  end
281
281
 
282
- def belonging_to_parent(options = {})
283
- define_model :parent
282
+ context 'given the association is neither configured to be required nor optional' do
283
+ context 'when qualified with required(true)' do
284
+ if active_record_supports_optional_for_associations?
285
+ context 'when belongs_to is configured to be required by default' do
286
+ it 'passes' do
287
+ configuring_default_belongs_to_requiredness(true) do
288
+ expect(belonging_to_parent).to belong_to(:parent).required(true)
289
+ end
290
+ end
291
+ end
292
+
293
+ context 'when belongs_to is not configured to be required by default' do
294
+ it 'fails with an appropriate message' do
295
+ configuring_default_belongs_to_requiredness(false) do
296
+ assertion = lambda do
297
+ expect(belonging_to_parent).
298
+ to belong_to(:parent).required(true)
299
+ end
300
+
301
+ message = format_message(<<-MESSAGE, one_line: true)
302
+ Expected Child to have a belongs_to association called parent
303
+ (the association should have been defined with `required:
304
+ true`, but was not)
305
+ MESSAGE
306
+
307
+ expect(&assertion).to fail_with_message(message)
308
+ end
309
+ end
310
+ end
311
+ else
312
+ it 'fails with an appropriate message' do
313
+ assertion = lambda do
314
+ expect(belonging_to_parent).
315
+ to belong_to(:parent).required(true)
316
+ end
317
+
318
+ message = format_message(<<-MESSAGE, one_line: true)
319
+ Expected Child to have a belongs_to association called parent
320
+ (the association should have been defined with `required:
321
+ true`, but was not)
322
+ MESSAGE
323
+
324
+ expect(&assertion).to fail_with_message(message)
325
+ end
326
+ end
327
+ end
328
+
329
+ context 'when qualified with required(false)' do
330
+ if active_record_supports_optional_for_associations?
331
+ context 'when belongs_to is configured to be required by default' do
332
+ it 'fails with an appropriate message' do
333
+ configuring_default_belongs_to_requiredness(true) do
334
+ assertion = lambda do
335
+ expect(belonging_to_parent).
336
+ to belong_to(:parent).required(false)
337
+ end
338
+
339
+ message = format_message(<<-MESSAGE, one_line: true)
340
+ Expected Child to have a belongs_to association called parent
341
+ (the association should have been defined with `required:
342
+ false`, but was not)
343
+ MESSAGE
344
+
345
+ expect(&assertion).to fail_with_message(message)
346
+ end
347
+ end
348
+ end
349
+
350
+ context 'when belongs_to is not configured to be required by default' do
351
+ it 'passes' do
352
+ configuring_default_belongs_to_requiredness(false) do
353
+ expect(belonging_to_parent).to belong_to(:parent).required(false)
354
+ end
355
+ end
356
+ end
357
+ else
358
+ it 'passes' do
359
+ expect(belonging_to_parent).to belong_to(:parent).required(false)
360
+ end
361
+ end
362
+ end
363
+
364
+ context 'when qualified with optional' do
365
+ if active_record_supports_optional_for_associations?
366
+ context 'when belongs_to is configured to be required by default' do
367
+ it 'fails with an appropriate message' do
368
+ configuring_default_belongs_to_requiredness(true) do
369
+ assertion = lambda do
370
+ expect(belonging_to_parent).
371
+ to belong_to(:parent).optional
372
+ end
373
+
374
+ message = format_message(<<-MESSAGE, one_line: true)
375
+ Expected Child to have a belongs_to association called parent (the
376
+ association should have been defined with `optional: true`, but
377
+ was not)
378
+ MESSAGE
379
+
380
+ expect(&assertion).to fail_with_message(message)
381
+ end
382
+ end
383
+ end
384
+
385
+ context 'when belongs_to is not configured to be required by default' do
386
+ it 'passes' do
387
+ configuring_default_belongs_to_requiredness(false) do
388
+ expect(belonging_to_parent).to belong_to(:parent).optional
389
+ end
390
+ end
391
+ end
392
+ else
393
+ it 'passes' do
394
+ expect(belonging_to_parent).to belong_to(:parent).optional
395
+ end
396
+ end
397
+ end
398
+
399
+ context 'when qualified with nothing' do
400
+ if active_record_supports_optional_for_associations?
401
+ context 'when belongs_to is configured to be required by default' do
402
+ it 'passes' do
403
+ configuring_default_belongs_to_requiredness(true) do
404
+ expect(belonging_to_parent).to belong_to(:parent)
405
+ end
406
+ end
407
+ end
408
+
409
+ context 'when belongs_to is not configured to be required by default' do
410
+ it 'passes' do
411
+ configuring_default_belongs_to_requiredness(false) do
412
+ expect(belonging_to_parent).to belong_to(:parent)
413
+ end
414
+ end
415
+
416
+ context 'and a presence validation is on the attribute instead of using required: true' do
417
+ it 'passes' do
418
+ configuring_default_belongs_to_requiredness(false) do
419
+ record = belonging_to_parent do
420
+ validates_presence_of :parent
421
+ end
422
+
423
+ expect(record).to belong_to(:parent)
424
+ end
425
+ end
426
+ end
427
+
428
+ context 'and a presence validation is on the attribute with a condition' do
429
+ context 'and the condition is true' do
430
+ it 'passes' do
431
+ configuring_default_belongs_to_requiredness(false) do
432
+ child_model = create_child_model_belonging_to_parent do
433
+ attr_accessor :condition
434
+ validates_presence_of :parent, if: :condition
435
+ end
436
+
437
+ record = child_model.new(condition: true)
438
+
439
+ expect(record).to belong_to(:parent)
440
+ end
441
+ end
442
+ end
443
+
444
+ context 'and the condition is false' do
445
+ it 'passes' do
446
+ configuring_default_belongs_to_requiredness(false) do
447
+ child_model = create_child_model_belonging_to_parent do
448
+ attr_accessor :condition
449
+ validates_presence_of :parent, if: :condition
450
+ end
451
+
452
+ record = child_model.new(condition: false)
453
+
454
+ expect(record).to belong_to(:parent)
455
+ end
456
+ end
457
+ end
458
+ end
459
+ end
460
+ else
461
+ it 'passes' do
462
+ expect(belonging_to_parent).to belong_to(:parent)
463
+ end
464
+
465
+ context 'and a presence validation is on the attribute instead of using required: true' do
466
+ it 'passes' do
467
+ record = belonging_to_parent do
468
+ validates_presence_of :parent
469
+ end
470
+
471
+ expect(record).to belong_to(:parent)
472
+ end
473
+ end
474
+
475
+ context 'and a presence validation is on the attribute with a condition' do
476
+ context 'and the condition is true' do
477
+ it 'passes' do
478
+ child_model = create_child_model_belonging_to_parent do
479
+ attr_accessor :condition
480
+ validates_presence_of :parent, if: :condition
481
+ end
482
+
483
+ record = child_model.new(condition: true)
484
+
485
+ expect(record).to belong_to(:parent)
486
+ end
487
+ end
488
+
489
+ context 'and the condition is false' do
490
+ it 'passes' do
491
+ child_model = create_child_model_belonging_to_parent do
492
+ attr_accessor :condition
493
+ validates_presence_of :parent, if: :condition
494
+ end
495
+
496
+ record = child_model.new(condition: false)
497
+
498
+ expect(record).to belong_to(:parent)
499
+ end
500
+ end
501
+ end
502
+ end
503
+ end
504
+ end
505
+
506
+ context 'given the association is configured with required: true' do
507
+ context 'when qualified with required(true)' do
508
+ it 'passes' do
509
+ expect(belonging_to_parent(required: true)).
510
+ to belong_to(:parent).required(true)
511
+ end
512
+ end
513
+
514
+ context 'when qualified with required(false)' do
515
+ it 'passes' do
516
+ assertion = lambda do
517
+ expect(belonging_to_parent(required: true)).
518
+ to belong_to(:parent).required(false)
519
+ end
520
+
521
+ message = format_message(<<-MESSAGE, one_line: true)
522
+ Expected Child to have a belongs_to association called parent (the
523
+ association should have been defined with `required: false`, but
524
+ was not)
525
+ MESSAGE
526
+
527
+ expect(&assertion).to fail_with_message(message)
528
+ end
529
+ end
530
+
531
+ context 'when qualified with optional' do
532
+ it 'fails with an appropriate message' do
533
+ assertion = lambda do
534
+ expect(belonging_to_parent(required: true)).
535
+ to belong_to(:parent).optional
536
+ end
537
+
538
+ message = format_message(<<-MESSAGE, one_line: true)
539
+ Expected Child to have a belongs_to association called parent (the
540
+ association should have been defined with `optional: true`, but
541
+ was not)
542
+ MESSAGE
543
+
544
+ expect(&assertion).to fail_with_message(message)
545
+ end
546
+ end
547
+
548
+ context 'when qualified with nothing' do
549
+ it 'passes' do
550
+ expect(belonging_to_parent(required: true)).to belong_to(:parent)
551
+ end
552
+ end
553
+ end
554
+
555
+ if active_record_supports_optional_for_associations?
556
+ context 'given the association is configured as optional: true' do
557
+ context 'when qualified with required(true)' do
558
+ it 'fails with an appropriate message' do
559
+ assertion = lambda do
560
+ expect(belonging_to_parent(optional: true)).
561
+ to belong_to(:parent).required(true)
562
+ end
563
+
564
+ message = format_message(<<-MESSAGE, one_line: true)
565
+ Expected Child to have a belongs_to association called parent (the
566
+ association should have been defined with `required: true`, but
567
+ was not)
568
+ MESSAGE
569
+
570
+ expect(&assertion).to fail_with_message(message)
571
+ end
572
+ end
573
+
574
+ context 'when qualified with required(false)' do
575
+ it 'passes' do
576
+ expect(belonging_to_parent(optional: true)).
577
+ to belong_to(:parent).required(false)
578
+ end
579
+ end
580
+
581
+ context 'when qualified with optional' do
582
+ it 'passes' do
583
+ expect(belonging_to_parent(optional: true)).
584
+ to belong_to(:parent).optional
585
+ end
586
+ end
587
+
588
+ context 'when qualified with nothing' do
589
+ it 'fails with an appropriate message' do
590
+ assertion = lambda do
591
+ expect(belonging_to_parent(optional: true)).
592
+ to belong_to(:parent)
593
+ end
594
+
595
+ message = format_message(<<-MESSAGE, one_line: true)
596
+ Expected Child to have a belongs_to association called parent (the
597
+ association should have been defined with `required: true`, but
598
+ was not)
599
+ MESSAGE
600
+
601
+ expect(&assertion).to fail_with_message(message)
602
+ end
603
+ end
604
+ end
605
+ end
606
+
607
+ def belonging_to_parent(options = {}, parent_options = {}, &block)
608
+ child_model = create_child_model_belonging_to_parent(
609
+ options,
610
+ parent_options,
611
+ &block
612
+ )
613
+ child_model.new
614
+ end
615
+
616
+ def create_child_model_belonging_to_parent(
617
+ options = {},
618
+ parent_options = {},
619
+ &block
620
+ )
621
+ define_model(:parent, parent_options)
622
+
284
623
  define_model :child, parent_id: :integer do
285
624
  belongs_to :parent, options
286
- end.new
625
+
626
+ if block
627
+ class_eval(&block)
628
+ end
629
+ end
630
+ end
631
+
632
+ def belonging_to_with_inverse(association, inverse_association)
633
+ parent_model_name = association.to_s.singularize
634
+ child_model_name = inverse_association.to_s.singularize
635
+ parent_foreign_key = "#{parent_model_name}_id"
636
+
637
+ define_model parent_model_name do
638
+ has_many inverse_association
639
+ end
640
+
641
+ child_model = define_model(
642
+ child_model_name,
643
+ parent_foreign_key => :integer,
644
+ ) do
645
+ belongs_to association, inverse_of: inverse_association
646
+ end
647
+
648
+ child_model.new
287
649
  end
288
650
 
289
651
  def belonging_to_non_existent_class(model_name, assoc_name, options = {})
@@ -526,6 +888,33 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do
526
888
  }.to fail_with_message(message)
527
889
  end
528
890
 
891
+ if rails_5_x?
892
+ context 'index_errors' do
893
+ it 'accepts an association with a matching :index_errors option' do
894
+ define_model :child, parent_id: :integer
895
+ define_model :parent do
896
+ has_many :children, index_errors: true
897
+ end
898
+ expect(Parent.new).to have_many(:children).index_errors(true)
899
+ end
900
+
901
+ it 'rejects an association with a non-matching :index_errors option and returns the correct message' do
902
+ define_model :child, parent_id: :integer
903
+ define_model :parent do
904
+ has_many :children, autosave: false
905
+ end
906
+
907
+ message =
908
+ 'Expected Parent to have a has_many association called children ' +
909
+ '(children should have index_errors set to true)'
910
+
911
+ expect {
912
+ expect(Parent.new).to have_many(:children).index_errors(true)
913
+ }.to fail_with_message(message)
914
+ end
915
+ end
916
+ end
917
+
529
918
  context 'validate' do
530
919
  it 'accepts when the :validate option matches' do
531
920
  expect(having_many_children(validate: false)).to have_many(:children).validate(false)
@@ -826,6 +1215,31 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do
826
1215
  end
827
1216
  end
828
1217
 
1218
+ if active_record_supports_optional_for_associations?
1219
+ context 'given an association with a matching :required option' do
1220
+ it 'passes' do
1221
+ expect(having_one_detail(required: true)).
1222
+ to have_one(:detail).required
1223
+ end
1224
+ end
1225
+ end
1226
+
1227
+ context 'given an association with a non-matching :required option' do
1228
+ it 'fails with an appropriate message' do
1229
+ assertion = lambda do
1230
+ expect(having_one_detail(required: false)).
1231
+ to have_one(:detail).required
1232
+ end
1233
+
1234
+ message =
1235
+ 'Expected Person to have a has_one association called detail ' +
1236
+ '(the association should have been defined with `required: true`, ' +
1237
+ 'but was not)'
1238
+
1239
+ expect(&assertion).to fail_with_message(message)
1240
+ end
1241
+ end
1242
+
829
1243
  def having_one_detail(options = {})
830
1244
  define_model :detail, person_id: :integer
831
1245
  define_model(:person).tap do |model|
@@ -1210,7 +1624,7 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do
1210
1624
  def define_association_with_conditions(model, macro, name, conditions, other_options={})
1211
1625
  args = []
1212
1626
  options = {}
1213
- if Shoulda::Matchers::RailsShim.active_record_major_version == 4
1627
+ if active_record_supports_relations?
1214
1628
  args << proc { where(conditions) }
1215
1629
  else
1216
1630
  options[:conditions] = conditions
@@ -1222,7 +1636,7 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do
1222
1636
  def define_association_with_order(model, macro, name, order, other_options={})
1223
1637
  args = []
1224
1638
  options = {}
1225
- if Shoulda::Matchers::RailsShim.active_record_major_version == 4
1639
+ if active_record_supports_relations?
1226
1640
  args << proc { order(order) }
1227
1641
  else
1228
1642
  options[:order] = order
@@ -1232,11 +1646,27 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do
1232
1646
  end
1233
1647
 
1234
1648
  def dependent_options
1235
- case Rails.version
1236
- when /\A3/
1237
- [:destroy, :delete, :nullify, :restrict]
1238
- when /\A4/
1649
+ if active_record_supports_more_dependent_options?
1239
1650
  [:destroy, :delete, :nullify, :restrict_with_exception, :restrict_with_error]
1651
+ else
1652
+ [:destroy, :delete, :nullify, :restrict]
1240
1653
  end
1241
1654
  end
1655
+
1656
+ def configuring_default_belongs_to_requiredness(value, &block)
1657
+ configuring_application(
1658
+ ActiveRecord::Base,
1659
+ :belongs_to_required_by_default,
1660
+ value,
1661
+ &block
1662
+ )
1663
+ end
1664
+
1665
+ def configuring_application(config, name, value)
1666
+ previous_value = config.send(name)
1667
+ config.send("#{name}=", value)
1668
+ yield
1669
+ ensure
1670
+ config.send("#{name}=", previous_value)
1671
+ end
1242
1672
  end