Skip to content

Commit

Permalink
Fix bug, when ':dependent => :destroy' option violates foreign key co…
Browse files Browse the repository at this point in the history
…nstraints, issue #12380
  • Loading branch information
iantropov committed Oct 26, 2013
1 parent fa91546 commit 87d1aba
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 9 deletions.
7 changes: 7 additions & 0 deletions activerecord/CHANGELOG.md
@@ -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.
Expand Down
17 changes: 11 additions & 6 deletions activerecord/lib/active_record/associations/builder/association.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Up @@ -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
Expand Up @@ -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
Expand Up @@ -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

0 comments on commit 87d1aba

Please sign in to comment.