Rails:验证大于另一个的日期

pif*_*ffy 6 ruby validation ruby-on-rails date

我正在ActiveRecord中编写自定义验证器,以便截止日期有意义:

  validate :deadline_is_possible?

  def deadline_is_possible?
    if deadline > begins_at
      errors.add(:deadline, 'must be possible')
    end
  end
Run Code Online (Sandbox Code Playgroud)

然而,这会为nil:NilClass生成"NoMethodError:undefined method`>'.我事件试图将日期变成字符串,如:

  def deadline_is_possible?
    if deadline.to_s > begins_at.to_s
      errors.add(:deadline, 'must be possible')
    end
  end
Run Code Online (Sandbox Code Playgroud)

虽然它不会产生错误,但也不起作用.

我还宣布了其他验证者(例如

  def begins_at_is_date?
    if !begins_at.is_a?(Date)
      errors.add(:begins_at, 'must be a date')
    end
  end
Run Code Online (Sandbox Code Playgroud)

工作还可以.

小智 14

您可以使用比较:

   validates :deadline, comparison: { greater_than: :begins_at }
Run Code Online (Sandbox Code Playgroud)

文档: https: //guides.rubyonrails.org/active_record_validations.html#comparison

  • 这仅出现在 Rails 7 上...:-/ (5认同)

Jes*_*ott 9

如果其中一个日期为零,您可能需要处理。您可以将这些设置为截止日期数据库中的默认值,或者执行以下操作:

  validate :deadline_is_possible?

  def deadline_is_possible?
    return if [deadline.blank?, begins_at.blank?].any?
    if deadline > begins_at
      errors.add(:deadline, 'must be possible')
    end
  end
Run Code Online (Sandbox Code Playgroud)


Kri*_*ris 9

您可以添加自己的验证器:

class AfterDateValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    return if value.blank?

    other_date = record.public_send(options.fetch(:with))

    return if other_date.blank?

    if value < other_date
      record.errors.add(attribute, (options[:message] || "must be after #{options[:with].to_s.humanize}"))
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

并在模型中使用它:

validates :invited_on, presence: true
validates :selected_on, presence: true, after_date: :invited_on
Run Code Online (Sandbox Code Playgroud)