Rails 2.3.5
Upgrade to Rails 2.3.5. Also work around this bug: https://rails.lighthouseapp.com/projects/8994/tickets/3524 created by the aforementioned Rails release.
This commit is contained in:
parent
a6429f8c22
commit
e3832c6f79
187 changed files with 2316 additions and 891 deletions
|
@ -651,6 +651,18 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
|
|||
assert_equal 1, Client.find_all_by_client_of(firm.id).size
|
||||
end
|
||||
|
||||
def test_delete_all_association_with_primary_key_deletes_correct_records
|
||||
firm = Firm.find(:first)
|
||||
# break the vanilla firm_id foreign key
|
||||
assert_equal 2, firm.clients.count
|
||||
firm.clients.first.update_attribute(:firm_id, nil)
|
||||
assert_equal 1, firm.clients(true).count
|
||||
assert_equal 1, firm.clients_using_primary_key_with_delete_all.count
|
||||
old_record = firm.clients_using_primary_key_with_delete_all.first
|
||||
firm = Firm.find(:first)
|
||||
firm.destroy
|
||||
assert Client.find_by_id(old_record.id).nil?
|
||||
end
|
||||
|
||||
def test_creation_respects_hash_condition
|
||||
ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
|
||||
|
|
|
@ -132,6 +132,28 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
|||
assert !posts(:welcome).reload.people(true).include?(people(:michael))
|
||||
end
|
||||
|
||||
def test_replace_order_is_preserved
|
||||
posts(:welcome).people.clear
|
||||
posts(:welcome).people = [people(:david), people(:michael)]
|
||||
assert_equal [people(:david).id, people(:michael).id], posts(:welcome).readers.all(:order => 'id').map(&:person_id)
|
||||
|
||||
# Test the inverse order in case the first success was a coincidence
|
||||
posts(:welcome).people.clear
|
||||
posts(:welcome).people = [people(:michael), people(:david)]
|
||||
assert_equal [people(:michael).id, people(:david).id], posts(:welcome).readers.all(:order => 'id').map(&:person_id)
|
||||
end
|
||||
|
||||
def test_replace_by_id_order_is_preserved
|
||||
posts(:welcome).people.clear
|
||||
posts(:welcome).person_ids = [people(:david).id, people(:michael).id]
|
||||
assert_equal [people(:david).id, people(:michael).id], posts(:welcome).readers.all(:order => 'id').map(&:person_id)
|
||||
|
||||
# Test the inverse order in case the first success was a coincidence
|
||||
posts(:welcome).people.clear
|
||||
posts(:welcome).person_ids = [people(:michael).id, people(:david).id]
|
||||
assert_equal [people(:michael).id, people(:david).id], posts(:welcome).readers.all(:order => 'id').map(&:person_id)
|
||||
end
|
||||
|
||||
def test_associate_with_create
|
||||
assert_queries(1) { posts(:thinking) }
|
||||
|
||||
|
|
|
@ -36,6 +36,15 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
|
|||
assert_equal accounts(:rails_core_account), firm.account_using_primary_key
|
||||
end
|
||||
|
||||
def test_update_with_foreign_and_primary_keys
|
||||
firm = companies(:first_firm)
|
||||
account = firm.account_using_foreign_and_primary_keys
|
||||
assert_equal Account.find_by_firm_name(firm.name), account
|
||||
firm.save
|
||||
firm.reload
|
||||
assert_equal account, firm.account_using_foreign_and_primary_keys
|
||||
end
|
||||
|
||||
def test_can_marshal_has_one_association_with_nil_target
|
||||
firm = Firm.new
|
||||
assert_nothing_raised do
|
||||
|
@ -306,4 +315,16 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
|
|||
Firm.find(@firm.id, :include => :account).save!
|
||||
end
|
||||
end
|
||||
|
||||
def test_build_respects_hash_condition
|
||||
account = companies(:first_firm).build_account_limit_500_with_hash_conditions
|
||||
assert account.save
|
||||
assert_equal 500, account.credit_limit
|
||||
end
|
||||
|
||||
def test_create_respects_hash_condition
|
||||
account = companies(:first_firm).create_account_limit_500_with_hash_conditions
|
||||
assert !account.new_record?
|
||||
assert_equal 500, account.credit_limit
|
||||
end
|
||||
end
|
||||
|
|
|
@ -436,6 +436,70 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
|
|||
end
|
||||
end
|
||||
|
||||
class TestDefaultAutosaveAssociationOnNewRecord < ActiveRecord::TestCase
|
||||
def test_autosave_new_record_on_belongs_to_can_be_disabled_per_relationship
|
||||
new_account = Account.new("credit_limit" => 1000)
|
||||
new_firm = Firm.new("name" => "some firm")
|
||||
|
||||
assert new_firm.new_record?
|
||||
new_account.firm = new_firm
|
||||
new_account.save!
|
||||
|
||||
assert !new_firm.new_record?
|
||||
|
||||
new_account = Account.new("credit_limit" => 1000)
|
||||
new_autosaved_firm = Firm.new("name" => "some firm")
|
||||
|
||||
assert new_autosaved_firm.new_record?
|
||||
new_account.unautosaved_firm = new_autosaved_firm
|
||||
new_account.save!
|
||||
|
||||
assert new_autosaved_firm.new_record?
|
||||
end
|
||||
|
||||
def test_autosave_new_record_on_has_one_can_be_disabled_per_relationship
|
||||
firm = Firm.new("name" => "some firm")
|
||||
account = Account.new("credit_limit" => 1000)
|
||||
|
||||
assert account.new_record?
|
||||
firm.account = account
|
||||
firm.save!
|
||||
|
||||
assert !account.new_record?
|
||||
|
||||
firm = Firm.new("name" => "some firm")
|
||||
account = Account.new("credit_limit" => 1000)
|
||||
|
||||
firm.unautosaved_account = account
|
||||
|
||||
assert account.new_record?
|
||||
firm.unautosaved_account = account
|
||||
firm.save!
|
||||
|
||||
assert account.new_record?
|
||||
end
|
||||
|
||||
def test_autosave_new_record_on_has_many_can_be_disabled_per_relationship
|
||||
firm = Firm.new("name" => "some firm")
|
||||
account = Account.new("credit_limit" => 1000)
|
||||
|
||||
assert account.new_record?
|
||||
firm.accounts << account
|
||||
|
||||
firm.save!
|
||||
assert !account.new_record?
|
||||
|
||||
firm = Firm.new("name" => "some firm")
|
||||
account = Account.new("credit_limit" => 1000)
|
||||
|
||||
assert account.new_record?
|
||||
firm.unautosaved_accounts << account
|
||||
|
||||
firm.save!
|
||||
assert account.new_record?
|
||||
end
|
||||
end
|
||||
|
||||
class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
|
@ -473,9 +537,17 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|||
assert !@pirate.valid?
|
||||
|
||||
@pirate.ship.mark_for_destruction
|
||||
@pirate.ship.expects(:valid?).never
|
||||
assert_difference('Ship.count', -1) { @pirate.save! }
|
||||
end
|
||||
|
||||
def test_a_child_marked_for_destruction_should_not_be_destroyed_twice
|
||||
@pirate.ship.mark_for_destruction
|
||||
assert @pirate.save
|
||||
@pirate.ship.expects(:destroy).never
|
||||
assert @pirate.save
|
||||
end
|
||||
|
||||
def test_should_rollback_destructions_if_an_exception_occurred_while_saving_a_child
|
||||
# Stub the save method of the @pirate.ship instance to destroy and then raise an exception
|
||||
class << @pirate.ship
|
||||
|
@ -510,9 +582,17 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|||
assert !@ship.valid?
|
||||
|
||||
@ship.pirate.mark_for_destruction
|
||||
@ship.pirate.expects(:valid?).never
|
||||
assert_difference('Pirate.count', -1) { @ship.save! }
|
||||
end
|
||||
|
||||
def test_a_parent_marked_for_destruction_should_not_be_destroyed_twice
|
||||
@ship.pirate.mark_for_destruction
|
||||
assert @ship.save
|
||||
@ship.pirate.expects(:destroy).never
|
||||
assert @ship.save
|
||||
end
|
||||
|
||||
def test_should_rollback_destructions_if_an_exception_occurred_while_saving_a_parent
|
||||
# Stub the save method of the @ship.pirate instance to destroy and then raise an exception
|
||||
class << @ship.pirate
|
||||
|
@ -553,9 +633,33 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
|
|||
children.each { |child| child.name = '' }
|
||||
assert !@pirate.valid?
|
||||
|
||||
children.each { |child| child.mark_for_destruction }
|
||||
children.each do |child|
|
||||
child.mark_for_destruction
|
||||
child.expects(:valid?).never
|
||||
end
|
||||
assert_difference("#{association_name.classify}.count", -2) { @pirate.save! }
|
||||
end
|
||||
|
||||
define_method("test_should_skip_validation_on_the_#{association_name}_association_if_destroyed") do
|
||||
@pirate.send(association_name).create!(:name => "#{association_name}_1")
|
||||
children = @pirate.send(association_name)
|
||||
|
||||
children.each { |child| child.name = '' }
|
||||
assert !@pirate.valid?
|
||||
|
||||
children.each { |child| child.destroy }
|
||||
assert @pirate.valid?
|
||||
end
|
||||
|
||||
define_method("test_a_child_marked_for_destruction_should_not_be_destroyed_twice_while_saving_#{association_name}") do
|
||||
@pirate.send(association_name).create!(:name => "#{association_name}_1")
|
||||
children = @pirate.send(association_name)
|
||||
|
||||
children.each { |child| child.mark_for_destruction }
|
||||
assert @pirate.save
|
||||
children.each { |child| child.expects(:destroy).never }
|
||||
assert @pirate.save
|
||||
end
|
||||
|
||||
define_method("test_should_rollback_destructions_if_an_exception_occurred_while_saving_#{association_name}") do
|
||||
2.times { |i| @pirate.send(association_name).create!(:name => "#{association_name}_#{i}") }
|
||||
|
@ -646,15 +750,15 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
|
|||
def test_should_automatically_validate_the_associated_model
|
||||
@pirate.ship.name = ''
|
||||
assert !@pirate.valid?
|
||||
assert !@pirate.errors.on(:ship_name).blank?
|
||||
assert_equal "can't be blank", @pirate.errors.on(:"ship.name")
|
||||
end
|
||||
|
||||
def test_should_merge_errors_on_the_associated_models_onto_the_parent_even_if_it_is_not_valid
|
||||
@pirate.ship.name = nil
|
||||
@pirate.catchphrase = nil
|
||||
assert !@pirate.valid?
|
||||
assert !@pirate.errors.on(:ship_name).blank?
|
||||
assert !@pirate.errors.on(:catchphrase).blank?
|
||||
assert @pirate.errors.full_messages.include?("Name can't be blank")
|
||||
assert @pirate.errors.full_messages.include?("Catchphrase can't be blank")
|
||||
end
|
||||
|
||||
def test_should_still_allow_to_bypass_validations_on_the_associated_model
|
||||
|
@ -736,15 +840,15 @@ class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
|
|||
def test_should_automatically_validate_the_associated_model
|
||||
@ship.pirate.catchphrase = ''
|
||||
assert !@ship.valid?
|
||||
assert !@ship.errors.on(:pirate_catchphrase).blank?
|
||||
assert_equal "can't be blank", @ship.errors.on(:"pirate.catchphrase")
|
||||
end
|
||||
|
||||
def test_should_merge_errors_on_the_associated_model_onto_the_parent_even_if_it_is_not_valid
|
||||
@ship.name = nil
|
||||
@ship.pirate.catchphrase = nil
|
||||
assert !@ship.valid?
|
||||
assert !@ship.errors.on(:name).blank?
|
||||
assert !@ship.errors.on(:pirate_catchphrase).blank?
|
||||
assert @ship.errors.full_messages.include?("Name can't be blank")
|
||||
assert @ship.errors.full_messages.include?("Catchphrase can't be blank")
|
||||
end
|
||||
|
||||
def test_should_still_allow_to_bypass_validations_on_the_associated_model
|
||||
|
@ -806,7 +910,7 @@ module AutosaveAssociationOnACollectionAssociationTests
|
|||
@pirate.send(@association_name).each { |child| child.name = '' }
|
||||
|
||||
assert !@pirate.valid?
|
||||
assert_equal "can't be blank", @pirate.errors.on("#{@association_name}_name")
|
||||
assert @pirate.errors.full_messages.include?("Name can't be blank")
|
||||
assert @pirate.errors.on(@association_name).blank?
|
||||
end
|
||||
|
||||
|
@ -814,7 +918,7 @@ module AutosaveAssociationOnACollectionAssociationTests
|
|||
@pirate.send(@association_name).build(:name => '')
|
||||
|
||||
assert !@pirate.valid?
|
||||
assert_equal "can't be blank", @pirate.errors.on("#{@association_name}_name")
|
||||
assert_equal "can't be blank", @pirate.errors.on("#{@association_name}.name")
|
||||
assert @pirate.errors.on(@association_name).blank?
|
||||
end
|
||||
|
||||
|
@ -823,7 +927,7 @@ module AutosaveAssociationOnACollectionAssociationTests
|
|||
@pirate.catchphrase = nil
|
||||
|
||||
assert !@pirate.valid?
|
||||
assert_equal "can't be blank", @pirate.errors.on("#{@association_name}_name")
|
||||
assert_equal "can't be blank", @pirate.errors.on("#{@association_name}.name")
|
||||
assert !@pirate.errors.on(:catchphrase).blank?
|
||||
end
|
||||
|
||||
|
@ -920,4 +1024,119 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::T
|
|||
end
|
||||
|
||||
include AutosaveAssociationOnACollectionAssociationTests
|
||||
end
|
||||
end
|
||||
|
||||
class TestAutosaveAssociationValidationsOnAHasManyAssocication < ActiveRecord::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
@pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?")
|
||||
@pirate.birds.create(:name => 'cookoo')
|
||||
end
|
||||
|
||||
test "should automatically validate associations" do
|
||||
assert @pirate.valid?
|
||||
@pirate.birds.each { |bird| bird.name = '' }
|
||||
|
||||
assert !@pirate.valid?
|
||||
end
|
||||
end
|
||||
|
||||
class TestAutosaveAssociationValidationsOnAHasOneAssocication < ActiveRecord::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
@pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?")
|
||||
@pirate.create_ship(:name => 'titanic')
|
||||
end
|
||||
|
||||
test "should automatically validate associations with :validate => true" do
|
||||
assert @pirate.valid?
|
||||
@pirate.ship.name = ''
|
||||
assert !@pirate.valid?
|
||||
end
|
||||
|
||||
test "should not automatically validate associations without :validate => true" do
|
||||
assert @pirate.valid?
|
||||
@pirate.non_validated_ship.name = ''
|
||||
assert @pirate.valid?
|
||||
end
|
||||
end
|
||||
|
||||
class TestAutosaveAssociationValidationsOnABelongsToAssocication < ActiveRecord::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
@pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?")
|
||||
end
|
||||
|
||||
test "should automatically validate associations with :validate => true" do
|
||||
assert @pirate.valid?
|
||||
@pirate.parrot = Parrot.new(:name => '')
|
||||
assert !@pirate.valid?
|
||||
end
|
||||
|
||||
test "should not automatically validate associations without :validate => true" do
|
||||
assert @pirate.valid?
|
||||
@pirate.non_validated_parrot = Parrot.new(:name => '')
|
||||
assert @pirate.valid?
|
||||
end
|
||||
end
|
||||
|
||||
class TestAutosaveAssociationValidationsOnAHABTMAssocication < ActiveRecord::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
@pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?")
|
||||
end
|
||||
|
||||
test "should automatically validate associations with :validate => true" do
|
||||
assert @pirate.valid?
|
||||
@pirate.parrots = [ Parrot.new(:name => 'popuga') ]
|
||||
@pirate.parrots.each { |parrot| parrot.name = '' }
|
||||
assert !@pirate.valid?
|
||||
end
|
||||
|
||||
test "should not automatically validate associations without :validate => true" do
|
||||
assert @pirate.valid?
|
||||
@pirate.non_validated_parrots = [ Parrot.new(:name => 'popuga') ]
|
||||
@pirate.non_validated_parrots.each { |parrot| parrot.name = '' }
|
||||
assert @pirate.valid?
|
||||
end
|
||||
end
|
||||
|
||||
class TestAutosaveAssociationValidationMethodsGeneration < ActiveRecord::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
def setup
|
||||
@pirate = Pirate.new
|
||||
end
|
||||
|
||||
test "should generate validation methods for has_many associations" do
|
||||
assert @pirate.respond_to?(:validate_associated_records_for_birds)
|
||||
end
|
||||
|
||||
test "should generate validation methods for has_one associations with :validate => true" do
|
||||
assert @pirate.respond_to?(:validate_associated_records_for_ship)
|
||||
end
|
||||
|
||||
test "should not generate validation methods for has_one associations without :validate => true" do
|
||||
assert !@pirate.respond_to?(:validate_associated_records_for_non_validated_ship)
|
||||
end
|
||||
|
||||
test "should generate validation methods for belongs_to associations with :validate => true" do
|
||||
assert @pirate.respond_to?(:validate_associated_records_for_parrot)
|
||||
end
|
||||
|
||||
test "should not generate validation methods for belongs_to associations without :validate => true" do
|
||||
assert !@pirate.respond_to?(:validate_associated_records_for_non_validated_parrot)
|
||||
end
|
||||
|
||||
test "should generate validation methods for HABTM associations with :validate => true" do
|
||||
assert @pirate.respond_to?(:validate_associated_records_for_parrots)
|
||||
end
|
||||
|
||||
test "should not generate validation methods for HABTM associations without :validate => true" do
|
||||
assert !@pirate.respond_to?(:validate_associated_records_for_non_validated_parrots)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -474,6 +474,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|||
topic = Topic.find(1)
|
||||
assert_equal topic, topic.delete, 'topic.delete did not return self'
|
||||
assert topic.frozen?, 'topic not frozen after delete'
|
||||
assert topic.destroyed?, 'topic not marked as being destroyed'
|
||||
assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
|
||||
end
|
||||
|
||||
|
@ -486,6 +487,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|||
topic = Topic.find(1)
|
||||
assert_equal topic, topic.destroy, 'topic.destroy did not return self'
|
||||
assert topic.frozen?, 'topic not frozen after destroy'
|
||||
assert topic.destroyed?, 'topic not marked as being destroyed'
|
||||
assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
|
||||
end
|
||||
|
||||
|
|
|
@ -41,6 +41,14 @@ class MysqlConnectionTest < ActiveRecord::TestCase
|
|||
sleep 2
|
||||
@connection.verify!
|
||||
assert @connection.active?
|
||||
end
|
||||
|
||||
# Test that MySQL allows multiple results for stored procedures
|
||||
if Mysql.const_defined?(:CLIENT_MULTI_RESULTS)
|
||||
def test_multi_results
|
||||
rows = ActiveRecord::Base.connection.select_rows('CALL ten();')
|
||||
assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -519,8 +519,8 @@ class FoxyFixturesTest < ActiveRecord::TestCase
|
|||
end
|
||||
|
||||
def test_identifies_consistently
|
||||
assert_equal 1281023246, Fixtures.identify(:ruby)
|
||||
assert_equal 2140105598, Fixtures.identify(:sapphire_2)
|
||||
assert_equal 207281424, Fixtures.identify(:ruby)
|
||||
assert_equal 1066363776, Fixtures.identify(:sapphire_2)
|
||||
end
|
||||
|
||||
TIMESTAMP_COLUMNS = %w(created_at created_on updated_at updated_on)
|
||||
|
|
|
@ -38,24 +38,6 @@ class OptimisticLockingTest < ActiveRecord::TestCase
|
|||
assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
|
||||
end
|
||||
|
||||
def test_lock_destroy
|
||||
p1 = Person.find(1)
|
||||
p2 = Person.find(1)
|
||||
assert_equal 0, p1.lock_version
|
||||
assert_equal 0, p2.lock_version
|
||||
|
||||
p1.first_name = 'stu'
|
||||
p1.save!
|
||||
assert_equal 1, p1.lock_version
|
||||
assert_equal 0, p2.lock_version
|
||||
|
||||
assert_raises(ActiveRecord::StaleObjectError) { p2.destroy }
|
||||
|
||||
assert p1.destroy
|
||||
assert_equal true, p1.frozen?
|
||||
assert_raises(ActiveRecord::RecordNotFound) { Person.find(1) }
|
||||
end
|
||||
|
||||
def test_lock_repeating
|
||||
p1 = Person.find(1)
|
||||
p2 = Person.find(1)
|
||||
|
|
|
@ -26,13 +26,13 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
|
|||
Pirate.accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
||||
end
|
||||
|
||||
def test_base_should_have_an_empty_reject_new_nested_attributes_procs
|
||||
assert_equal Hash.new, ActiveRecord::Base.reject_new_nested_attributes_procs
|
||||
def test_base_should_have_an_empty_nested_attributes_options
|
||||
assert_equal Hash.new, ActiveRecord::Base.nested_attributes_options
|
||||
end
|
||||
|
||||
def test_should_add_a_proc_to_reject_new_nested_attributes_procs
|
||||
def test_should_add_a_proc_to_nested_attributes_options
|
||||
[:parrots, :birds].each do |name|
|
||||
assert_instance_of Proc, Pirate.reject_new_nested_attributes_procs[name]
|
||||
assert_instance_of Proc, Pirate.nested_attributes_options[name][:reject_if]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -49,24 +49,66 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
|
|||
ship = pirate.create_ship(:name => 'Nights Dirty Lightning')
|
||||
|
||||
assert_no_difference('Ship.count') do
|
||||
pirate.update_attributes(:ship_attributes => { '_delete' => true })
|
||||
pirate.update_attributes(:ship_attributes => { '_destroy' => true })
|
||||
end
|
||||
end
|
||||
|
||||
def test_a_model_should_respond_to_underscore_delete_and_return_if_it_is_marked_for_destruction
|
||||
def test_a_model_should_respond_to_underscore_destroy_and_return_if_it_is_marked_for_destruction
|
||||
ship = Ship.create!(:name => 'Nights Dirty Lightning')
|
||||
assert !ship._delete
|
||||
assert !ship._destroy
|
||||
ship.mark_for_destruction
|
||||
assert ship._delete
|
||||
assert ship._destroy
|
||||
end
|
||||
|
||||
def test_underscore_delete_is_deprecated
|
||||
ActiveSupport::Deprecation.expects(:warn)
|
||||
ship = Ship.create!(:name => 'Nights Dirty Lightning')
|
||||
ship._delete
|
||||
end
|
||||
|
||||
def test_reject_if_method_without_arguments
|
||||
Pirate.accepts_nested_attributes_for :ship, :reject_if => :new_record?
|
||||
|
||||
pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
|
||||
pirate.ship_attributes = { :name => 'Black Pearl' }
|
||||
assert_no_difference('Ship.count') { pirate.save! }
|
||||
end
|
||||
|
||||
def test_reject_if_method_with_arguments
|
||||
Pirate.accepts_nested_attributes_for :ship, :reject_if => :reject_empty_ships_on_create
|
||||
|
||||
pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
|
||||
pirate.ship_attributes = { :name => 'Red Pearl', :_reject_me_if_new => true }
|
||||
assert_no_difference('Ship.count') { pirate.save! }
|
||||
|
||||
# pirate.reject_empty_ships_on_create returns false for saved records
|
||||
pirate.ship_attributes = { :name => 'Red Pearl', :_reject_me_if_new => true }
|
||||
assert_difference('Ship.count') { pirate.save! }
|
||||
end
|
||||
|
||||
def test_reject_if_with_indifferent_keys
|
||||
Pirate.accepts_nested_attributes_for :ship, :reject_if => proc {|attributes| attributes[:name].blank? }
|
||||
|
||||
pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
|
||||
pirate.ship_attributes = { :name => 'Hello Pearl' }
|
||||
assert_difference('Ship.count') { pirate.save! }
|
||||
end
|
||||
end
|
||||
|
||||
class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
||||
include AssertRaiseWithMessage
|
||||
|
||||
def setup
|
||||
@pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
|
||||
@ship = @pirate.create_ship(:name => 'Nights Dirty Lightning')
|
||||
end
|
||||
|
||||
def test_should_raise_argument_error_if_trying_to_build_polymorphic_belongs_to
|
||||
assert_raise_with_message ArgumentError, "Cannot build association looter. Are you trying to build a polymorphic one-to-one association?" do
|
||||
Treasure.new(:name => 'pearl', :looter_attributes => {:catchphrase => "Arrr"})
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_define_an_attribute_writer_method_for_the_association
|
||||
assert_respond_to @pirate, :ship_attributes=
|
||||
end
|
||||
|
@ -79,9 +121,9 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
|||
assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
|
||||
end
|
||||
|
||||
def test_should_not_build_a_new_record_if_there_is_no_id_and_delete_is_truthy
|
||||
def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy
|
||||
@ship.destroy
|
||||
@pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_delete => '1' }
|
||||
@pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' }
|
||||
|
||||
assert_nil @pirate.ship
|
||||
end
|
||||
|
@ -101,8 +143,8 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
|||
assert_equal 'Nights Dirty Lightning', @ship.name
|
||||
end
|
||||
|
||||
def test_should_not_replace_an_existing_record_if_there_is_no_id_and_delete_is_truthy
|
||||
@pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_delete => '1' }
|
||||
def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy
|
||||
@pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger', :_destroy => '1' }
|
||||
|
||||
assert_equal @ship, @pirate.ship
|
||||
assert_equal 'Nights Dirty Lightning', @pirate.ship.name
|
||||
|
@ -129,29 +171,29 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
|||
assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
|
||||
end
|
||||
|
||||
def test_should_delete_an_existing_record_if_there_is_a_matching_id_and_delete_is_truthy
|
||||
def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy
|
||||
@pirate.ship.destroy
|
||||
[1, '1', true, 'true'].each do |truth|
|
||||
@pirate.reload.create_ship(:name => 'Mister Pablo')
|
||||
assert_difference('Ship.count', -1) do
|
||||
@pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_delete => truth })
|
||||
@pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => truth })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_not_delete_an_existing_record_if_delete_is_not_truthy
|
||||
def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
|
||||
[nil, '0', 0, 'false', false].each do |not_truth|
|
||||
assert_no_difference('Ship.count') do
|
||||
@pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_delete => not_truth })
|
||||
@pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => not_truth })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_not_delete_an_existing_record_if_allow_destroy_is_false
|
||||
def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
|
||||
Pirate.accepts_nested_attributes_for :ship, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? }
|
||||
|
||||
assert_no_difference('Ship.count') do
|
||||
@pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_delete => '1' })
|
||||
@pirate.update_attribute(:ship_attributes, { :id => @pirate.ship.id, :_destroy => '1' })
|
||||
end
|
||||
|
||||
Pirate.accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
||||
|
@ -174,7 +216,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
|
|||
|
||||
def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
|
||||
assert_no_difference('Ship.count') do
|
||||
@pirate.attributes = { :ship_attributes => { :id => @ship.id, :_delete => '1' } }
|
||||
@pirate.attributes = { :ship_attributes => { :id => @ship.id, :_destroy => '1' } }
|
||||
end
|
||||
assert_difference('Ship.count', -1) do
|
||||
@pirate.save
|
||||
|
@ -205,9 +247,9 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
|
|||
assert_equal 'Arr', @ship.pirate.catchphrase
|
||||
end
|
||||
|
||||
def test_should_not_build_a_new_record_if_there_is_no_id_and_delete_is_truthy
|
||||
def test_should_not_build_a_new_record_if_there_is_no_id_and_destroy_is_truthy
|
||||
@pirate.destroy
|
||||
@ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_delete => '1' }
|
||||
@ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_destroy => '1' }
|
||||
|
||||
assert_nil @ship.pirate
|
||||
end
|
||||
|
@ -227,8 +269,8 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
|
|||
assert_equal 'Aye', @pirate.catchphrase
|
||||
end
|
||||
|
||||
def test_should_not_replace_an_existing_record_if_there_is_no_id_and_delete_is_truthy
|
||||
@ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_delete => '1' }
|
||||
def test_should_not_replace_an_existing_record_if_there_is_no_id_and_destroy_is_truthy
|
||||
@ship.reload.pirate_attributes = { :catchphrase => 'Arr', :_destroy => '1' }
|
||||
|
||||
assert_equal @pirate, @ship.pirate
|
||||
assert_equal 'Aye', @ship.pirate.catchphrase
|
||||
|
@ -255,29 +297,29 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
|
|||
assert_equal 'Arr', @ship.pirate.catchphrase
|
||||
end
|
||||
|
||||
def test_should_delete_an_existing_record_if_there_is_a_matching_id_and_delete_is_truthy
|
||||
def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy
|
||||
@ship.pirate.destroy
|
||||
[1, '1', true, 'true'].each do |truth|
|
||||
@ship.reload.create_pirate(:catchphrase => 'Arr')
|
||||
assert_difference('Pirate.count', -1) do
|
||||
@ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_delete => truth })
|
||||
@ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => truth })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_not_delete_an_existing_record_if_delete_is_not_truthy
|
||||
def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
|
||||
[nil, '0', 0, 'false', false].each do |not_truth|
|
||||
assert_no_difference('Pirate.count') do
|
||||
@ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_delete => not_truth })
|
||||
@ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => not_truth })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_not_delete_an_existing_record_if_allow_destroy_is_false
|
||||
def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
|
||||
Ship.accepts_nested_attributes_for :pirate, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? }
|
||||
|
||||
assert_no_difference('Pirate.count') do
|
||||
@ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_delete => '1' })
|
||||
@ship.update_attribute(:pirate_attributes, { :id => @ship.pirate.id, :_destroy => '1' })
|
||||
end
|
||||
|
||||
Ship.accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
||||
|
@ -293,7 +335,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
|
|||
|
||||
def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
|
||||
assert_no_difference('Pirate.count') do
|
||||
@ship.attributes = { :pirate_attributes => { :id => @ship.pirate.id, '_delete' => true } }
|
||||
@ship.attributes = { :pirate_attributes => { :id => @ship.pirate.id, '_destroy' => true } }
|
||||
end
|
||||
assert_difference('Pirate.count', -1) { @ship.save }
|
||||
end
|
||||
|
@ -361,18 +403,18 @@ module NestedAttributesOnACollectionAssociationTests
|
|||
assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name
|
||||
end
|
||||
|
||||
def test_should_not_assign_delete_key_to_a_record
|
||||
def test_should_not_assign_destroy_key_to_a_record
|
||||
assert_nothing_raised ActiveRecord::UnknownAttributeError do
|
||||
@pirate.send(association_setter, { 'foo' => { '_delete' => '0' }})
|
||||
@pirate.send(association_setter, { 'foo' => { '_destroy' => '0' }})
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_ignore_new_associated_records_with_truthy_delete_attribute
|
||||
def test_should_ignore_new_associated_records_with_truthy_destroy_attribute
|
||||
@pirate.send(@association_name).destroy_all
|
||||
@pirate.reload.attributes = {
|
||||
association_getter => {
|
||||
'foo' => { :name => 'Grace OMalley' },
|
||||
'bar' => { :name => 'Privateers Greed', '_delete' => '1' }
|
||||
'bar' => { :name => 'Privateers Greed', '_destroy' => '1' }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,7 +466,7 @@ module NestedAttributesOnACollectionAssociationTests
|
|||
['1', 1, 'true', true].each do |true_variable|
|
||||
record = @pirate.reload.send(@association_name).create!(:name => 'Grace OMalley')
|
||||
@pirate.send(association_setter,
|
||||
@alternate_params[association_getter].merge('baz' => { :id => record.id, '_delete' => true_variable })
|
||||
@alternate_params[association_getter].merge('baz' => { :id => record.id, '_destroy' => true_variable })
|
||||
)
|
||||
|
||||
assert_difference('@pirate.send(@association_name).count', -1) do
|
||||
|
@ -435,7 +477,7 @@ module NestedAttributesOnACollectionAssociationTests
|
|||
|
||||
def test_should_not_destroy_the_associated_model_with_a_non_truthy_argument
|
||||
[nil, '', '0', 0, 'false', false].each do |false_variable|
|
||||
@alternate_params[association_getter]['foo']['_delete'] = false_variable
|
||||
@alternate_params[association_getter]['foo']['_destroy'] = false_variable
|
||||
assert_no_difference('@pirate.send(@association_name).count') do
|
||||
@pirate.update_attributes(@alternate_params)
|
||||
end
|
||||
|
@ -444,7 +486,7 @@ module NestedAttributesOnACollectionAssociationTests
|
|||
|
||||
def test_should_not_destroy_the_associated_model_until_the_parent_is_saved
|
||||
assert_no_difference('@pirate.send(@association_name).count') do
|
||||
@pirate.send(association_setter, @alternate_params[association_getter].merge('baz' => { :id => @child_1.id, '_delete' => true }))
|
||||
@pirate.send(association_setter, @alternate_params[association_getter].merge('baz' => { :id => @child_1.id, '_destroy' => true }))
|
||||
end
|
||||
assert_difference('@pirate.send(@association_name).count', -1) { @pirate.save }
|
||||
end
|
||||
|
@ -507,3 +549,33 @@ class TestNestedAttributesOnAHasAndBelongsToManyAssociation < ActiveRecord::Test
|
|||
|
||||
include NestedAttributesOnACollectionAssociationTests
|
||||
end
|
||||
|
||||
class TestNestedAttributesLimit < ActiveRecord::TestCase
|
||||
def setup
|
||||
Pirate.accepts_nested_attributes_for :parrots, :limit => 2
|
||||
|
||||
@pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
|
||||
end
|
||||
|
||||
def teardown
|
||||
Pirate.accepts_nested_attributes_for :parrots, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
|
||||
end
|
||||
|
||||
def test_limit_with_less_records
|
||||
@pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Big Big Love' } } }
|
||||
assert_difference('Parrot.count') { @pirate.save! }
|
||||
end
|
||||
|
||||
def test_limit_with_number_exact_records
|
||||
@pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' }, 'bar' => { :name => 'Blown Away' } } }
|
||||
assert_difference('Parrot.count', 2) { @pirate.save! }
|
||||
end
|
||||
|
||||
def test_limit_with_exceeding_records
|
||||
assert_raises(ActiveRecord::NestedAttributes::TooManyRecords) do
|
||||
@pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' },
|
||||
'bar' => { :name => 'Blown Away' },
|
||||
'car' => { :name => 'The Happening' }} }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -170,9 +170,9 @@ class ReflectionTest < ActiveRecord::TestCase
|
|||
|
||||
def test_reflection_of_all_associations
|
||||
# FIXME these assertions bust a lot
|
||||
assert_equal 30, Firm.reflect_on_all_associations.size
|
||||
assert_equal 23, Firm.reflect_on_all_associations(:has_many).size
|
||||
assert_equal 7, Firm.reflect_on_all_associations(:has_one).size
|
||||
assert_equal 36, Firm.reflect_on_all_associations.size
|
||||
assert_equal 26, Firm.reflect_on_all_associations(:has_many).size
|
||||
assert_equal 10, Firm.reflect_on_all_associations(:has_one).size
|
||||
assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
|
||||
end
|
||||
|
||||
|
|
|
@ -651,6 +651,14 @@ class ActiveRecordErrorI18nTests < ActiveSupport::TestCase
|
|||
assert_full_message 'Title is kaputt?!', :title, :kaputt, :message => :broken
|
||||
end
|
||||
|
||||
test "#full_message with different scope" do
|
||||
store_translations(:my_errors => { :messages => { :kaputt => 'is kaputt' } })
|
||||
assert_full_message 'Title is kaputt', :title, :kaputt, :scope => [:activerecord, :my_errors]
|
||||
|
||||
store_translations(:my_errors => { :full_messages => { :kaputt => '{{attribute}} {{message}}!' } })
|
||||
assert_full_message 'Title is kaputt!', :title, :kaputt, :scope => [:activerecord, :my_errors]
|
||||
end
|
||||
|
||||
# switch locales
|
||||
|
||||
test "#message allows to switch locales" do
|
||||
|
|
|
@ -28,6 +28,12 @@ class ProtectedPerson < ActiveRecord::Base
|
|||
set_table_name 'people'
|
||||
attr_accessor :addon
|
||||
attr_protected :first_name
|
||||
|
||||
def special_error
|
||||
this_method_does_not_exist!
|
||||
rescue
|
||||
errors.add(:special_error, "This method does not exist")
|
||||
end
|
||||
end
|
||||
|
||||
class UniqueReply < Reply
|
||||
|
@ -172,6 +178,14 @@ class ValidationsTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_values_are_not_retrieved_unless_needed
|
||||
assert_nothing_raised do
|
||||
person = ProtectedPerson.new
|
||||
person.special_error
|
||||
assert_equal "This method does not exist", person.errors[:special_error]
|
||||
end
|
||||
end
|
||||
|
||||
def test_single_error_per_attr_iteration
|
||||
r = Reply.new
|
||||
r.save
|
||||
|
@ -905,14 +919,18 @@ class ValidationsTest < ActiveRecord::TestCase
|
|||
end
|
||||
|
||||
def test_validates_length_with_globally_modified_error_message
|
||||
ActiveSupport::Deprecation.silence do
|
||||
ActiveRecord::Errors.default_error_messages[:too_short] = 'tu est trops petit hombre {{count}}'
|
||||
end
|
||||
defaults = ActiveSupport::Deprecation.silence { ActiveRecord::Errors.default_error_messages }
|
||||
original_message = defaults[:too_short]
|
||||
defaults[:too_short] = 'tu est trops petit hombre {{count}}'
|
||||
|
||||
Topic.validates_length_of :title, :minimum => 10
|
||||
t = Topic.create(:title => 'too short')
|
||||
assert !t.valid?
|
||||
|
||||
assert_equal 'tu est trops petit hombre 10', t.errors['title']
|
||||
|
||||
ensure
|
||||
defaults[:too_short] = original_message
|
||||
end
|
||||
|
||||
def test_validates_size_of_association
|
||||
|
@ -1432,12 +1450,22 @@ class ValidationsTest < ActiveRecord::TestCase
|
|||
end
|
||||
|
||||
def test_validation_order
|
||||
Topic.validates_presence_of :title
|
||||
Topic.validates_length_of :title, :minimum => 2
|
||||
Topic.validates_presence_of :title, :author_name
|
||||
Topic.validate {|topic| topic.errors.add('author_email_address', 'will never be valid')}
|
||||
Topic.validates_length_of :title, :content, :minimum => 2
|
||||
|
||||
t = Topic.new("title" => "")
|
||||
assert !t.valid?
|
||||
assert_equal "can't be blank", t.errors.on("title").first
|
||||
t = Topic.new :title => ''
|
||||
t.valid?
|
||||
e = t.errors.instance_variable_get '@errors'
|
||||
assert_equal 'title', key = e.keys.first
|
||||
assert_equal "can't be blank", t.errors.on(key).first
|
||||
assert_equal 'is too short (minimum is 2 characters)', t.errors.on(key).second
|
||||
assert_equal 'author_name', key = e.keys.second
|
||||
assert_equal "can't be blank", t.errors.on(key)
|
||||
assert_equal 'author_email_address', key = e.keys.third
|
||||
assert_equal 'will never be valid', t.errors.on(key)
|
||||
assert_equal 'content', key = e.keys.fourth
|
||||
assert_equal 'is too short (minimum is 2 characters)', t.errors.on(key)
|
||||
end
|
||||
|
||||
def test_invalid_should_be_the_opposite_of_valid
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue