I've got a record in my Rails app with an after_destroy
hook that needs to do be aware why the record gets destroyed. More specifically, if the record is being destroyed in a cascade because its parent says dependent: :destroy
, it needs to do things differently than if the record was individually destroyed.
What I tried to do is to see if its parent was destroyed?
, only to figure out that dependent: :destroy
callbacks are done before the parent is destroyed. Which makes sense because it should be able to fail. (i.e. restrict).
So, how do I do this?
Dependent is an option of Rails collection association declaration to cascade the delete action. The :destroy is to cause the associated object to also be destroyed when its owner is destroyed.
Basically destroy runs any callbacks on the model while delete doesn't. Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted). Returns the frozen instance.
Callbacks are methods that get called at certain moments of an object's life cycle. With callbacks it is possible to write code that will run whenever an Active Record object is created, saved, updated, deleted, validated, or loaded from the database.
In Rails, callbacks are hooks provided by Active Record that allow methods to run before or after a create, update, or destroy action occurs to an object. Since it can be hard to remember all of them and what they do, here is a quick reference for all current Rails 5 Active Record callbacks.
Solution #1
If your model is simple enough and you don't need to invoke any callbacks in the child relation, you can just use dependent: delete_all
in the parent.
Solution #2
For more complex scenarios you can use destroyed_by_association
, which returns a ActiveRecord::Reflection::HasManyReflection
object when it's part of cascade, or nil otherwise:
after_destroy :your_callback
def your_callback
if destroyed_by_association
# this is part of a cascade
else
# isolated deletion
end
end
I just tried this in Rails 4.2 and it works.
Source: https://github.com/rails/rails/issues/12828#issuecomment-28142658
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With