diff options
author | Ivan Antropov <antropov.ivan@gmail.com> | 2013-10-26 12:35:59 +0700 |
---|---|---|
committer | Ivan Antropov <antropov.ivan@gmail.com> | 2013-10-26 12:35:59 +0700 |
commit | 87d1aba3cba0d9b02490784b3090b0e5c94f56df (patch) | |
tree | 032f9bc83d33ed12964716a1bdc53d53e4253cb3 | |
parent | fa915461bc4892b8d53d3d4e202ba16f0dbdfe12 (diff) | |
download | rails-87d1aba3cba0d9b02490784b3090b0e5c94f56df.tar.gz rails-87d1aba3cba0d9b02490784b3090b0e5c94f56df.tar.bz2 rails-87d1aba3cba0d9b02490784b3090b0e5c94f56df.zip |
Fix bug, when ':dependent => :destroy' option violates foreign key constraints, issue #12380
5 files changed, 61 insertions, 9 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 810a2c668d..58d7ba22bf 100644 --- a/activerecord/CHANGELOG.md +++ b/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. diff --git a/activerecord/lib/active_record/associations/builder/association.rb b/activerecord/lib/active_record/associations/builder/association.rb index 1059fc032d..18d46b4849 100644 --- a/activerecord/lib/active_record/associations/builder/association.rb +++ b/activerecord/lib/active_record/associations/builder/association.rb @@ -69,7 +69,10 @@ module ActiveRecord::Associations::Builder 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 @@ module ActiveRecord::Associations::Builder 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 diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb index 4e88b50ec5..9c1bbad8ca 100644 --- a/activerecord/lib/active_record/associations/builder/belongs_to.rb +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -133,5 +133,9 @@ module ActiveRecord::Associations::Builder 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 diff --git a/activerecord/lib/active_record/associations/builder/has_one.rb b/activerecord/lib/active_record/associations/builder/has_one.rb index 62d454ce55..066a787ff9 100644 --- a/activerecord/lib/active_record/associations/builder/has_one.rb +++ b/activerecord/lib/active_record/associations/builder/has_one.rb @@ -20,8 +20,8 @@ module ActiveRecord::Associations::Builder 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 diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index a79f145e31..19a8ae75ea 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -831,3 +831,39 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase 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 |