I have two classes: Parent and Child with
Child:
belongs_to :parent
and
Parent
has_many :children, :dependent => :destroy
The problem is that I want to check that there is always at least one child present, so I have a before_destroy method in Child that abort the destroy if it is the only child belonging to its parent.
And, if I want to destroy the parent, it will call the before_destroy callback on every child, but when there is one child, it will abort the destroy, so the parent will never get destroyed.
How can I tell the child to call the before_destroy callback only if it's not being destroyed because of its parent?
Thanks!
dependent: :destroy Rails, when attempting to destroy an instance of the Parent, will also iteratively go through each child of the parent calling destroy on the child. The benefit of this is that any callbacks and validation on those children are given their day in the sun.
what is dependent :destroy. 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.
:prepend — If true, the callback will be prepended to the existing chain rather than appended. In our case, with the user model we can see the callback order using _destroy_callbacks method : lambda in the callback chains are the dependent: :delete_all or dependent: :destroy before_destroy actions.
The standard way to delete associated data in Rails is to let ActiveRecord handle it via dependent: :destroy . In the following example, when the parent model ( author ) is deleted, all data in the dependent models will get deleted by ActiveRecord as well. There is an indexed foreign key, but no foreign key constraint.
In Rails 4 you can do the following:
class Parent < AR::Base has_many :children, dependent: :destroy end class Child < AR::Base belongs_to :parent before_destroy :check_destroy_allowed, unless: :destroyed_by_association private def check_destroy_allowed # some condition that returns true or false end end
This way, when calling destroy
directly on a child, the check_destroy_allowed
callback will be run, but when you call destroy
on the parent, it won't.
has_many :childs, :dependent => :delete_all
This will delete all the children without running any hooks.
You can find the documentation at: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many
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