Rails - 在before_destroy回调时取消销毁

问题描述 投票:11回答:5

有什么办法,在某些条件下,取消对活动记录的before_destroy回调中的对象的销毁?谢谢

ruby-on-rails activerecord
5个回答
24
投票

你应该返回false

Rails 5

“取消回调

如果before_ *回调抛出:abort,则取消所有后续回调和相关操作。“

Rails 4 and lower

“取消回调

如果before_ *回调返回false,则取消所有后续回调和相关操作。回调通常按照定义的顺序运行,但定义为模型上的方法的回调除外,这些回调最后被称为。

Source


3
投票

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

Documentation


3
投票

返回false是正确的方法:

before_destroy do
  if self.some_condition?
    return false
  end
end

你可以在点6 Halting Execution下看到这里的文档。 http://guides.rubyonrails.org/active_record_callbacks.html


2
投票

由于没有一个给定的答案真正解决了问题,但上面的评论告诉它 - 这里以答案的形式使其易于查找:

在轨道5中,而不是

before_destroy do
  if self.some_condition?
    return false
  end
end

使用

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

确保不进行破坏。

感谢RFVoltolini's comment - 这节省了我的一天!


0
投票

您还可以覆盖#destroy方法:

def destroy
  study_assignments.empty? ? super : self
end
© www.soinside.com 2019 - 2024. All rights reserved.