Introduce orphan_strategy none
Many people override apply_orphan_strategy and either leave it blank or call custom methods from there. Introducing `orphan_strategy: :none` to allows developers to skip default orphan handling. From here a developer can add `before_destroy` with what ever logic is desired. It is possible to introduce a custom orphan strategy with a mixin/concern, but it doesn't seem to save any code and is not the best interface with too many nuances. Leaving in the code for now but not promoting to a supported feature yet.
This commit is contained in:
parent
cb9635cc3a
commit
753013a1bb
|
@ -5,6 +5,7 @@ a nice looking [Changelog](http://keepachangelog.com).
|
||||||
|
|
||||||
## Version [HEAD] <sub><sup>Unreleased</sub></sup>
|
## Version [HEAD] <sub><sup>Unreleased</sub></sup>
|
||||||
|
|
||||||
|
* 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)
|
* 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)
|
* 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)
|
* 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)
|
- `ancestry_primary_key_format` (introduced 4.3.0, removed by #649)
|
||||||
- `touch_ancestors` (introduced 2.1, removed by TODO)
|
- `touch_ancestors` (introduced 2.1, removed by TODO)
|
||||||
* These are seen as internal and may go away:
|
* 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] <sub><sup>2023-04-01</sub></sup>
|
## Version [4.3.3] <sub><sup>2023-04-01</sub></sup>
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,7 @@ The `has_ancestry` method supports the following options:
|
||||||
:restrict An AncestryException is raised if any children exist
|
:restrict An AncestryException is raised if any children exist
|
||||||
:adopt The orphan subtree is added to the parent of the deleted node
|
:adopt The orphan subtree is added to the parent of the deleted node
|
||||||
If the deleted node is Root, then rootify the orphan subtree
|
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)
|
:cache_depth Cache the depth of each node: (See Depth Cache section)
|
||||||
false Do not cache depth (default)
|
false Do not cache depth (default)
|
||||||
true Cache depth in 'ancestry_depth'
|
true Cache depth in 'ancestry_depth'
|
||||||
|
|
|
@ -60,19 +60,13 @@ module Ancestry
|
||||||
after_update :update_descendants_with_new_ancestry, if: :ancestry_changed?
|
after_update :update_descendants_with_new_ancestry, if: :ancestry_changed?
|
||||||
|
|
||||||
# Apply orphan strategy before destroy
|
# Apply orphan strategy before destroy
|
||||||
case orphan_strategy
|
orphan_strategy_helper = "apply_orphan_strategy_#{orphan_strategy}"
|
||||||
when :rootify
|
if method_defined?(orphan_strategy_helper)
|
||||||
alias_method :apply_orphan_strategy, :apply_orphan_strategy_rootify
|
alias_method :apply_orphan_strategy, orphan_strategy_helper
|
||||||
when :destroy
|
before_destroy :apply_orphan_strategy
|
||||||
alias_method :apply_orphan_strategy, :apply_orphan_strategy_destroy
|
elsif orphan_strategy.to_s != "none"
|
||||||
when :adopt
|
|
||||||
alias_method :apply_orphan_strategy, :apply_orphan_strategy_adopt
|
|
||||||
when :restrict
|
|
||||||
alias_method :apply_orphan_strategy, :apply_orphan_strategy_restrict
|
|
||||||
else
|
|
||||||
raise Ancestry::AncestryException.new(I18n.t("ancestry.invalid_orphan_strategy"))
|
raise Ancestry::AncestryException.new(I18n.t("ancestry.invalid_orphan_strategy"))
|
||||||
end
|
end
|
||||||
before_destroy :apply_orphan_strategy
|
|
||||||
|
|
||||||
# Create ancestry column accessor and set to option or default
|
# Create ancestry column accessor and set to option or default
|
||||||
if options[:cache_depth]
|
if options[:cache_depth]
|
||||||
|
|
|
@ -85,6 +85,62 @@ class OphanStrategiesTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
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
|
def test_basic_delete
|
||||||
AncestryTestDatabase.with_model do |model|
|
AncestryTestDatabase.with_model do |model|
|
||||||
n1 = model.create! #create a root node
|
n1 = model.create! #create a root node
|
||||||
|
|
Loading…
Reference in New Issue