Xác thực sự hiện diện của trường này hay trường khác (XOR)


91

Làm cách nào để xác thực sự hiện diện của trường này hay trường khác nhưng không phải cả hai và ít nhất một trường?

Câu trả lời:


154

Mã của bạn sẽ hoạt động nếu bạn thêm các điều kiện vào xác thực số như sau:

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

Các chức năng hoạt động tuyệt vời. Nhưng, tôi không thể nhận được lỗi hiển thị trên trang biểu mẫu. Trừ khi tôi làm điều gì đó như ´ = @ bill.errors [: base] [0] `trên _form.slim của tôi. Bất kỳ đề xuất?
bir_ham

45

Tôi nghĩ điều này dễ thành ngữ hơn trong Rails 3+:

ví dụ: Để xác thực rằng một trong số user_namehoặc emailhiện tại:

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

27
Điều này không xử lý "không phải cả hai" Tiêu chí
Paul 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

Bạn thậm chí có thể làm điều này với 3 giá trị trở lên:

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

10

Ví dụ cho đường ray 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

#Father Họ hoặc Họ của Mẹ là bắt buộc

 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

Hãy thử ví dụ đơn giản ở trên.


1

Tôi đặt câu trả lời của tôi cho câu hỏi này dưới đây. Trong ví dụ này :description:keywordslà các trường mà một trong số này không được để trống:

  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

Xác thực bằng Proc hoặc Biểu tượng với: if và: trừ khi sẽ được gọi ngay trước khi xác thực xảy ra.

Vì vậy, sự hiện diện của một trong cả hai trường có thể như thế này:

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

Mã (đoạn mã ví dụ) có :ifhoặc :unlesslà mục mới nhất, tuy nhiên như được khai báo trong tài liệu, mã sẽ được gọi ngay trước khi xác thực xảy ra - vì vậy, một kiểm tra khác sẽ hoạt động sau, nếu điều kiện khớp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.