aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/associations/builder/association.rb14
-rw-r--r--activerecord/lib/active_record/associations/builder/belongs_to.rb5
-rw-r--r--activerecord/lib/active_record/associations/builder/has_one.rb2
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb36
5 files changed, 59 insertions, 5 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 4af510603e..f94e8f21ca 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*
+
* Detect in-place modifications on String attributes.
Before this change user have to mark the attribute as changed to it be persisted
diff --git a/activerecord/lib/active_record/associations/builder/association.rb b/activerecord/lib/active_record/associations/builder/association.rb
index f085fd1cfd..e474236939 100644
--- a/activerecord/lib/active_record/associations/builder/association.rb
+++ b/activerecord/lib/active_record/associations/builder/association.rb
@@ -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
diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb
index 3998aca23e..954ea3878a 100644
--- a/activerecord/lib/active_record/associations/builder/belongs_to.rb
+++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb
@@ -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
diff --git a/activerecord/lib/active_record/associations/builder/has_one.rb b/activerecord/lib/active_record/associations/builder/has_one.rb
index a1f4f51664..c194c8ae9a 100644
--- a/activerecord/lib/active_record/associations/builder/has_one.rb
+++ b/activerecord/lib/active_record/associations/builder/has_one.rb
@@ -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
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index d8d8bbf75e..65b6068df4 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -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