Skip to content

Commit aa75459

Browse files
committed
Prevent deletion of pages with descendants that are attached to nodes
When a parent page is destroyed, its descendant pages are also destroyed via the nested set. If any of those descendants are attached to menu nodes, the node references become broken. This adds a before_destroy check that prevents deletion when descendant pages still have menu node associations.
1 parent b52d064 commit aa75459

3 files changed

Lines changed: 28 additions & 0 deletions

File tree

app/models/alchemy/page.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ class Page < BaseRecord
135135

136136
has_many :page_ingredients, class_name: "Alchemy::Ingredients::Page", foreign_key: :related_object_id, dependent: :nullify
137137

138+
before_destroy :check_descendants_for_menu_nodes
139+
138140
before_validation :set_language,
139141
if: -> { language.nil? }
140142

@@ -611,5 +613,13 @@ def touch_nodes
611613
ids = node_ids + nodes.flat_map { |n| n.ancestors.pluck(:id) }
612614
Node.where(id: ids).touch_all
613615
end
616+
617+
def check_descendants_for_menu_nodes
618+
pages_with_nodes = descendants.joins(:nodes).reorder("alchemy_pages.lft").distinct
619+
if pages_with_nodes.exists?
620+
errors.add(:descendants, :still_attached_to_nodes, page_names: pages_with_nodes.map(&:name).to_sentence)
621+
throw :abort
622+
end
623+
end
614624
end
615625
end

config/locales/alchemy.en.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,8 @@ en:
834834
base:
835835
restrict_dependent_destroy:
836836
has_many: "There are still %{record} attached to this page. Please remove them first."
837+
descendants:
838+
still_attached_to_nodes: "The following descendant pages are still attached to menu nodes: %{page_names}. Please remove them first."
837839
alchemy/element:
838840
attributes:
839841
page_version_id:

spec/models/alchemy/page_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,22 @@ module Alchemy
281281
expect { page.destroy! }.to change { ingredient.reload.related_object_id }.from(page.id).to(nil)
282282
end
283283
end
284+
285+
context "with a descendant page attached to a menu node" do
286+
let!(:page) { create(:alchemy_page) }
287+
let!(:child_page) { create(:alchemy_page, parent: page) }
288+
let!(:node) { create(:alchemy_node, page: child_page, parent: create(:alchemy_node)) }
289+
290+
it "prevents destruction of the parent page" do
291+
expect(page.destroy).to be false
292+
expect(page.errors[:descendants]).to include(
293+
::I18n.t(
294+
"activerecord.errors.models.alchemy/page.attributes.descendants.still_attached_to_nodes",
295+
page_names: child_page.name
296+
)
297+
)
298+
end
299+
end
284300
end
285301
end
286302

0 commit comments

Comments
 (0)