如何通过与空白值进行比较来验证?

How to validate with comparison against a blank value?

我有一个 Rails ActiveModel,它有两个字段 date_fromdate_to,我希望模型在(且仅在)

时有效

换句话说,只有当两个字段都设置但顺序错误时,模型才应该无效。在那种情况下,我还希望 both 字段被标记为无效。

我试过

validates :date_from, comparison: { less_than_or_equal_to: :date_to }, allow_blank: true
validates :date_to, comparison: { greater_than_or_equal_to: :date_from }, allow_blank: true

但是当其中一个字段设置为

时失败
#<ActiveModel::Error attribute=date_to, type=comparison of Date with nil failed, options={}>

referenced字段为空时,如何使比较验证通过?

可以使用两个单独的 validates 调用来完成,方法是添加带有 if 选项的条件检查

validates :date_from, 
  comparison: { less_than_or_equal_to: :date_to },
  allow_blank: true,
  if: :date_to # make sure `date_to` is not `nil`

validates :date_to,
  comparison: { greater_than_or_equal_to: :date_from },
  allow_blank: true,
  if: :date_from

如果其中一个日期是 nil,这将跳过这些验证。当两个日期都存在时,它会运行两个验证并添加两个单独的错误,这可能不太正确,因为它本质上是一个错误。

为了使此验证的意图更加明显,validate 方法更合适

validate :date_from_is_less_than_date_to

def date_from_is_less_than_date_to
  return unless date_from && date_to # valid if date(s) are missing

  unless date_from < date_to
    errors.add(:base, 'Date range is invalid')

    # NOTE: to add errors to show on form fields
    # errors.add(:date_from, 'must come before Date to')
    # errors.add(:date_to, 'must come after Date from')

    # NOTE: to add errors only for date that changed
    #       requires ActiveModel::Dirty
    # errors.add(:date_from, 'must come before Date to') if date_from_changed?
    # errors.add(:date_to, 'must come after Date from')  if date_to_changed?
  end
end