0

我有一个继承自 ActiveRecord::Base 的 Commentable 类和一个继承自 Commentables 的 Event 类。

我已经覆盖了这两个类中的销毁方法,并且 Event.distroy 调用了 super。然而,一些意想不到的事情发生了。具体来说,事件的 has_and_belongs_to_many 关联被删除。我认为这是因为某些模块被包含在 Commentables 和 Event 类之间,但不确定是否有办法阻止这种情况。

这是简化的代码:

class Commentable < ActiveRecord::Base
  has_many :comments

  def destroy
    comments.destroy_all
    self.deleted = true
    self.save!
  end

end

class Event < Commentable
  has_and_belongs_to_many :practitioners, :foreign_key => "commentable_id"

  def destroy
    #some Event specific code
    super
  end

end

我不想从数据库中删除行,只需设置一个“已删除”标志。我也不想删除任何关联。但是,在 Event.destroy 和 Commentable.destroy 之间的某个地方,其他一些 rails 代码会破坏 has_and_belongs_to_many 表中的记录。

知道为什么会发生这种情况以及如何阻止它吗?

4

2 回答 2

5

您实际上不必在Commentable模型上覆盖destroy,只需添加一个before_destroy回调false即可实际取消destroy调用。例如:

class Commentable < ActiveRecord::Base
 # ... some code ...
  before_destroy { |record|
    comments.destroy_all
    self.deleted = true
    self.save!
    false
  }
 # ... some code ...
 end

模型也是如此Event;只需添加一个回调而不覆盖destroy方法本身。

更多关于可用回调的信息在这里

于 2012-12-02T07:54:26.497 回答
0

false如果返回,Rails 5 不会停止回调链。我们将不得不使用throw(:abort)

before_destroy :destroy_validation

def destroy_validation
  if condition
    errors.add(:base, "item cannot be destroyed because of the reason...")
    throw(:abort)
  end
end

在 Rails 5 之前,false从任何before_ callbackin ActiveModel or ActiveModel::Validations, ActiveRecord&返回ActiveSupport导致回调链停止。

我们可以通过将此配置更改为 来关闭此默认行为true。但是,当false从回调返回时,Rails 会显示弃用警告。

新的 Rails 5 应用程序带有一个名为callback_terminator.rb.

ActiveSupport.halt_callback_chains_on_return_false = false

默认情况下,该值设置为false

=> DEPRECATION WARNING: Returning `false` in Active Record and Active Model callbacks will not implicitly halt a callback chain in the next release of Rails. To explicitly halt the callback chain, please use `throw :abort` instead.
ActiveRecord::RecordNotSaved: Failed to save the record

这是一个受欢迎的更改,有助于防止回调意外停止。

于 2020-01-23T16:32:03.937 回答