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.