Association matchers support :autosave option
has_one, has_many, belongs_to, and has_and_belongs_to_many relationships can have an `:autosave` option, which causes the relevant associated records to be automatically saved when their parent is saved. This is based on a PR by @calebthompson, which I've brought up to date with master.
This commit is contained in:
parent
7fa7e67d88
commit
21e984cd28
2
NEWS.md
2
NEWS.md
|
@ -3,6 +3,8 @@
|
||||||
* Association matchers now test that the model being referred to (either
|
* Association matchers now test that the model being referred to (either
|
||||||
implicitly or explicitly, using `:class_name`) actually exists.
|
implicitly or explicitly, using `:class_name`) actually exists.
|
||||||
|
|
||||||
|
* Add ability to test `:autosave` option on associations.
|
||||||
|
|
||||||
# v 2.5.0
|
# v 2.5.0
|
||||||
|
|
||||||
* Fix Rails/Test::Unit integration to ensure that the test case classes we are
|
* Fix Rails/Test::Unit integration to ensure that the test case classes we are
|
||||||
|
|
|
@ -28,6 +28,8 @@ module Shoulda # :nodoc:
|
||||||
# * <tt>dependent</tt> - tests that the association makes use of the
|
# * <tt>dependent</tt> - tests that the association makes use of the
|
||||||
# dependent option.
|
# dependent option.
|
||||||
# * <tt>:class_name</tt> - tests that the association resoves to class_name.
|
# * <tt>:class_name</tt> - tests that the association resoves to class_name.
|
||||||
|
# * <tt>:autosave</tt> - tests that the association makes use of the
|
||||||
|
# autosave option.
|
||||||
# * <tt>:validate</tt> - tests that the association makes use of the validate
|
# * <tt>:validate</tt> - tests that the association makes use of the validate
|
||||||
# option.
|
# option.
|
||||||
#
|
#
|
||||||
|
@ -48,6 +50,8 @@ module Shoulda # :nodoc:
|
||||||
# * <tt>:dependent</tt> - tests that the association makes use of the
|
# * <tt>:dependent</tt> - tests that the association makes use of the
|
||||||
# dependent option.
|
# dependent option.
|
||||||
# * <tt>:class_name</tt> - tests that the association resolves to class_name.
|
# * <tt>:class_name</tt> - tests that the association resolves to class_name.
|
||||||
|
# * <tt>:autosave</tt> - tests that the association makes use of the
|
||||||
|
# autosave option.
|
||||||
# * <tt>:validate</tt> - tests that the association makes use of the validate
|
# * <tt>:validate</tt> - tests that the association makes use of the validate
|
||||||
# option.
|
# option.
|
||||||
#
|
#
|
||||||
|
@ -120,6 +124,11 @@ module Shoulda # :nodoc:
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def autosave(autosave)
|
||||||
|
@options[:autosave] = autosave
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
def class_name(class_name)
|
def class_name(class_name)
|
||||||
@options[:class_name] = class_name
|
@options[:class_name] = class_name
|
||||||
self
|
self
|
||||||
|
@ -163,6 +172,7 @@ module Shoulda # :nodoc:
|
||||||
class_exists? &&
|
class_exists? &&
|
||||||
foreign_key_exists? &&
|
foreign_key_exists? &&
|
||||||
class_name_correct? &&
|
class_name_correct? &&
|
||||||
|
autosave_correct? &&
|
||||||
conditions_correct? &&
|
conditions_correct? &&
|
||||||
join_table_exists? &&
|
join_table_exists? &&
|
||||||
validate_correct? &&
|
validate_correct? &&
|
||||||
|
@ -266,6 +276,19 @@ module Shoulda # :nodoc:
|
||||||
false
|
false
|
||||||
end
|
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?
|
def conditions_correct?
|
||||||
if options.key?(:conditions)
|
if options.key?(:conditions)
|
||||||
if option_verifier.correct_for_relation_clause?(:conditions, options[:conditions])
|
if option_verifier.correct_for_relation_clause?(:conditions, options[:conditions])
|
||||||
|
|
|
@ -116,6 +116,26 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
|
||||||
}.to fail_with_message(message)
|
}.to fail_with_message(message)
|
||||||
end
|
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
|
context 'an association with a :validate option' do
|
||||||
[false, true].each do |validate_value|
|
[false, true].each do |validate_value|
|
||||||
context "when the model has validate: #{validate_value}" do
|
context "when the model has validate: #{validate_value}" do
|
||||||
|
@ -380,6 +400,26 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
|
||||||
}.to fail_with_message(message)
|
}.to fail_with_message(message)
|
||||||
end
|
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
|
context 'validate' do
|
||||||
it 'accepts when the :validate option matches' do
|
it 'accepts when the :validate option matches' do
|
||||||
expect(having_many_children(validate: false)).to have_many(:children).validate(false)
|
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')
|
expect(having_one_detail).to have_one(:detail).class_name('Detail')
|
||||||
end
|
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
|
it 'accepts an association with a valid :class_name option' do
|
||||||
define_model :person_detail, person_id: :integer
|
define_model :person_detail, person_id: :integer
|
||||||
define_model :person do
|
define_model :person do
|
||||||
|
@ -712,6 +772,30 @@ describe Shoulda::Matchers::ActiveRecord::AssociationMatcher do
|
||||||
}.to fail_with_message(message)
|
}.to fail_with_message(message)
|
||||||
end
|
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
|
context 'validate' do
|
||||||
it 'accepts when the :validate option matches' do
|
it 'accepts when the :validate option matches' do
|
||||||
expect(having_and_belonging_to_many_relatives(validate: false)).
|
expect(having_and_belonging_to_many_relatives(validate: false)).
|
||||||
|
|
Loading…
Reference in New Issue