自定义验证器获取时间对象但需要字符串

时间:2014-10-27 15:34:05

标签: ruby-on-rails activerecord

在我的Rails 4.1.6项目中,我有一个带有时间戳的数据库表:

create_table "jobs", force: true do |t|
  ...
  t.timestamp "run_time",             limit: 6
  ...
end

该模型包含该字段的自定义验证:

class Job < ActiveRecord::Base
  ...
  validates :run_time, iso_time: true
  ...
end

自定义验证器是:

require "time"

class IsoTimeValidator < ActiveModel::EachValidator

  def validate_each(record, attribute, value)
    p [value.class, value] #DEBUG
    errors = []
    unless Iso_8601.valid?(value)
      errors << "is not an ISO-8601 time"
    else
      if options[:time_zone]
        if Iso_8601.has_time_zone?(value) != options[:time_zone]
          errors << [
            "should",
            ("not" unless options[:time_zone]),
            "have time zone"
          ].compact.join(' ')
        end
      end
    end
    set_errors(record, attribute, errors)
  end

  private

  def set_errors(record, attribute, errors)
    unless errors.empty?
      if options[:message]
        record.errors[attribute] = options[:message]
      else
        record.errors[attribute] += errors
      end
    end
  end

end

这个验证器不起作用,因为Rails没有通过它 属性的原始字符串值。相反,Rails转换了 在调用验证程序之前将字符串转换为时间对象。如果是字符串 无法转换,它将nil传递给验证器:

Job.new(run_time: "ABC").save
# [nilClass, nil]

如果可以转换字符串,它会将时间对象传递给 验证器:

Job.new(run_time: "01/01/2014").save
# [ActiveSupport::TimeWithZone, Wed, 01 Jan 2014 00:00:00 UTC +00:00]

验证时间戳属性时,如何自定义验证器 是否可以访问属性的原始字符串值?

1 个答案:

答案 0 :(得分:1)

你试过run_time_before_type_cast吗?

在您的验证器中,您可以使用record.send "#{attribute}_before_type_cast"

之类的内容