From 64006ba68ce0968b4b29449abff9a6d0767f8165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20St=C3=B6ckel?= Date: Mon, 16 Oct 2023 00:23:15 +0200 Subject: [PATCH] Destroy in reverse order to rspect foreign keys (#478) Otherwise a foreign key error can occur if foreign keys have been added, for example: `Mysql2::Error: Cannot delete or update a parent row: a foreign key constraint fails` --- lib/awesome_nested_set/model/prunable.rb | 7 ++++++- spec/models/users_spec.rb | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/awesome_nested_set/model/prunable.rb b/lib/awesome_nested_set/model/prunable.rb index dc84cf0c..edefee4e 100644 --- a/lib/awesome_nested_set/model/prunable.rb +++ b/lib/awesome_nested_set/model/prunable.rb @@ -35,9 +35,14 @@ def destroy_descendants end end + # Use reverse to delete from deepest child to parent in order to respect any possible foreign keys + def decendants_to_destroy_in_order + descendants.reverse + end + def destroy_or_delete_descendants if acts_as_nested_set_options[:dependent] == :destroy - descendants.each do |model| + decendants_to_destroy_in_order.each do |model| model.skip_before_destroy = true model.destroy end diff --git a/spec/models/users_spec.rb b/spec/models/users_spec.rb index 4f6761d2..eaa7eb93 100644 --- a/spec/models/users_spec.rb +++ b/spec/models/users_spec.rb @@ -652,6 +652,19 @@ expect(User.valid?).to be_truthy end + it "destroys in the right order to respect foreign keys" do + User.acts_as_nested_set_options[:dependent] = :destroy + + expect(users(:top_level).decendants_to_destroy_in_order).to eq [ + users(:child_3), + users(:child_2_1), + users(:child_2), + users(:child_1) + ] + expect(users(:top_level)).to receive(:decendants_to_destroy_in_order).once.and_call_original + expect { users(:top_level).destroy! }.to change(User, :count).by(-5) + end + it "assigning_parent_uuid_on_create" do user = User.create!(:name => "Child", :parent_uuid => users(:child_2).uuid) expect(users(:child_2)).to eq(user.parent)