1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #12450 from iantropov/master

Fix bug, when ':dependent => :destroy' violates foreign key constraints

Conflicts:
	activerecord/CHANGELOG.md
	activerecord/lib/active_record/associations/builder/association.rb
	activerecord/lib/active_record/associations/builder/has_one.rb
This commit is contained in:
Rafael Mendonça França 2014-06-27 15:39:48 -03:00
commit b22edc6488
5 changed files with 59 additions and 5 deletions

View file

@ -1,3 +1,10 @@
* Move 'dependent: :destroy' handling for 'belongs_to'
from 'before_destroy' to 'after_destroy' callback chain
Fix #12380.
*Ivan Antropov*
* Detect in-place modifications on String attributes.
Before this change user have to mark the attribute as changed to it be persisted

View file

@ -85,7 +85,11 @@ module ActiveRecord::Associations::Builder
end
def self.define_callbacks(model, reflection)
add_before_destroy_callbacks(model, reflection) if reflection.options[:dependent]
if dependent = reflection.options[:dependent]
check_dependent_options(dependent)
add_destroy_callbacks(model, reflection)
end
Association.extensions.each do |extension|
extension.build model, reflection
end
@ -126,11 +130,13 @@ module ActiveRecord::Associations::Builder
private
def self.add_before_destroy_callbacks(model, reflection)
unless valid_dependent_options.include? reflection.options[:dependent]
raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{reflection.options[:dependent]}"
def self.check_dependent_options(dependent)
unless valid_dependent_options.include? dependent
raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{dependent}"
end
end
def self.add_destroy_callbacks(model, reflection)
name = reflection.name
model.before_destroy lambda { |o| o.association(name).handle_dependency }
end

View file

@ -107,5 +107,10 @@ module ActiveRecord::Associations::Builder
model.after_touch callback
model.after_destroy callback
end
def self.add_destroy_callbacks(model, reflection)
name = reflection.name
model.after_destroy lambda { |o| o.association(name).handle_dependency }
end
end
end

View file

@ -16,7 +16,7 @@ module ActiveRecord::Associations::Builder
private
def self.add_before_destroy_callbacks(model, reflection)
def self.add_destroy_callbacks(model, reflection)
super unless reflection.options[:through]
end
end

View file

@ -935,3 +935,39 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal 1, Column.count
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