【问题标题】:Rails 4: How to cancel save on a "before_save" callback?Rails 4:如何取消“before_save”回调的保存?
【发布时间】:2014-05-23 20:04:01
【问题描述】:

我有复杂的模型/表格。我不想重复记录,所以我想合并具有相似属性的记录。如何使用 before_save 回调取消“保存”?这就是我的想法:

class ProductsColor < ActiveRecord::Base


  before_save :check_for_similar_record

  def check_for_similar_record
    if ProductsColor.exist?(color_id: self.color_id, product_id: self.product_id)
      # merge values with existing ProductsColor and stop self from saving
    end
  end

end

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    导轨 5

    As of Rails 5,您可以通过在回调中显式调用throw :abort 来表示应该中止操作。 cancelling callbacks(现在)的文档部分指出:

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

    transactions 的以下部分继续:

    如果before_* 回调取消操作,则发出ROLLBACK。您还可以在任何回调中触发ROLLBACK 引发异常,包括after_* 挂钩。

    导轨 4

    这个故事与 Rails 5 非常相似,只是回调应该返回 false。 the documentation的对应部分很有帮助

    如果 before_* 回调返回 false,则取消所有后续回调和相关操作。如果 after_* 回调返回 false,则后面的所有回调都将被取消。

    紧随其后

    如果 before_* 回调取消操作,则发出 ROLLBACK。您还可以触发 ROLLBACK 在任何回调中引发异常,包括 after_* 挂钩。

    【讨论】:

    • 另见:Rails 5 throw abort : 如何设置错误消息? stackoverflow.com/questions/38625276/…
    • 如果你想让它静默不保存怎么办?例如防止关联表中的重复关联。在这种情况下不需要抛出错误...... Rails 5
    • 为了实现你必须做类似condition ? true : throw(:abort)
    • 如果我想要自定义消息怎么办?我使用raise ActiveRecord::RecordNotSaved, 'Record already exists'...为了使其更具可读性,我创建了一个新类ActiveRecord::RecordExists = Class.new(ActiveRecord::ActiveRecordError)(用于初始化程序),然后是raise ActiveRecord::RecordExists, 'The record already exists'
    • @S.Goswami 这是错误的做法。如果你想要自定义错误消息,你应该使用验证。
    【解决方案2】:

    为防止记录被保存,您只需返回false:

    def check_for_similar_record
      if ProductsColor.exists?(color_id: self.color_id, product_id: self.product_id)
        # merge values
        false
      else
        true
      end
    end
    

    【讨论】:

    • 如果返回 nil 记录仍然会保存,必须显式返回 false 才能取消保存。
    • 从 Rails 5 开始,这不再是正确的 - 有关详细信息,请参阅其他答案。
    • @JonGjengset 问题是“Rails 4:如何在“before_save”回调中取消保存?”。我是否得到了你的反对票?
    • 哦,对不起,你是对的,我完全错过了。撤消。我只是投了反对票,因为我认为答案不再正确,但显然我错了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多