Skip to content

Commit

Permalink
Delete nested elements quickly
Browse files Browse the repository at this point in the history
This builds an array of all the descendent elements from this element,
and then calls the DeleteElements service class on them. Afterwards it
resets the two associations, so that no callbacks run on in-memory
deleted objects.
  • Loading branch information
mamhoff committed Apr 9, 2021
1 parent 8b915e6 commit fdb4668
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 0 deletions.
13 changes: 13 additions & 0 deletions app/models/alchemy/element.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class Element < BaseRecord

has_many :contents, dependent: :destroy, inverse_of: :element

before_destroy :destroy_all_nested_elements

has_many :all_nested_elements,
-> { order(:position) },
class_name: "Alchemy::Element",
Expand Down Expand Up @@ -347,5 +349,16 @@ def touch_touchable_pages

touchable_pages.each(&:touch)
end

def destroy_all_nested_elements
deeply_nested_elements = descendent_elements(self).flatten
DeleteElements.new(deeply_nested_elements).call
nested_elements.reset
all_nested_elements.reset
end

def descendent_elements(el)
el.all_nested_elements + el.all_nested_elements.map { |el| descendent_elements(el) }
end
end
end
14 changes: 14 additions & 0 deletions spec/models/alchemy/element_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -968,4 +968,18 @@ module Alchemy
end
end
end

describe "destroy callbacks" do
let(:element) { create(:alchemy_element) }
let!(:nested_element_1) { create(:alchemy_element, parent_element: element) }
let!(:nested_element_2) { create(:alchemy_element, parent_element: nested_element_1) }
let!(:nested_element_3) { create(:alchemy_element, parent_element: nested_element_2) }

it "destroys all the nested elements quickly" do
expect(Alchemy::DeleteElements).to receive(:new).with(
[nested_element_1, nested_element_2, nested_element_3]
).and_call_original
element.reload.destroy!
end
end
end

0 comments on commit fdb4668

Please sign in to comment.