验证运行后但在保存之前,如何将模型实例设置为无效?

时间:2009-11-09 12:43:44

标签: ruby-on-rails activerecord callback

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

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 在验证其存在之前使用。

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

2 个答案:

答案 0 :(得分: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来处理未定义大小的故障情况。

答案 1 :(得分:0)

我假设您希望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