【问题标题】:rails built in datetime validation内置日期时间验证的rails
【发布时间】:2010-11-25 03:35:30
【问题描述】:

rails 是否对日期时间进行任何验证?我找到了一个插件 http://github.com/adzap/validates_timeliness/tree/master, 但它似乎应该开箱即用。

【问题讨论】:

  • 我爱validates_timeliness。它可以作为 gem 安装。安装速度与复制粘贴所选答案的速度差不多。

标签: ruby-on-rails validation


【解决方案1】:

DateTimes 没有内置的 ActiveRecord 验证器,但您可以轻松地将这种功能添加到 ActiveRecord 模型中,而无需使用插件,如下所示:

class Thing < ActiveRecord::Base
  validate :happened_at_is_valid_datetime

  def happened_at_is_valid_datetime
    errors.add(:happened_at, 'must be a valid datetime') if ((DateTime.parse(happened_at) rescue ArgumentError) == ArgumentError)
  end
end

【讨论】:

  • 我很高兴这有帮助。这不是最出色的代码,但它确实有效。
  • 谢谢,太好了。尝试过validates_timeliness,但在使用 getter 和 setter 时遇到了问题。这非常有效。
  • 为什么不:DateTime.parse(happened_at) rescue errors.add(:happened_at, 'must be a valid datetime')?拯救 ArgumentError 只是为了检查它是否是 ArgumentError 对我来说没有多大意义。
  • 一般不会根据数据库的列进行typecast吗?这不是不必要的吗?
  • 如果你得到这个no implicit conversion of ActiveSupport::TimeWithZone into String,试试to_sDateTime.parse(happened_at.to_s)
【解决方案2】:

Gabe 的回答对我没有用,所以这是我为验证我的日期所做的:

class MyModel < ActiveRecord::Base
  validate :mydate_is_date?

  private

  def mydate_is_date?
    if !mydate.is_a?(Date)
      errors.add(:mydate, 'must be a valid date') 
    end
  end
end

我只是想验证日期实际上是一个日期,而不是字符串、字符、int、float 等......

更复杂的日期验证可以在这里找到:https://github.com/codegram/date_validator

【讨论】:

  • gem 是最简单的解决方案,我花了三分钟实现。不值得写任何代码。
  • @MichaelSchmitz - 值得编写代码,因为代码是不言自明的 - 查看代码的新人可能不知道 gem 的存在,它增加了简单任务的额外开销。跨度>
  • @Toby - 感谢您的指点,您是对的。我是目前唯一的开发人员,我想我很高兴它的工作。
  • 这只是验证对象是日期的实例,但它可以是 nil,甚至是无效的日期。
  • 并且 gem 不是开销,否则你将不得不在每个模型中重写你的方法。
【解决方案3】:

Rails 的最新版本将在验证之前将 type cast 值,因此无效值将作为 nils 传递给自定义验证器。我正在做这样的事情:

# app/validators/date_time_validator.rb
class DateTimeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if record.public_send("#{attribute}_before_type_cast").present? && value.blank?
      record.errors.add(attribute, :invalid)
    end
  end
end
# app/models/something.rb
class Something < ActiveRecord::Base
  validates :sold_at, date_time: true
end
# spec/models/something_spec.rb (using factory_girl and RSpec)
describe Something do
  subject { build(:something) }

  it 'should validate that :sold_at is datetimey' do
    is_expected.not_to allow_value(0, '0', 'lorem').for(:sold_at).with_message(:invalid)
    is_expected.to allow_value(Time.current.iso8601).for(:sold_at)
  end
end

【讨论】:

    【解决方案4】:

    您可以自己创建自定义日期时间验证器

    1) 在 app 目录中创建一个名为 validators 的文件夹

    2) 创建一个文件 datetime_validator.rb。在 app/validators 目录中包含以下内容

     class DatetimeValidator < ActiveModel::EachValidator
      def validate_each(record, attribute, value)
        if ((DateTime.parse(value) rescue ArgumentError) == ArgumentError)  
          record.errors[attribute] << (options[:message] || "must be a valid datetime")
        end
      end
    end
    

    3) 将此验证应用于模型

    class YourModel < ActiveRecord::Base
      validates :happend_at, datetime: true
    end
    

    4) 在 application.rb 中添加以下行

    config.autoload_paths += %W["#{config.root}/app/validators/"]
    

    5) 重新启动您的 Rails 应用程序

    注意:上述方法在rails 4中测试过

    【讨论】:

    • 我个人认为DateTimeValidator(大写T)因为它是DateTime你正在验证。从constantize 的角度来看更有意义。
    【解决方案5】:

    我推荐一颗宝石date_validator。见https://rubygems.org/gems/date_validator。它维护良好,API 简单紧凑。

    【讨论】:

    • 请注意所有到达这里的人,几年过去了......这个 gem 不会验证数据库中作为字符串支持的日期:github.com/codegram/date_validator/issues/38 并且是 loosley mantained(请参阅 PR 待定)
    【解决方案6】:

    验证日期是非常必要的。使用默认的 Rails 表单助手,您可以选择像 9 月 31 日这样的日期。

    【讨论】:

    • 通过表单验证用户输入是一个好的开始,但问题的上下文表明 OP 询问的是 Rails 模型验证。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    相关资源
    最近更新 更多