Rails: how to disable before_destroy callback when it's being destroyed because of the parent is being destroyed (:dependent => :destroy)
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
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.
carp's answer above will work if you set prepend to true on the before_destroy method. Try this:
Child:
belongs_to :parent
before_destroy :prevent_destroy
attr_accessor :destroyed_by_parent
...
private
def prevent_destroy
if !destroyed_by_parent
self.errors[:base] << "You may not delete this child."
return false
end
end
Parent:
has_many :children, :dependent => :destroy
before_destroy :set_destroyed_by_parent, prepend: true
...
private
def set_destroyed_by_parent
children.each{ |child| child.destroyed_by_parent = true }
end
We had to do this because we're using Paranoia, and dependent: delete_all
would hard-delete rather than soft-delete them. My gut tells me there's a better way to do this, but it's not obvious, and this gets the job done.