Rails - Отменить уничтожить при обратном вызове before_destroy

существует ли какой-либо способ, если задано определенное условие, отменить уничтожение объекта в обратном вызове before_destroy активной записи? Благодаря

Ответ 1

Вы должны вернуть false.

Рельсы 5

"Отмена обратных вызовов

Если запрос before_ * callback отменяется: прерывание, все последующие обратные вызовы и связанное с ними действие отменены. "

Рельсы 4 и ниже

"Отмена обратных вызовов

Если обратный вызов before_ * возвращает false, все последующие обратные вызовы и связанное с ним действие отменены. Обратные вызовы обычно выполняются в том порядке, в котором они определены, за исключением обратных вызовов, определенных как методы на модели, которые называются последними.

Источник

Ответ 2

Обертки Rails сохраняют и уничтожают транзакцию, поэтому работает raise в обратном вызове:

class Post < ActiveRecord::Base
  before_destroy :saveable?

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

Подставьте true для вашего условия.

Здесь сокращенный вывод консоли:

[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

Документация

Ответ 3

Возврат false - это способ сделать это правильно:

before_destroy do
  if self.some_condition?
    return false
  end
end

Документацию можно посмотреть здесь в пункте 6 Halting Execution. http://guides.rubyonrails.org/active_record_callbacks.html

Ответ 4

Поскольку ни один из приведенных ответов действительно не решает проблему, но вышеупомянутый комментарий говорит об этом - здесь в форме ответа, чтобы его было легко найти:

В рельсах 5 вместо

before_destroy do
  if self.some_condition?
    return false
  end
end

использование

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

чтобы убедиться, что уничтожить не выполняется.

благодаря комментарию RFVoltolini - это спасло мой день!

Ответ 5

Вы также можете переопределить метод #destroy:

def destroy
  study_assignments.empty? ? super : raise("can not be destroyed")
end