diff --git a/NEWS.md b/NEWS.md
index b8b9f96a..cf554860 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -3,6 +3,8 @@
* Association matchers now test that the model being referred to (either
implicitly or explicitly, using `:class_name`) actually exists.
+* Add ability to test `:autosave` option on associations.
+
# v 2.5.0
* Fix Rails/Test::Unit integration to ensure that the test case classes we are
diff --git a/lib/shoulda/matchers/active_record/association_matcher.rb b/lib/shoulda/matchers/active_record/association_matcher.rb
index 94ad6963..39235cae 100644
--- a/lib/shoulda/matchers/active_record/association_matcher.rb
+++ b/lib/shoulda/matchers/active_record/association_matcher.rb
@@ -28,6 +28,8 @@ module Shoulda # :nodoc:
# * dependent - tests that the association makes use of the
# dependent option.
# * :class_name - tests that the association resoves to class_name.
+ # * :autosave - tests that the association makes use of the
+ # autosave option.
# * :validate - tests that the association makes use of the validate
# option.
#
@@ -48,6 +50,8 @@ module Shoulda # :nodoc:
# * :dependent - tests that the association makes use of the
# dependent option.
# * :class_name - tests that the association resolves to class_name.
+ # * :autosave - tests that the association makes use of the
+ # autosave option.
# * :validate - tests that the association makes use of the validate
# option.
#
@@ -120,6 +124,11 @@ module Shoulda # :nodoc:
self
end
+ def autosave(autosave)
+ @options[:autosave] = autosave
+ self
+ end
+
def class_name(class_name)
@options[:class_name] = class_name
self
@@ -163,6 +172,7 @@ module Shoulda # :nodoc:
class_exists? &&
foreign_key_exists? &&
class_name_correct? &&
+ autosave_correct? &&
conditions_correct? &&
join_table_exists? &&
validate_correct? &&
@@ -266,6 +276,19 @@ module Shoulda # :nodoc:
false
end
+ def autosave_correct?
+ if options.key?(:autosave)
+ if option_verifier.correct_for_boolean?(:autosave, options[:autosave])
+ true
+ else
+ @missing = "#{name} should have autosave set to #{options[:autosave]}"
+ 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/shoulda/matchers/active_record/association_matcher_spec.rb b/spec/shoulda/matchers/active_record/association_matcher_spec.rb
index bc89187c..253b9a19 100644
--- a/spec/shoulda/matchers/active_record/association_matcher_spec.rb
+++ b/spec/shoulda/matchers/active_record/association_matcher_spec.rb
@@ -116,6 +116,26 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
}.to fail_with_message(message)
end
+ it 'accepts an association with a matching :autosave option' do
+ define_model :parent, :adopter => :boolean
+ define_model :child, :parent_id => :integer do
+ belongs_to :parent, :autosave => true
+ end
+ expect(Child.new).to belong_to(:parent).autosave(true)
+ end
+
+ it 'rejects an association with a non-matching :autosave option with the correct message' do
+ define_model :parent, :adopter => :boolean
+ define_model :child, :parent_id => :integer do
+ belongs_to :parent, :autosave => false
+ end
+
+ message = 'Expected Child to have a belongs_to association called parent (parent should have autosave set to true)'
+ expect {
+ expect(Child.new).to belong_to(:parent).autosave(true)
+ }.to fail_with_message(message)
+ end
+
context 'an association with a :validate option' do
[false, true].each do |validate_value|
context "when the model has validate: #{validate_value}" do
@@ -380,6 +400,26 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
}.to fail_with_message(message)
end
+ it 'accepts an association with a matching :autosave option' do
+ define_model :child, :parent_id => :integer
+ define_model :parent do
+ has_many :children, :autosave => true
+ end
+ expect(Parent.new).to have_many(:children).autosave(true)
+ end
+
+ it 'rejects an association with a non-matching :autosave option with the correct message' do
+ define_model :child, :parent_id => :integer
+ define_model :parent do
+ has_many :children, :autosave => false
+ end
+
+ message = 'Expected Parent to have a has_many association called children (children should have autosave set to true)'
+ expect {
+ expect(Parent.new).to have_many(:children).autosave(true)
+ }.to fail_with_message(message)
+ end
+
context 'validate' do
it 'accepts when the :validate option matches' do
expect(having_many_children(validate: false)).to have_many(:children).validate(false)
@@ -530,6 +570,26 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
expect(having_one_detail).to have_one(:detail).class_name('Detail')
end
+ it 'accepts an association with a matching :autosave option' do
+ define_model :detail, :person_id => :integer, :disabled => :boolean
+ define_model :person do
+ has_one :detail, :autosave => true
+ end
+ expect(Person.new).to have_one(:detail).autosave(true)
+ end
+
+ it 'rejects an association with a non-matching :autosave option with the correct message' do
+ define_model :detail, :person_id => :integer, :disabled => :boolean
+ define_model :person do
+ has_one :detail, :autosave => false
+ end
+
+ message = 'Expected Person to have a has_one association called detail (detail should have autosave set to true)'
+ expect {
+ expect(Person.new).to have_one(:detail).autosave(true)
+ }.to fail_with_message(message)
+ end
+
it 'accepts an association with a valid :class_name option' do
define_model :person_detail, person_id: :integer
define_model :person do
@@ -712,6 +772,30 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
}.to fail_with_message(message)
end
+ it 'accepts an association with a matching :autosave option' do
+ define_model :relatives, :adopted => :boolean
+ define_model :person do
+ has_and_belongs_to_many :relatives, :autosave => true
+ end
+ define_model :people_relative, :person_id => :integer,
+ :relative_id => :integer
+ expect(Person.new).to have_and_belong_to_many(:relatives).autosave(true)
+ end
+
+ it 'rejects an association with a non-matching :autosave option with the correct message' do
+ define_model :relatives, :adopted => :boolean
+ define_model :person do
+ has_and_belongs_to_many :relatives
+ end
+ define_model :people_relative, :person_id => :integer,
+ :relative_id => :integer
+
+ message = 'Expected Person to have a has_and_belongs_to_many association called relatives (relatives should have autosave set to true)'
+ expect {
+ expect(Person.new).to have_and_belong_to_many(:relatives).autosave(true)
+ }.to fail_with_message(message)
+ end
+
context 'validate' do
it 'accepts when the :validate option matches' do
expect(having_and_belonging_to_many_relatives(validate: false)).