Rails模型上的无效日期时间结果为零

时间:2012-10-23 18:08:20

标签: ruby-on-rails ruby-on-rails-3 validation activerecord

我有一个带有datetime属性的模型。我正在尝试验证将更新模型的传入JSON。但是ActiveRecord似乎是将属性的值设置为nil,如果它是无效的日期时间。我无法回复相应的错误,因为该属性被允许为零。我做错了什么?

代码:

class DatetimeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    value.to_datetime rescue record.errors[attribute] << (options[:message] || "must be a date.")
  end
end

class Foo
   # column :my_date, :datetime
   validates :my_date, :allow_nil => true, :datetime => true
end

控制台:

1.9.3p125 :001 > x = Foo.new
=> #<Foo id: nil, my_date: nil>
1.9.3p125 :001 > x.my_date = 'bad value'
=> 'bad value'
1.9.3p125 :001 > x.my_date
=> nil
1.9.3p125 :001 > x.valid?
=> true

就ActiveRecord而言,将datetime属性设置为'bad_value'相当于将其设置为nil,因此我无法对其进行验证,因为不需要my_date。这对我来说似乎是个错误。什么是最好的解决方法?

谢谢!

1 个答案:

答案 0 :(得分:10)

一种解决方法是将allow_nil部分移至date_time验证:

class DatetimeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    return if value.blank?
    value.to_datetime rescue record.errors[attribute] << (options[:message] || "must be a date.")
  end
end

class Foo
  validates :my_date, :datetime => true
end

编辑:我认为这是类型转换的问题 - 试试这个(改编自validates :numericality的代码):

def validate_each(record, attribute, value)
  before_type_cast = "#{attribute}_before_type_cast"

  raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast.to_sym)
  raw_value ||= value

  return if raw_value.blank?
  raw_value.to_datetime rescue record.errors[attribute] << (options[:message] || "must be a date.")
end