Rails - Cancel destroy on before_destroy callback

Rails wraps saves and destroys in a transaction, so a raise in the callback would work:

class Post < ActiveRecord::Base
  before_destroy :saveable?

  def saveable?
    if true
      raise "Destroy aborted; you can't do that!"
    end
  end
end

Substitute true for your condition.

Here's the abridged console output:

[1] pry(main)> Post.first.id
=> 1
[2] pry(main)> Post.first.destroy
RuntimeError: Destroy aborted; you can't do that!
[3] pry(main)> Post.first.id
=> 1

Documentation


As none of the given answers really solves the problem, but the comment above tells it - here the in form of an answer to make it easy to find:

In rails 5, instead of

before_destroy do
  if self.some_condition?
    return false
  end
end

use

before_destroy do
  if self.some_condition?
    throw(:abort)
  end
end

to make sure destroy is not being perfomed.

thanks to RFVoltolini's comment - this saved my day!


You should return false.

Rails 5

"Canceling callbacks

If a before_* callback throws :abort, all the later callbacks and the associated action are cancelled."

Rails 4 and lower

"Canceling callbacks

If a before_* callback returns false, all the later callbacks and the associated action are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks defined as methods on the model, which are called last."

Source