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?
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:
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
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_name
hoặc email
hiện tại:
validates :user_name, presence: true, unless: ->(user){user.email.present?}
validates :email, presence: true, unless: ->(user){user.user_name.present?}
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
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
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
và :keywords
là 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
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ó :if
hoặc :unless
là 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.