首页 > 解决方案 > Rails 5 throw(:abort) 中的 before_destroy 回调,但也修改了记录

问题描述

在 Rails 5 中,我相信防止破坏的唯一方法是调用throw(:abort); 这正在按预期工作。但是,我遇到的问题是,如果记录不符合要求,而不是销毁它,我想修改记录。然而,throw(:abort) 整个事务被还原,撤消记录收到的任何更改。

关于如何实现这一目标的任何建议?

class Thing < ApplicationRecord

  before_destroy :can_destroy?

  private

  def can_destroy?
    if model.something?
      self.update(something: 'foo') # This part is not being retained.
      throw(:abort)
  end
end

标签: callbackruby-on-rails-5

解决方案


您遇到的问题是 ActiveRecord 将所有之前/之后的回调包装在事务中,以确保如果其中任何一个失败,则不会将任何结果提交给数据库。可悲的是,你想做的正是它试图保护你免受伤害的事情。这样做并没有真正的“好”方法(我知道),但是绕过这个限制的一些技巧是在after_rollback回调中进行更新,因为你throw(:abort)会导致事务回滚。例如:

class Thing < ApplicationRecord

  before_destroy :can_destroy?
  after_rollback :can_destroy_callbacks
  private

  def can_destroy?
    if model.something?
      @update_later = true
      throw(:abort)
    end
  end

  def can_destroy_callbacks
    if @update_later
      update(something: 'foo')
    end
  end
end

推荐阅读