比较 ruby​​ 中相同的 DateTime 对象——为什么这两个 DateTime.now 不相等? [英] Comparing identical DateTime objects in ruby -- why are these two DateTime.now's not equal?

查看:56
本文介绍了比较 ruby​​ 中相同的 DateTime 对象——为什么这两个 DateTime.now 不相等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 rails 应用程序中,我有以下形式的模型代码:

In a rails app, I have model code of the form:

def do_stuff(resource)
  models = Model.where(resource: resource)
  operated_at = DateTime.now

  models.each { |model| some_operation(model, operated_at) }

  some_other_operation models, operated_at
end

def some_operation(model, operated_at)
  model.date_time_field = operated_at
  model.save
end

def some_other_operation(models, operated_at)
  models.each do |model|
    if model.date_time_field < operated_at
      # do something
    end    
  end
end

在这种情况下,some_other_operation 的做某事"块将始终被执行.更奇怪的是,如果我在没有定义所有函数的情况下在控制台中设置它,则比较会按预期进行.示例:

The 'do something' block of some_other_operation will always be executed, in this situation. Even stranger, if I set this up in the console without all the defined functions, the comparison works as expected. Example:

> model = Model.first
> time_var = DateTime.now
> model.last_imported_at = time_var
=> Fri, 25 Oct 2013 21:14:06 +0000
> model.save
=> true
> model.last_imported_at < time_var
=> false
> model.last_imported_at == time_var
=> true

最后,如果在 some_other_operation 中,我改为按以下方式进行比较:

Finally, if, in some_other_operation I instead compare in the following way:

if model.date_time_field.to_i < operated_at.to_i
  # do something
end

做某事"块仅在预期时到达.我怀疑这是因为 to_i 方法会删除 DateTime 对象上定义的秒的分数,而 operated_at 变量实际上被重新定义为 DateTime.now 每个方法的范围.如果是这种情况,那么我想我的问题是如何强制 operated_at 不为每个范围重新定义?

the 'do something' block is reached only when expected. I suspect this is because the to_i method will drop the fractions of a second defined on the DateTime object, and the operated_at variable is actually being redefined as DateTime.now for each methods' scope. If this is the case, then I guess my question is how do I force operated_at to not be redefined for each scope?

推荐答案

可能的线索;保存和重新加载的行为会截断 DateTime 的 seconds_fraction 部分.日期字段成为ActiveSupport::TimeWithZone 的一个实例.仅保存而不重新加载不会执行此操作;真正的 DateTime 对象仍然存在.

Possible clue; the act of saving and reloading truncates the seconds_fraction part of the DateTime. The date field becomes an instance of ActiveSupport::TimeWithZone. Just saving without reloading doesn't do this; the real DateTime object is still there.

2.0.0-p195 :001 > dt            =  DateTest.create
2.0.0-p195 :002 > right_now     =  DateTime.now
2.0.0-p195 :004 > dt.created_at =  right_now
2.0.0-p195 :005 > dt.created_at == right_now
 => true 

2.0.0-p195 :006 > dt.save
2.0.0-p195 :007 > dt.created_at == right_now
 => true 

2.0.0-p195 :008 > dt = DateTest.find(dt.id)
2.0.0-p195 :009 > dt.created_at == right_now
 => false 

当然调用 models.each 将在那里加载模型,然后因为延迟加载行为.给另一个回答者的道具.作为实验,尝试将 models 设置为 Model.where(resource: resource).to_a.

of course calling models.each is going to load the models there and then because of the lazy loading behaviour. Props to the other answerer. As an experiment, try setting models to Model.where(resource: resource).to_a.

这篇关于比较 ruby​​ 中相同的 DateTime 对象——为什么这两个 DateTime.now 不相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆