diff options
Diffstat (limited to 'activerecord')
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 |