aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/autosave_association_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases/autosave_association_test.rb')
-rw-r--r--activerecord/test/cases/autosave_association_test.rb166
1 files changed, 141 insertions, 25 deletions
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index fe5de44409..71c34d816a 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -1,8 +1,10 @@
require 'cases/helper'
require 'models/bird'
+require 'models/comment'
require 'models/company'
require 'models/customer'
require 'models/developer'
+require 'models/computer'
require 'models/invoice'
require 'models/line_item'
require 'models/order'
@@ -17,8 +19,38 @@ require 'models/tag'
require 'models/tagging'
require 'models/treasure'
require 'models/eye'
+require 'models/electron'
+require 'models/molecule'
+require 'models/member'
+require 'models/member_detail'
+require 'models/organization'
class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
+ def test_autosave_validation
+ person = Class.new(ActiveRecord::Base) {
+ self.table_name = 'people'
+ validate :should_be_cool, :on => :create
+ def self.name; 'Person'; end
+
+ private
+
+ def should_be_cool
+ unless self.first_name == 'cool'
+ errors.add :first_name, "not cool"
+ end
+ end
+ }
+ reference = Class.new(ActiveRecord::Base) {
+ self.table_name = "references"
+ def self.name; 'Reference'; end
+ belongs_to :person, autosave: true, class: person
+ }
+
+ u = person.create!(first_name: 'cool')
+ u.update_attributes!(first_name: 'nah') # still valid because validation only applies on 'create'
+ assert reference.create!(person: u).persisted?
+ end
+
def test_should_not_add_the_same_callbacks_multiple_times_for_has_one
assert_no_difference_when_adding_callbacks_twice_for Pirate, :ship
end
@@ -37,10 +69,6 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
private
- def base
- ActiveRecord::Base
- end
-
def assert_no_difference_when_adding_callbacks_twice_for(model, association_name)
reflection = model.reflect_on_association(association_name)
assert_no_difference "callbacks_for_model(#{model.name}).length" do
@@ -49,9 +77,9 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
end
def callbacks_for_model(model)
- model.instance_variables.grep(/_callbacks$/).map do |ivar|
+ model.instance_variables.grep(/_callbacks$/).flat_map do |ivar|
model.instance_variable_get(ivar)
- end.flatten
+ end
end
end
@@ -343,6 +371,33 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
end
end
+class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttributes < ActiveRecord::TestCase
+ def test_invalid_adding_with_nested_attributes
+ molecule = Molecule.new
+ valid_electron = Electron.new(name: 'electron')
+ invalid_electron = Electron.new
+
+ molecule.electrons = [valid_electron, invalid_electron]
+ molecule.save
+
+ assert_not invalid_electron.valid?
+ assert valid_electron.valid?
+ assert_not molecule.persisted?, 'Molecule should not be persisted when its electrons are invalid'
+ end
+
+ def test_valid_adding_with_nested_attributes
+ molecule = Molecule.new
+ valid_electron = Electron.new(name: 'electron')
+
+ molecule.electrons = [valid_electron]
+ molecule.save
+
+ assert valid_electron.valid?
+ assert molecule.persisted?
+ assert_equal 1, molecule.electrons.count
+ end
+end
+
class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCase
fixtures :companies, :people
@@ -401,7 +456,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
assert_equal new_client, companies(:first_firm).clients_of_firm.last
assert !companies(:first_firm).save
assert !new_client.persisted?
- assert_equal 1, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 2, companies(:first_firm).clients_of_firm(true).size
end
def test_adding_before_save
@@ -449,38 +504,38 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
def test_build_before_save
company = companies(:first_firm)
- new_client = assert_no_queries { company.clients_of_firm.build("name" => "Another Client") }
+ new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build("name" => "Another Client") }
assert !company.clients_of_firm.loaded?
company.name += '-changed'
assert_queries(2) { assert company.save }
assert new_client.persisted?
- assert_equal 2, company.clients_of_firm(true).size
+ assert_equal 3, company.clients_of_firm(true).size
end
def test_build_many_before_save
company = companies(:first_firm)
- assert_no_queries { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
+ assert_no_queries(ignore_none: false) { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
company.name += '-changed'
assert_queries(3) { assert company.save }
- assert_equal 3, company.clients_of_firm(true).size
+ assert_equal 4, company.clients_of_firm(true).size
end
def test_build_via_block_before_save
company = companies(:first_firm)
- new_client = assert_no_queries { company.clients_of_firm.build {|client| client.name = "Another Client" } }
+ new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build {|client| client.name = "Another Client" } }
assert !company.clients_of_firm.loaded?
company.name += '-changed'
assert_queries(2) { assert company.save }
assert new_client.persisted?
- assert_equal 2, company.clients_of_firm(true).size
+ assert_equal 3, company.clients_of_firm(true).size
end
def test_build_many_via_block_before_save
company = companies(:first_firm)
- assert_no_queries do
+ assert_no_queries(ignore_none: false) do
company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) do |client|
client.name = "changed"
end
@@ -488,7 +543,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
company.name += '-changed'
assert_queries(3) { assert company.save }
- assert_equal 3, company.clients_of_firm(true).size
+ assert_equal 4, company.clients_of_firm(true).size
end
def test_replace_on_new_object
@@ -563,20 +618,28 @@ class TestDefaultAutosaveAssociationOnNewRecord < ActiveRecord::TestCase
firm.save!
assert !account.persisted?
end
+
+ def test_autosave_new_record_with_after_create_callback
+ post = PostWithAfterCreateCallback.new(title: 'Captain Murphy', body: 'is back')
+ post.comments.build(body: 'foo')
+ post.save!
+
+ assert_not_nil post.author_id
+ end
end
class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
self.use_transactional_fixtures = false
- def setup
- super
+ setup do
@pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?")
@ship = @pirate.create_ship(:name => 'Nights Dirty Lightning')
end
- def teardown
+ teardown do
# We are running without transactional fixtures and need to cleanup.
Bird.delete_all
+ Parrot.delete_all
@ship.delete
@pirate.delete
end
@@ -633,10 +696,23 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
end
end
+ @ship.pirate.catchphrase = "Changed Catchphrase"
+
assert_raise(RuntimeError) { assert !@pirate.save }
assert_not_nil @pirate.reload.ship
end
+ def test_should_save_changed_has_one_changed_object_if_child_is_saved
+ @pirate.ship.name = "NewName"
+ assert @pirate.save
+ assert_equal "NewName", @pirate.ship.reload.name
+ end
+
+ def test_should_not_save_changed_has_one_unchanged_object_if_child_is_saved
+ @pirate.ship.expects(:save).never
+ assert @pirate.save
+ end
+
# belongs_to
def test_should_destroy_a_parent_association_as_part_of_the_save_transaction_if_it_was_marked_for_destroyal
assert !@ship.pirate.marked_for_destruction?
@@ -1053,6 +1129,27 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
end
end
+class TestAutosaveAssociationOnAHasOneThroughAssociation < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false unless supports_savepoints?
+
+ def setup
+ super
+ organization = Organization.create
+ @member = Member.create
+ MemberDetail.create(organization: organization, member: @member)
+ end
+
+ def test_should_not_has_one_through_model
+ class << @member.organization
+ def save(*args)
+ super
+ raise 'Oh noes!'
+ end
+ end
+ assert_nothing_raised { @member.save }
+ end
+end
+
class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
self.use_transactional_fixtures = false unless supports_savepoints?
@@ -1183,15 +1280,15 @@ module AutosaveAssociationOnACollectionAssociationTests
end
def test_should_default_invalid_error_from_i18n
- I18n.backend.store_translations(:en, :activerecord => {:errors => { :models =>
- { @association_name.to_s.singularize.to_sym => { :blank => "cannot be blank" } }
+ I18n.backend.store_translations(:en, activerecord: {errors: { models:
+ { @associated_model_name.to_s.to_sym => { blank: "cannot be blank" } }
}})
- @pirate.send(@association_name).build(:name => '')
+ @pirate.send(@association_name).build(name: '')
assert !@pirate.valid?
assert_equal ["cannot be blank"], @pirate.errors["#{@association_name}.name"]
- assert_equal ["#{@association_name.to_s.titleize} name cannot be blank"], @pirate.errors.full_messages
+ assert_equal ["#{@association_name.to_s.humanize} name cannot be blank"], @pirate.errors.full_messages
assert @pirate.errors[@association_name].empty?
ensure
I18n.backend = I18n::Backend::Simple.new
@@ -1307,6 +1404,7 @@ class TestAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCase
def setup
super
@association_name = :birds
+ @associated_model_name = :bird
@pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?")
@child_1 = @pirate.birds.create(:name => 'Posideons Killer')
@@ -1321,12 +1419,30 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::T
def setup
super
+ @association_name = :autosaved_parrots
+ @associated_model_name = :parrot
+ @habtm = true
+
+ @pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
+ @child_1 = @pirate.parrots.create(name: 'Posideons Killer')
+ @child_2 = @pirate.parrots.create(name: 'Killer bandita Dionne')
+ end
+
+ include AutosaveAssociationOnACollectionAssociationTests
+end
+
+class TestAutosaveAssociationOnAHasAndBelongsToManyAssociationWithAcceptsNestedAttributes < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false unless supports_savepoints?
+
+ def setup
+ super
@association_name = :parrots
+ @associated_model_name = :parrot
@habtm = true
- @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?")
- @child_1 = @pirate.parrots.create(:name => 'Posideons Killer')
- @child_2 = @pirate.parrots.create(:name => 'Killer bandita Dionne')
+ @pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
+ @child_1 = @pirate.parrots.create(name: 'Posideons Killer')
+ @child_2 = @pirate.parrots.create(name: 'Killer bandita Dionne')
end
include AutosaveAssociationOnACollectionAssociationTests