【问题标题】:ActiveRecord: abort datetime parsing if value is invalidActiveRecord:如果值无效,则中止日期时间解析
【发布时间】:2026-02-22 11:45:02
【问题描述】:

我的 ActiveRecord 模型(在 Rails 中)中有一个日期时间字段,当日期字段超出范围时,我需要保护我的模型不崩溃。

我找到了this 的问题并尝试做出类似的做法:

class Something < ActiveRecord::Base
    validate :important_date_is_valid_datetime, on: :create
    validates :important_date, presence: true

private

    def important_date_is_valid_datetime
        if (DateTime.parse(important_date.to_s()) rescue ArgumentError) == ArgumentError then
            errors.add(:important_date, 'must be a valid datetime') 
        end
    end

end 

此代码可以“验证”日期时间字段,但如果 valie 超出范围,它不会中止字段解析:

irb(main):007:0> Something.new(important_date: "2015-20-40").valid?
ArgumentError: argument out of range
    from /home/shau-kote/.gem/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/values/time_zone.rb:350:in `initialize'
    from /home/shau-kote/.gem/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/values/time_zone.rb:350:in `new'
    from /home/shau-kote/.gem/ruby/2.1.0/gems/activesupport-4.2.0/lib/active_support/values/time_zone.rb:350:in `parse'
    ...

我可以防止类似的崩溃吗?

【问题讨论】:

    标签: ruby-on-rails datetime activerecord


    【解决方案1】:

    这是 Rails 4 的一个问题,在调用验证器之前就抛出异常。有一个pull request 带回了 Rails 3 的行为,其中无效日期只是 nil。这个拉取请求似乎被合并了,所以也许更新你的 Rails 版本已经可以解决问题了。

    与此同时,我可以想到两种解决方法:首先,您可以使用客户端验证,如果需要,当然可以对其进行篡改,但会保护用户以“善意”使用您的应用;其次,而不是使用验证在使用参数设置 datetime 属性之前,您可以在控制器中检查有效日期(或分别为 ArgumentError)。这两个选项都不是最佳的,但应该可以防止更多的崩溃。

    【讨论】:

    • 我有最新的 gem Rails 4.2.0,直到现在还有这个问题。这非常令人不快,但是您的“第二个解决方法”非常适合我的项目。谢谢。
    最近更新 更多