Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extensible orphan_strategy #658

Merged
merged 2 commits into from Jul 13, 2023

Conversation

kbrock
Copy link
Collaborator

@kbrock kbrock commented Mar 28, 2023

This introduces 2 ways for developers to extend the built in orphan strategies.

Fixes #142

/cc @brendon Here is custom orphan strategies.

After implementing this, I'm thinking of keeping :none and dropping the custom string.

  • none is straightforward and simple to document. The custom one is much harder (red flag)
  • There is a gotcha requiring them to define it first. Requires a bunch of documentation (red flag)
  • Defining your own before_destroy seems simple.
  • Avoiding the build the callback gook would be nice. Maybe leaving this code as is but not documenting it may be a plan as well.
  • I don't like people knowing about and overriding apply_orphan_strategy, but maybe it is not so bad.

As a developer, what is your take?


Turning orphan strategy handling off

class ModelBefore
  def apply_orphan_strategy # no longer necessary with :none
    # skip
  end
  has_ancestry orphan_strategy: :none
end

class ModelAfter
  has_ancestry orphan_strategy: :none
end

Implementing a custom orphan strategy

module CustomStrategy
  def apply_orphan_strategy_abc
    # custom goodness
  end
end

class ModelAfter1
  includes CustomStrategy
  has_ancestry orphan_strategy: :abc
end

class ModelAfter2
  includes CustomStrategy
  before_destroy :apply_orphan_strategy_abc
  has_ancestry orphan_strategy: :none
end

Copy link
Contributor

@brendon brendon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good. Just a couple of suggestions there :D

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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you just compare with the symbol to avoid calling to_s?

README.md Outdated
:orphan_strategy Instruct Ancestry what to do with children of a node that is destroyed:
:destroy All children are destroyed as well (default)
:rootify The children of the destroyed node become root nodes
: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`)
String Custom. `before_destroy :apply_orphan_strategy_#{String}` to handle orphans.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might need a little expansion so that people know they don't need to add their own before_destroy block here. Perhaps:

Your custom destroy strategy method named with the convention apply_orphan_strategy_#{String} will be executed as an before_destroy callback.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, After trying to document this had me wanting to drop the feature apply_orphan_strategy_#{string} and just have the person write a before_destroy

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea that makes sense :)

@kbrock kbrock force-pushed the extensible_orphan_strategy branch from 3b3edca to b01c78e Compare March 29, 2023 01:57
@kbrock kbrock force-pushed the extensible_orphan_strategy branch from b01c78e to 967445d Compare April 9, 2023 02:45
@kbrock
Copy link
Collaborator Author

kbrock commented Jul 13, 2023

Ok, so this stalled.

I think that introducing none makes sense while introducing a naming strategy is too much.
The issues with making sure the method is defined first and the difficulty in documentation makes me feel that this is not ready yet.

I will keep this PR intact, and create another PR to introduce none
The naming strategy code is smaller and simpler.
Not ready to support the strategy yet, but leaving the code in there.

@kbrock kbrock force-pushed the extensible_orphan_strategy branch from 967445d to 562fd6f Compare July 13, 2023 13:33
also tried for some consistency in messaging around attributes
@kbrock kbrock force-pushed the extensible_orphan_strategy branch from 562fd6f to c0d2bf6 Compare July 13, 2023 13:34
@kbrock
Copy link
Collaborator Author

kbrock commented Jul 13, 2023

update:

  • Removed documentation around custom strategies. Just supporting none for now.
  • Reworked wording in readme around has_ancestry options.
  • rebased to fix conflict

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.
@kbrock kbrock force-pushed the extensible_orphan_strategy branch from c0d2bf6 to 753013a Compare July 13, 2023 13:40
@kbrock
Copy link
Collaborator Author

kbrock commented Jul 13, 2023

update:

  • handle alternate ancestry column names in custom ancestry test

@kbrock kbrock merged commit c08b07d into stefankroes:master Jul 13, 2023
8 checks passed
@kbrock kbrock deleted the extensible_orphan_strategy branch July 13, 2023 13:48
@brendon
Copy link
Contributor

brendon commented Jul 13, 2023

Looks good :) When I'm upgrading next, I'll give it a go. It might be that the custom orphan strategy would need to be defined immediately after has_ancestry to ensure callbacks are still in the correct order in some apps :)

@kbrock
Copy link
Collaborator Author

kbrock commented Jul 14, 2023

Actually, the custom method needs to be defined before the has_ancestry.
So just adding an include or subclassing a model would work.

But in looking through github, the overrides for this method were almost all to disable it.
There was one that moved this to a background task. (was thinking of changing these methods to pass an object, but the reliance on changed makes it tricky)

@brendon
Copy link
Contributor

brendon commented Jul 16, 2023

I think in my case it was the order of deletion but I think that was also fixed recently so I might not need the custom method anyway. I've not started moving to Rails 7 yet but when I do, this gem will get upgraded :D

@kbrock
Copy link
Collaborator Author

kbrock commented Jul 17, 2023

@brendon Thanks. That info helps me.

Someone asked about when this will ship. I'm probably going to backport this, as I am making (slow) progress towards converting many functions to sql only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Custom orphan_strategy would be desirable
2 participants