验证一个字段或另一个字段的存在(XOR)


Answers:


154

如果将条件添加到数字验证中,则代码将正常工作,如下所示:

class Transaction < ActiveRecord::Base
    validates_presence_of :date
    validates_presence_of :name

    validates_numericality_of :charge, allow_nil: true
    validates_numericality_of :payment, allow_nil: true


    validate :charge_xor_payment

  private

    def charge_xor_payment
      unless charge.blank? ^ payment.blank?
        errors.add(:base, "Specify a charge or a payment, not both")
      end
    end

end

该功能很好用。但是,我无法获得表单页面上显示的错误。除非我在_form.slim上执行类似于´= @ invoice.errors [:base] [0]`的操作。有什么建议?
bir_ham

45

我认为这在Rails 3+中更常见:

例如:用于验证user_nameemail存在以下一种:

validates :user_name, presence: true, unless: ->(user){user.email.present?}
validates :email, presence: true, unless: ->(user){user.user_name.present?}

27
这不处理“不是两个”标准
保罗Pettengill

11
class Transaction < ActiveRecord::Base
    validates_presence_of :date
    validates_presence_of :name

    validates_numericality_of :charge, allow_nil: true
    validates_numericality_of :payment, allow_nil: true


    validate :charge_xor_payment

  private

    def charge_xor_payment
      if [charge, payment].compact.count != 1
        errors.add(:base, "Specify a charge or a payment, not both")
      end
    end

end

您甚至可以使用3个或更多值来执行此操作:

if [month_day, week_day, hour].compact.count != 1

10

导轨示例3。

class Transaction < ActiveRecord::Base
  validates_presence_of :date
  validates_presence_of :name

  validates_numericality_of :charge, :unless => proc{|obj| obj.charge.blank?}
  validates_numericality_of :payment, :unless => proc{|obj| obj.payment.blank?}


  validate :charge_xor_payment

  private

    def charge_xor_payment
      if !(charge.blank? ^ payment.blank?)
        errors[:base] << "Specify a charge or a payment, not both"
      end
    end
end

2
 validate :father_or_mother

#父亲姓或母亲姓是强制性的

 def father_or_mother
        if father_last_name == "Last Name" or father_last_name.blank?
           errors.add(:father_last_name, "cant blank")
           errors.add(:mother_last_name, "cant blank")
        end
 end

尝试上面的简单示例。


1

我在下面回答这个问题。在此示例中,:description并且:keywords是其中一个不为空的字段:

  validate :some_was_present

  belongs_to :seo_customable, polymorphic: true

  def some_was_present
    desc = description.blank?
    errors.add(desc ? :description : :keywords, t('errors.messages.blank')) if desc && keywords.blank?
  end

1

使用Proc或Symbol与:if和:unless进行验证进行的验证将在验证发生之前立即调用。

因此,两个字段之一的状态可能是这样的:

validates :charge,
  presence: true,
  if: ->(user){user.charge.present? || user.payment.present?}
validates :payment,
  presence: true,
  if: ->(user){user.payment.present? || user.charge.present?}

(示例代码段)代码具有:if:unless作为最新项目,但是如doc中所声明的那样,它将在验证发生之前立即被调用-因此,如果条件匹配,则将在之后进行另一项检查。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.