diff --git a/CHANGELOG.md b/CHANGELOG.md index 05f2227..e3ee213 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ a nice looking [Changelog](http://keepachangelog.com). ## Version [HEAD] Unreleased +* Introduce `orphan_strategy: :none` [#658](https://github.com/stefankroes/ancestry/pull/658) * Introduce `rebuild_counter_cache!` to reset counter caches. [#663](https://github.com/stefankroes/ancestry/pull/663) [#668](https://github.com/stefankroes/ancestry/pull/668) (thx @RongRongTeng) * Documentation fixes [#664](https://github.com/stefankroes/ancestry/pull/664) [#667](https://github.com/stefankroes/ancestry/pull/667) (thx @motokikando, @onerinas) * Introduce `build_cache_depth_sql!`, a sql alternative to `build_cache_depth` [#654](https://github.com/stefankroes/ancestry/pull/654) @@ -41,7 +42,7 @@ jobs. If you need to do this in the ui, please use `cache_depth`. - `ancestry_primary_key_format` (introduced 4.3.0, removed by #649) - `touch_ancestors` (introduced 2.1, removed by TODO) * These are seen as internal and may go away: - - `apply_orphan_strategy` (TODO: use `orphan_strategy => none` and define `before_destory`) + - `apply_orphan_strategy` Please use `orphan_strategy: :none` and a custom `before_destory` instead. ## Version [4.3.3] 2023-04-01 diff --git a/README.md b/README.md index 71deede..37567c6 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,7 @@ The `has_ancestry` method supports the following options: :restrict An AncestryException is raised if any children exist :adopt The orphan subtree is added to the parent of the deleted node If the deleted node is Root, then rootify the orphan subtree + :none skip this logic. (add your own `before_destroy`) :cache_depth Cache the depth of each node: (See Depth Cache section) false Do not cache depth (default) true Cache depth in 'ancestry_depth' diff --git a/lib/ancestry/has_ancestry.rb b/lib/ancestry/has_ancestry.rb index f3773c4..55daed9 100644 --- a/lib/ancestry/has_ancestry.rb +++ b/lib/ancestry/has_ancestry.rb @@ -60,19 +60,13 @@ module Ancestry after_update :update_descendants_with_new_ancestry, if: :ancestry_changed? # Apply orphan strategy before destroy - case orphan_strategy - when :rootify - alias_method :apply_orphan_strategy, :apply_orphan_strategy_rootify - when :destroy - alias_method :apply_orphan_strategy, :apply_orphan_strategy_destroy - when :adopt - alias_method :apply_orphan_strategy, :apply_orphan_strategy_adopt - when :restrict - alias_method :apply_orphan_strategy, :apply_orphan_strategy_restrict - else + orphan_strategy_helper = "apply_orphan_strategy_#{orphan_strategy}" + if method_defined?(orphan_strategy_helper) + alias_method :apply_orphan_strategy, orphan_strategy_helper + before_destroy :apply_orphan_strategy + elsif orphan_strategy.to_s != "none" raise Ancestry::AncestryException.new(I18n.t("ancestry.invalid_orphan_strategy")) end - before_destroy :apply_orphan_strategy # Create ancestry column accessor and set to option or default if options[:cache_depth] diff --git a/test/concerns/orphan_strategies_test.rb b/test/concerns/orphan_strategies_test.rb index 8474a73..bb4d12c 100644 --- a/test/concerns/orphan_strategies_test.rb +++ b/test/concerns/orphan_strategies_test.rb @@ -85,6 +85,62 @@ class OphanStrategiesTest < ActiveSupport::TestCase end end + def test_apply_orphan_strategy_none + AncestryTestDatabase.with_model orphan_strategy: :none do |model, roots| + root = model.create! + child = model.create!(:parent => root) + model.class_eval do + def apply_orphan_strategy + raise "this should not be called" + end + end + assert_difference 'model.count', -1 do + root.destroy + end + # this record should still exist + assert child.reload.root_id == root.id + end + end + + def test_apply_orphan_strategy_custom + AncestryTestDatabase.with_model orphan_strategy: :none do |model| + model.class_eval do + before_destroy :apply_orphan_strategy_abc + + def apply_orphan_strategy_abc + apply_orphan_strategy_destroy + end + end + + root = model.create! + 3.times { root.children.create! } + model.create! # a node that is not affected + assert_difference 'model.count', -4 do + root.destroy + end + end + end + + # Not supported. Keeping around to explore for future uses. + def test_apply_orphan_strategy_custom_unsupported + AncestryTestDatabase.with_model skip_ancestry: true do |model| + model.class_eval do + # needs to be defined before calling has_ancestry + def apply_orphan_strategy_abc + apply_orphan_strategy_destroy + end + + has_ancestry orphan_strategy: :abc, ancestry_column: AncestryTestDatabase.ancestry_column + end + root = model.create! + 3.times { root.children.create! } + model.create! # a node that is not affected + assert_difference 'model.count', -4 do + root.destroy + end + end + end + def test_basic_delete AncestryTestDatabase.with_model do |model| n1 = model.create! #create a root node