diff --git a/lib/shoulda/matchers/active_record/association_matcher.rb b/lib/shoulda/matchers/active_record/association_matcher.rb index cba6a93db..dbf4d8554 100644 --- a/lib/shoulda/matchers/active_record/association_matcher.rb +++ b/lib/shoulda/matchers/active_record/association_matcher.rb @@ -255,6 +255,46 @@ module ActiveRecord # # @return [AssociationMatcher] # + # ##### required + # + # Use `required` to assert that the `:required` option was specified. + # + # class Person < ActiveRecord::Base + # belongs_to :organization, required: true + # end + # + # # RSpec + # describe Person + # it { should belong_to(:organization).required } + # end + # + # # Minitest (Shoulda) + # class PersonTest < ActiveSupport::TestCase + # should belong_to(:organization).required + # end + # + # @return [AssociationMatcher] + # + # ##### optional + # + # Use `optional` to assert that the `:optional` option was specified. + # + # class Person < ActiveRecord::Base + # belongs_to :organization, optional: true + # end + # + # # RSpec + # describe Person + # it { should belong_to(:organization).optional } + # end + # + # # Minitest (Shoulda) + # class PersonTest < ActiveSupport::TestCase + # should belong_to(:organization).optional + # end + # + # @return [AssociationMatcher] + # def belong_to(name) AssociationMatcher.new(:belongs_to, name) end @@ -937,6 +977,17 @@ def with_primary_key(primary_key) self end + # TODO: Removed when Rails 4.2 support finished. + def required(required = true) + @options[:required] = required + self + end + + def optional(optional = true) + @options[:optional] = optional + self + end + def validate(validate = true) @options[:validate] = validate self @@ -975,6 +1026,8 @@ def matches?(subject) primary_key_exists? && class_name_correct? && join_table_correct? && + required_correct? && # TODO: Removed when Rails 4.2 support finished. + optional_correct? && autosave_correct? && conditions_correct? && validate_correct? && @@ -1130,6 +1183,33 @@ def autosave_correct? end end + # TODO: Removed when Rails 4.2 support finished. + def required_correct? + if options.key?(:required) + if option_verifier.correct_for_boolean?(:required, options[:required]) + true + else + @missing = "#{name} should have required set to #{options[:required]}" + false + end + else + true + end + end + + def optional_correct? + if options.key?(:optional) + if option_verifier.correct_for_boolean?(:optional, options[:optional]) + true + else + @missing = "#{name} should have optional set to #{options[:optional]}" + false + end + else + true + end + end + def conditions_correct? if options.key?(:conditions) if option_verifier.correct_for_relation_clause?(:conditions, options[:conditions]) diff --git a/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb b/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb index b51f9b4e9..c99d6e155 100644 --- a/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb @@ -53,6 +53,44 @@ expect(Child.new).to belong_to(:parent) end + # TODO: Removed when Rails 4.2 support finished. + it 'accepts an association with a valid :required option' do + begin + expect(belonging_to_parent(required: true)). + to belong_to(:parent).required + rescue + skip 'This version does not support required qualifier' + end + end + + # TODO: Removed when Rails 4.2 support finished. + it 'accepts an association with a valid :required option' do + begin + expect(belonging_to_parent(required: false)). + not_to belong_to(:parent).required + rescue + skip 'This version does not support required qualifier' + end + end + + it 'accepts an association with a valid :optional option' do + begin + expect(belonging_to_parent(optional: true)). + to belong_to(:parent).optional + rescue + skip 'This version does not support optional qualifier' + end + end + + it 'accepts an association with a valid :optional option' do + begin + expect(belonging_to_parent(optional: false)). + not_to belong_to(:parent).optional + rescue + skip 'This version does not support optional qualifier' + end + end + it 'accepts an association with a valid :dependent option' do expect(belonging_to_parent(dependent: :destroy)). to belong_to(:parent).dependent(:destroy)