如何在activerecord中实现动态验证

时间:2015-12-15 22:20:29

标签: ruby-on-rails validation activerecord

根据参数或操作调整模型验证的最佳方法是什么?假设我正在进入系统领域,所以所需要的只是基本的联系信息。但后来我可能会为该用户输入一份新合同,此时我需要更详细的信息。因此,我只需要输入一个潜在客户就可能需要电话号码,但一旦他们签订合同,我可能需要他们的生日和备用电话号码。

我考虑使用状态机,但用户实际上可以同时签订两份合同,因此状态对这种情况并不起作用。

我还考虑过将额外信息存储在合同中,但由于用户可以拥有多个合同,因此需要与用户共同使用,这样才不会多余。

所以基本上在保存合同时,如果所述用户没有额外的字段,它会告诉我附加用户无效。

3 个答案:

答案 0 :(得分:4)

您可以使用conditional validation例如:

validates_presence_of :phone, :if => Proc.new { |p| p.lead? }

答案 1 :(得分:3)

结帐conditional validations

class Person
  validates_presence_of :given_name, family_name

  validates_presence_of :phone_number, :email_address, :if => :registered

  with_options :if => :registered do |person|
    # validations in this block are scoped to a registered user
    person.validates_presence_of :dob
  end

end

:if选项可以:

  • 对应于评估为true或false的类的方法的符号
  • 一个proc或lambda,它返回一个计算结果为true或false的值
  • 包含红宝石代码的字符串(上帝知道你为什么要这样做)

您还可以访问以类似方式工作的:unless选项。

您还可以封装逻辑以确定用户的当前状态,并使用它来确定您可以采取的验证步骤:

class Person

  validates_presence_of :email_address, :if => ->(p) { p.state == :pending_confirmation }

  # I actually prefer validations in this format
  validate do # stricter validations when user is confirming registration
    if confirming_membership && (given_name.blank? || family_name.blank?
      errors.add(:base, 'A full name is required')
    end
  end

  def state
    # your logic could be anything, this is just an example
    if self.confirmed_email
      :registered
    elsif confirming_membership
      :pending_confirmation
    else
      :new_user
    end
  end

  def confirming_membership
    # some logic
  end
end

答案 2 :(得分:1)

无论领导发布什么行动,你都可以这样做:

@object.save(validate: false)

然后,当他们需要输入合同时,请不要使用validate: false选项以确保运行这些验证。

另外,如果您只想跳过某些验证,请参阅this post