Fix bug, when ':dependent => :destroy' option violates foreign key constraints, issue #12380

This commit is contained in:
Ivan Antropov 2013-10-26 12:35:59 +07:00
parent fa915461bc
commit 87d1aba3cb
5 changed files with 61 additions and 9 deletions

@ -1,3 +1,10 @@
* Move 'dependent: :destroy' handling for 'belongs_to'
from 'before_destroy' to 'after_destroy' callback chain
Fix #12380.
*Ivan Antropov*
* Fixed `ActiveRecord::Associations::CollectionAssociation#find`
when using `has_many` association with `:inverse_of` and finding an array of one element,
it should return an array of one element too.

@ -69,7 +69,10 @@ def define_extensions(model)
end
def define_callbacks(model, reflection)
add_before_destroy_callbacks(model, name) if options[:dependent]
if options[:dependent]
check_dependent_options
add_destroy_callbacks(model, name)
end
Association.extensions.each do |extension|
extension.build model, reflection
end
@ -110,12 +113,14 @@ def valid_dependent_options
private
def add_before_destroy_callbacks(model, name)
unless valid_dependent_options.include? options[:dependent]
raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{options[:dependent]}"
def check_dependent_options
unless valid_dependent_options.include? options[:dependent]
raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{options[:dependent]}"
end
end
model.before_destroy lambda { |o| o.association(name).handle_dependency }
end
def add_destroy_callbacks(model, name)
model.before_destroy lambda { |o| o.association(name).handle_dependency }
end
end
end

@ -133,5 +133,9 @@ def add_touch_callbacks(model, reflection)
model.after_touch callback
model.after_destroy callback
end
def add_destroy_callbacks(model, name)
model.after_destroy lambda { |o| o.association(name).handle_dependency }
end
end
end

@ -20,8 +20,8 @@ def valid_dependent_options
private
def add_before_destroy_callbacks(model, name)
super unless options[:through]
end
def add_destroy_callbacks(model, name)
super unless options[:through]
end
end
end

@ -831,3 +831,39 @@ def test_reflect_the_most_recent_change
assert_equal post.author_id, author2.id
end
end
class BelongsToWithForeignKeyTest < ActiveRecord::TestCase
def setup
ActiveRecord::Schema.define do
drop_table :authors, if_exists: true
drop_table :author_addresses, if_exists: true
create_table :author_addresses do |t|
end
exec_query <<-eos
create table authors(
id int,
author_address_id int,
name varchar(255),
PRIMARY KEY (id),
FOREIGN KEY (author_address_id) REFERENCES author_addresses(id)
);
eos
end
end
def teardown
ActiveRecord::Schema.define do
drop_table :authors, if_exists: true
drop_table :author_addresses, if_exists: true
end
end
def test_destroy_linked_models
address = AuthorAddress.create!
author = Author.create! id: 1, name: "Author", author_address_id: address.id
author.destroy!
end
end