我有一个Active Record模型,其中包含属性:expiry_date。我如何进行验证,使其在今天(当时的当前日期)之后?我对Rails和ruby完全不熟悉,我找不到类似的问题来回答这个问题吗?
我正在使用Rails 3.1.3和ruby 1.8.7
答案 0 :(得分:63)
您的问题(几乎)完全回答in the Rails guides。
这是他们给出的示例代码。此类验证日期是在过去,而您的问题是如何验证日期是否在 future ,但是调整它应该非常简单:
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
答案 1 :(得分: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
在你的模特中:
validates :signed_date, not_in_past: true
答案 2 :(得分:3)
我接受了@dankohn的回答,并更新为I18n准备好了。我还删除了blank
测试,因为这不是此验证程序的责任,可以通过将presence: true
添加到验证调用来轻松启用。
更新的类,现在命名为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
现在将in_future
密钥添加到您的本地化文件中。
对于errors.messages.in_future
下的所有字段,例如对于荷兰人:
nl:
errors:
messages:
in_future: 'moet in de toekomst zijn'
或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'
答案 3 :(得分:3)
在Rails 4+中,有future?
个对象的past?
和DateTime
方法,因此更简单的答案是
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.past?
errors.add(:expiration_date, "can't be in the past")
end
end
end
答案 4 :(得分:2)
最简单且最有效的解决方案是使用Rails的内置验证。只需验证它:
validates :expiry_date, inclusion: { in: (Date.today..Date.today+5.years) }