Skip to content

Commit

Permalink
Do not destroy nodes with dependent nodes that are in use on a page
Browse files Browse the repository at this point in the history
This moves the validation up in the file so that awesome_nested_set does
not run its `delete_all` callback before we validate that it can do
that.

It also extends the validation such that we collect all the pages that
are referenced in the subtree below this node.
  • Loading branch information
mamhoff committed May 13, 2020
1 parent 27480a2 commit bacc74f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 4 deletions.
9 changes: 5 additions & 4 deletions app/models/alchemy/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ module Alchemy
class Node < BaseRecord
VALID_URL_REGEX = /\A(\/|\D[a-z\+\d\.\-]+:)/

before_destroy :check_if_related_essence_nodes_present

acts_as_nested_set scope: "language_id", touch: true
stampable stamper_class_name: Alchemy.user_class_name

Expand All @@ -14,8 +16,6 @@ class Node < BaseRecord

has_many :essence_nodes, class_name: "Alchemy::EssenceNode", foreign_key: :node_id, inverse_of: :ingredient_association

before_destroy :check_if_related_essence_nodes_present

validates :name, presence: true, if: -> { page.nil? }
validates :url, format: { with: VALID_URL_REGEX }, unless: -> { url.nil? }

Expand Down Expand Up @@ -79,8 +79,9 @@ def view_folder_name
end

def check_if_related_essence_nodes_present
if essence_nodes.any?
errors.add(:base, :essence_nodes_present, page_names: essence_nodes.map(&:page).map(&:name).to_sentence)
dependent_essence_nodes = self_and_descendants.flat_map(&:essence_nodes)
if dependent_essence_nodes.any?
errors.add(:base, :essence_nodes_present, page_names: dependent_essence_nodes.map(&:page).map(&:name).to_sentence)
throw(:abort)
end
end
Expand Down
10 changes: 10 additions & 0 deletions spec/models/alchemy/node_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ module Alchemy
expect(node).not_to be_destroyed
expect(node.errors.full_messages).to eq(["This menu item is in use inside an Alchemy element on the following pages: #{page.name}."])
end

context "if there are essence nodes present on a child node" do
let!(:parent_node) { create(:alchemy_node, children: [node]) }

it "does not destroy the node and children either but adds an error" do
parent_node.destroy
expect(parent_node).not_to be_destroyed
expect(parent_node.errors.full_messages).to eq(["This menu item is in use inside an Alchemy element on the following pages: #{page.name}."])
end
end
end
end
end

0 comments on commit bacc74f

Please sign in to comment.