如何在今天的Rails中验证日期?

cod*_*res 39 ruby validation ruby-on-rails

我有一个包含属性的Active Record模型:expiry_date.我如何进行验证,使其在今天(当时的当前日期)之后?我对Rails和ruby完全不熟悉,我找不到类似的问题来回答这个问题?

我正在使用Rails 3.1.3和ruby 1.8.7

apn*_*ing 66

您的问题(几乎)在Rails指南中完全回答.

这是他们给出的示例代码.此类验证日期是否已过去,而您的问题是如何验证日期是否在将来,但调整它应该非常简单:

class Invoice < ActiveRecord::Base
  validate :expiration_date_cannot_be_in_the_past

  def expiration_date_cannot_be_in_the_past
    if expiration_date.present? && expiration_date < Date.today
      errors.add(:expiration_date, "can't be in the past")
    end
  end    
end
Run Code Online (Sandbox Code Playgroud)


Dan*_*ohn 18

这是设置自定义验证器的代码:

#app/validators/not_in_past_validator.rb
class NotInPastValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if value.blank?
      record.errors.add attribute, (options[:message] || "can't be blank")
    elsif value <= Time.zone.today
      record.errors.add attribute,
                        (options[:message] || "can't be in the past")
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

在你的模型中:

validates :signed_date, not_in_past: true
Run Code Online (Sandbox Code Playgroud)

  • 我认为`in_future`更好 (5认同)

Koe*_*en. 5

我接受了@dankohn 的回答,并更新为 I18n 准备就绪。我还删除了blank测试,因为这不是此验证器的责任,并且可以通过添加presence: true到 validates 调用轻松启用。

更新的类,现在命名为in_future,我认为它比not_in_past

class InFutureValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors.add(attribute, (options[:message] || :in_future)) unless in_future?(value)
  end

  def in_future?(date)
    date.present? && date > Time.zone.today
  end
end
Run Code Online (Sandbox Code Playgroud)

现在将in_future密钥添加到您的本地化文件中。

对于 下的所有字段errors.messages.in_future,例如荷兰语:

nl:
  errors:
    messages:
      in_future: 'moet in de toekomst zijn'
Run Code Online (Sandbox Code Playgroud)

或每场下activerecord.errors.models.MODEL.attributes.FIELD.in_future,例如用于end_date在一个Vacancy在荷兰的模型:

nl:
  activerecord:
    errors:
      models:
        vacancy:
          attributes:
            end_date:
              in_future: 'moet in de toekomst zijn'
Run Code Online (Sandbox Code Playgroud)


小智 5

最简单有效的解决方案是使用 Rails 的内置验证。只是像这样验证它:

validates :expiry_date, inclusion: { in: (Date.today..Date.today+5.years) }
Run Code Online (Sandbox Code Playgroud)

  • 注意 - 这些日期将固定在代码加载时(即 rails 实例启动) (12认同)
  • 然后替换为`in: -&gt;(date) { (Date.today..Date.today+5.years) }` (10认同)
  • 使用 ruby​​ 2.6 可以是```in: -&gt;(date) { (Date.today..) }``` (3认同)
  • 使用 shoulda_matchers 进行测试时,请使用 allowed_value 而不是 validates_inclusion_of,因为它们无法获取范围的最大值。 (2认同)