在我的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]
验证时间戳属性时,如何自定义验证器 是否可以访问属性的原始字符串值?
答案 0 :(得分:1)
你试过run_time_before_type_cast
吗?
在您的验证器中,您可以使用record.send "#{attribute}_before_type_cast"