在 Rails 模型中一起验证日期和时间字段

Posted

技术标签:

【中文标题】在 Rails 模型中一起验证日期和时间字段【英文标题】:Validate date and time fields together in rails model 【发布时间】:2012-04-14 21:44:51 【问题描述】:

编辑:如果下面的问题看起来有点“广泛”,总结是我只想在我的模型中组合一个日期字段和一个可选的时间字段,纯粹是为了使用日期验证器来验证它,但我当我传入一个字符串作为时间时,我的测试无法正确失败。


编辑 2:由于我仍在努力寻找将日期对象与时间对象连接以进行验证的方法,因此我想知道是否可以使用 is_a?(Time) 验证时间值是否为时间对象(而不是无效的字符串),但这似乎也不起作用,我想知道这是否是因为 Time mention with this method (但我不太了解它是否会导致问题。

我还想知道 to_time method 是否可以帮助我检查某个东西是否是 Time 对象,但我不确定如何。

希望有人可以建议如何将Date 对象与Time 对象连接以进行验证,或者至少告诉我如何检查提交的时间值是否为@987654330 @ 对象,而不是无效的字符串或其他东西。


编辑 3:我刚刚根据我找到的另一个答案尝试了以下操作,但它仍然没有抱怨测试中的“无效”字符串:

validate :start_time_is_time?, :if => "start_time.present?"

def start_time_is_time?
  unless start_time.is_a?(Time) || ((Time.parse(start_time) rescue ArgumentError) == ArgumentError)
    errors.add(:start_time, 'must be a valid time') 
  end
end

有什么理由可以将该字符串视为有效的Time


我有一个类似于Trying to set a variable in before_validation but it isn't working 的视图,该视图使用日历选择一天并使用下拉菜单选择时间。我尝试将相同的方法应用于我的模型,但由于我对 ruby​​ 有点陌生,并且无法填补答案留下的空白,因此无法让它工作。

我的模型有 start_date 和 start_time 字段。

我需要将这两个字段组合起来,以便我可以将它们一起验证为日期时间(使用 date_validator gem),而不必分别验证日期和时间,尽管它们将作为单独的字段进入数据库,除非否则有人可以说服我(尽管我已经分别对他们做了很多,所以我真的不想改变这一点)。

必须提交日期,但时间字段是可选的。

从另一个问题看来,我需要一个 before_validation 方法,该方法可以根据需要将 2 个字段组合成一个虚拟字段,然后我可以使用 date_validator gem 进行验证。

编辑:感谢 RyanJM,原始错误已得到纠正,但我仍然无法正确通过测试。以下是当前的游戏状态。

下面是我的 Showtime 模型的基础知识:

class Showtime < ActiveRecord::Base

  attr_accessible   :start_date, :start_time

  attr_accessor   :starting_at, :starting_time

  belongs_to :performance

  before_validation :construct_starting_at

  validates :start_date,  :presence => true,  :date =>  :after_or_equal_to => Proc.new  Date.today  
  validates :starting_at, :date =>  :after_or_equal_to => Proc.new  Time.now  , :if => "start_date.present? && start_time.present?"

  def construct_starting_at
    if start_date.present? && start_time.present?
      self.starting_time = self.start_time.strftime("%T")
      self.starting_at = DateTime.strptime("#start_date #starting_time", "%F %T")
    end
  end

end

如果需要,这里是性能模型的基础知识/相关部分:

class Performance < ActiveRecord::Base

  has_many :showtimes, :dependent => :delete_all
  accepts_nested_attributes_for :showtimes, :allow_destroy => true, :reject_if => lambda  |a| a[:start_date].blank? 

end

这是失败的测试:

require 'spec_helper'

describe Showtime do

  before(:each) do
    @attr = 
        :name => "Performance 1",
        :showtimes_attributes => 
              "0" => 
                  :start_date => Date.today+15.days,
                  :start_time => Time.now
              
        
    
  end

  it "should test that the start time is a valid time if it exists" do
    @attr_invalid = 
        "0" => 
            :start_date => Date.today+15.days,
            :start_time => "invalid"
        
    
    invalid = Performance.create(@attr.merge(:showtimes_attributes => @attr_invalid))
    invalid.should_not be_valid
  end

end

希望我没有破坏上述代码中的任何内容,只是为了显示必要的部分。

【问题讨论】:

数据库中实际定义的start_time是怎么回事? start_date 是否定义为数据库中的日期时间? start_date 被定义为datestart_time 被定义为time。我将它们保留为单独的字段,以便 start_time 可以是可选的。 如果 start_time 是可选的,那么当您要设置starting_at 时要检查什么?您可能需要两个案例,对吧?一个当它存在时,一个当它不存在时?就我而言,starting_at 是我保存到数据库的对象。你是如何声明变量的? 在我看来,我使用f.text_field :start_datef.time_select :start_time。然后,目前,我正在相互独立地进行所有验证,但如果将两者拼凑在一起以进行验证以使其更有意义,这看起来很费力,并且是有道理的,也是因为我正在努力寻找一种方法来检查start_time 是一个仍然允许零的时间。是的,我需要 2 个箱子,if start_date.present? &amp;&amp; start_time.present? xxxxxxxx elsif start_date.present? &amp;&amp; start_time.nil? xxxxxxxxx end。 @RyanJM 很高兴看到您的模型和视图的各个部分是什么样的。 您的attr_accessors 设置是否正确?打开控制台并验证您的construct_stating_at 是否正常工作。 gist.github.com/2320468 【参考方案1】:

我没有使用过 date_validator gem,但是validates_timeliness 做这种事情非常好,而且似乎也得到了更积极的维护。

【讨论】:

感谢蒂洛的回复。在移至 date_validator gem 之前,我尝试使用该 gem。我需要允许空白,并且 validates_timeliness 似乎存在一个错误,它允许空白与它正在应用验证的字段。 date_validator gem 似乎也简单得多。 Date_validator 似乎没有验证时间,所以我试图将我的日期与我的时间合并以获得我可以验证的日期时间。【参考方案2】:

以下是最终为我指明了正确方向的内容:https://github.com/codegram/date_validator/issues/25#issuecomment-6126879

【讨论】:

以上是关于在 Rails 模型中一起验证日期和时间字段的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Rails 中验证日期?

Rails 4 - 将日期时间转换为单独的日期和时间字段

无法在 Rails 中编写日期验证

在 Rails 中,如何编写一个带有“where”的查找器来比较两个日期?

验证模型表单日期字段时,Django 期望格式错误

使用 mvc 4 中的模型根据出生日期验证年龄