From 78bc14e6830cdf8d699d3d493e3292de2ec2efac Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Tue, 28 Mar 2023 22:21:17 -0400 Subject: [PATCH] Add option on how to handle orphans when arranging nodes --- lib/ancestry/class_methods.rb | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/ancestry/class_methods.rb b/lib/ancestry/class_methods.rb index c924063e..0b449187 100644 --- a/lib/ancestry/class_methods.rb +++ b/lib/ancestry/class_methods.rb @@ -40,16 +40,29 @@ def arrange(options = {}) # arranges array of nodes to a hierarchical hash # # @param nodes [Array[Node]] nodes to be arranged + # @param orphan_strategy [Symbol] :rootify or :destroy (default: :rootify) # @returns Hash{Node => {Node => {}, Node => {}}} # If a node's parent is not included, the node will be included as if it is a top level node - def arrange_nodes(nodes) + def arrange_nodes(nodes, orphan_strategy: :rootify) node_ids = Set.new(nodes.map(&:id)) index = Hash.new { |h, k| h[k] = {} } nodes.each_with_object({}) do |node, arranged| - children = index[node.id] - index[node.parent_id][node] = children - arranged[node] = children unless node_ids.include?(node.parent_id) + index[node.parent_id][node] = children = index[node.id] + if node.parent_id.nil? + arranged[node] = children + elsif !node_ids.include?(node.parent_id) + case orphan_strategy + when :destroy + # All children are destroyed as well (default) + when :adopt + raise ArgumentError, "Not Implemented" + when :rootify + arranged[node] = children + when :restrict + raise Ancestry::AncestryException, I18n.t("ancestry.cannot_delete_descendants") + end + end end end