From ed962dee3e56fa6e209b5e6747827caa7155e9db Mon Sep 17 00:00:00 2001 From: Gui Vieira Date: Tue, 3 Sep 2019 22:05:47 -0700 Subject: [PATCH] Add optional(false) support to belong_to (#1237) --- .../active_record/association_matcher.rb | 4 +- .../active_record/association_matcher_spec.rb | 90 +++++++++++++++++-- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/lib/shoulda/matchers/active_record/association_matcher.rb b/lib/shoulda/matchers/active_record/association_matcher.rb index 3d9bd2c6..19a712dc 100644 --- a/lib/shoulda/matchers/active_record/association_matcher.rb +++ b/lib/shoulda/matchers/active_record/association_matcher.rb @@ -1096,12 +1096,12 @@ module Shoulda self end - def optional + def optional(optional = true) remove_submatcher(AssociationMatchers::RequiredMatcher) add_submatcher( AssociationMatchers::OptionalMatcher, name, - true, + optional, ) self end 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 3ddf2fca..05d30a4c 100644 --- a/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +++ b/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb @@ -368,14 +368,14 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do end end - context 'when qualified with optional' do + context 'when qualified with optional(true)' do if active_record_supports_optional_for_associations? context 'when belongs_to is configured to be required by default' do it 'fails with an appropriate message' do with_belongs_to_as_required_by_default do assertion = lambda do expect(belonging_to_parent). - to belong_to(:parent).optional + to belong_to(:parent).optional(true) end message = format_message(<<-MESSAGE, one_line: true) @@ -394,13 +394,62 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do context 'when belongs_to is not configured to be required by default' do it 'passes' do with_belongs_to_as_optional_by_default do - expect(belonging_to_parent).to belong_to(:parent).optional + expect(belonging_to_parent).to belong_to(:parent).optional(true) end end end else it 'passes' do - expect(belonging_to_parent).to belong_to(:parent).optional + expect(belonging_to_parent).to belong_to(:parent).optional(true) + end + end + end + + context 'when qualified with optional(false)' do + if active_record_supports_optional_for_associations? + context 'when belongs_to is configured to be required by default' do + it 'passes' do + with_belongs_to_as_required_by_default do + expect(belonging_to_parent).to belong_to(:parent).optional(false) + end + end + end + + context 'when belongs_to is not configured to be required by default' do + it 'fails with an appropriate message' do + with_belongs_to_as_optional_by_default do + assertion = lambda do + expect(belonging_to_parent). + to belong_to(:parent).optional(false) + end + + message = format_message(<<-MESSAGE, one_line: true) + Expected Child to have a belongs_to association called parent + (and for the record to fail validation if :parent is + unset; i.e., either the association should have been defined + with `optional: false`, or there should be a presence + validation on :parent) + MESSAGE + + expect(&assertion).to fail_with_message(message) + end + end + end + else + it 'fails with an appropriate message' do + assertion = lambda do + expect(belonging_to_parent). + to belong_to(:parent).optional(false) + end + + message = format_message(<<-MESSAGE, one_line: true) + Expected Child to have a belongs_to association called parent + (and for the record to fail validation if :parent is unset; i.e., + either the association should have been defined with `optional: + false`, or there should be a presence validation on :parent) + MESSAGE + + expect(&assertion).to fail_with_message(message) end end end @@ -538,11 +587,11 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do end end - context 'when qualified with optional' do + context 'when qualified with optional(true)' do it 'fails with an appropriate message' do assertion = lambda do expect(belonging_to_parent(required: true)). - to belong_to(:parent).optional + to belong_to(:parent).optional(true) end message = format_message(<<-MESSAGE, one_line: true) @@ -557,6 +606,13 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do end end + context 'when qualified with optional(false)' do + it 'passes' do + expect(belonging_to_parent(required: true)). + to belong_to(:parent).optional(false) + end + end + context 'when qualified with nothing' do it 'passes' do expect(belonging_to_parent(required: true)).to belong_to(:parent) @@ -591,10 +647,28 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do end end - context 'when qualified with optional' do + context 'when qualified with optional(true)' do it 'passes' do expect(belonging_to_parent(optional: true)). - to belong_to(:parent).optional + to belong_to(:parent).optional(true) + end + end + + context 'when qualified with optional(false)' do + it 'fails with an appropriate message' do + assertion = lambda do + expect(belonging_to_parent(optional: true)). + to belong_to(:parent).optional(false) + end + + message = format_message(<<-MESSAGE, one_line: true) + Expected Child to have a belongs_to association called parent + (and for the record to fail validation if :parent is unset; i.e., + either the association should have been defined with `optional: + false`, or there should be a presence validation on :parent) + MESSAGE + + expect(&assertion).to fail_with_message(message) end end