【问题标题】:How do I set a model instance as invalid after validations are run but before it's saved?如何在运行验证后但在保存之前将模型实例设置为无效?
【发布时间】:2009-11-09 12:43:44
【问题描述】:

我有一个标准的活动记录模型,其中包含所需的属性:

class Sample < ActiveRecord::Base
  has_many :colors

  before_validation :grab_colors

  validates_presence_of :size
  validate :number_of_colors

  private

  def grab_colors
    # grab x number of colors | x = size
  end

  def number_of_colors
    self.errors.add("size","is to large.") if colors.count < size
  end
end

我的问题是 grab_colors 方法需要 size 属性,但执行的结果也需要验证。在上面的例子中 size 在它的存在被验证之前被使用。

我可以将实例设置为无效并在所有验证完成后停止保存过程吗?

【问题讨论】:

    标签: ruby-on-rails activerecord callback


    【解决方案1】:

    有几种方法可以做到这一点,但它们都涉及重写 grab_colors 以执行 validates_presence_of 检查。

    您正在设置 before_validation 回调。任何返回 false 的回调都将取消其余的事务。因此,您需要自行处理导致grab_colors 失败的情况。本质上,您要求的是这样的:

    def grab_colors
      unless size.blank?
        # grab x number of colors | x = size
      else
        errors.add(:size, "cannot be empty.")
        return false
      end
    end
    

    这会将您的自定义 before_validation 与 validates_presence_of 合并。当 size 不存在时,grab_colors 将设置错误并返回 false,取消剩余的事务,因此您的标准验证永远不会执行。从你提到的唯一一次失败是在未设置大小时。

    您还可以通过让 number_of_colors 调用 grab_colors 而不是调用 grab_colors 作为 before_validation 来实现您想要的效果。但是,您仍然需要调整 grab_colors 以处理未定义大小的故障情况。

    【讨论】:

      【解决方案2】:

      我假设您希望 number_of_colors 方法在 grab_colors 方法之后运行。在这种情况下,我建议从 validate 方法按顺序调用这两种方法。

      def validate
        unless size.blank?
          grab_colors 
          number_of_colors
        end
      end
      

      大小的验证仍由

      处理
      validates_presence_of :size
      

      但如果你有大小,那么 grab_colorsnumber_of_colors 运行。现在你不需要这些行了

      before_validation :grab_colors
      validate :number_of_colors
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-21
        • 2013-09-26
        • 2018-07-03
        • 2010-10-02
        • 2015-11-16
        • 1970-01-01
        相关资源
        最近更新 更多