我有以下装置:
link_1:
user: tom
image: boy1
created_at: <%= 5.day.ago %>
我尝试了以下请求:
Links.where("Date(created_at) = ?", 5.day.ago.to_date)
答案:
[]
GRRRR ....输入...输入... ...刮伤 我终于尝试过:
link_1:
user: tom
image: boy1
created_at: <%= 5.day.ago.to_date %>
和
Links.where("Date(created_at) = ?", 5.day.ago.to_date)
最后回答
[#<Link id: 298486374, user_id: 1038054164, image_id: 482586125, created_at: "2010-11-28 00:00:00", updated_at: "2010-12-03 21:32:19">]
我的期待是什么,但为什么我需要提交to_date?我不清楚,因为当我创建一个没有指定创建日期的对象时,我可以使用以下where子句选择它们而不会出现问题:
Links.where("Date(created_at) = ?", Date.today)
有什么想法吗?
答案 0 :(得分:20)
在灯具中你应该:
created_at: <%= 5.day.ago.to_s(:db) %>
您的查询将是:
Links.where("created_at = ?", ...
让ActiveRecord处理有关从数据库移动数据到数据库的详细信息。我们使用ORM是有原因的。
答案 1 :(得分:1)
我推测这是因为创建灯具和调用查询之间的时间差。
5天前+ 0.00025毫秒&gt; 5天前
我不确定日期时间的精确度是多少,但这是我能想到的唯一可能性。当您将其转换为日期时,您删除了无关的时间信息并使两者相等。
答案 2 :(得分:1)
created_at
是一个DateTime字段,5.days.ago
有效地返回一个DateTime对象。此对象的设置时间与调用时相同,例如。星期六,2014年8月23日10:30: 37 ,这是放入数据库的内容。
在失败的情况下,当您稍后再次呼叫5.days.ago
时(即使在同一执行中),新时间可能会有所不同,例如。 2014年8月23日星期六10:30: 38 。因此,您可以看到它们不相等,您将无法获得匹配。
当你追加.to_date
时,你会得到一个Date对象,它没有时间组件。当它被持久化到数据库或在您的查询中使用时,它将始终被视为具有00:00:00(午夜)的时间。因此,日期和时间将匹配,(只要您不尝试运行灯具并在午夜完成查询)
答案 3 :(得分:0)
两种情况之间的区别在于,当您拨打to_date
时,您会丢失时间值,因此最终结果是created_at
时间戳设置为当天的午夜。您还可以避免TimeWithZone
的时区转换。坦率地说,我们没有足够的信息来推测除此之外发生的事情。要查看确切的内容,最好的办法是查看log/test.log
中的查询 - 如果您没有看到查询,可以将log_level
设置为{{1}来启用查询在:debug
中。您可以在此处复制并粘贴SQL查询。
@Ibz也提出了一个好点:使用config/environments/test.rb
是一个好主意,因为fixture文件ERB被计算为一个字符串然后作为YAML读入,这可能会导致将值转换为字符串的一些问题。使用.to_s(:db)
将解决此问题,但为了避免将来出现此问题(并获得一系列其他功能),我建议您使用factory_girl代替灯具。
在处理测试日期时,这类问题很常见 - 特别是如果您尝试通过两个日期或时间戳的相等性进行查询。要解决这些问题,我建议您过去选择任意固定日期/时间而不是.to_s(:db)
,或者如果您确实需要使用动态日期/时间,请使用Timecop gem来控制/冻结时间在你的测试中。