我正在尝试使用Mysql 5.6.33和ActiveRecord 5.0.1将项目升级到mysql2 gem 0.4.5。我有许多规范测试涉及创建记录,然后搜索created_at
值为<= Time.now
的记录。我通过以下从ActiveRecord 4.2到ActiveRecord 5.0.1的行为更改示例总结了失败:
ActiveRecord 4
irb(main):021:0> puts Time.at(1482722443.8581448)
2016-12-26 03:20:43 +0000
=> nil
irb(main):022:0> p.updated_at = Time.at(1482722443.8581448)
=> 2016-12-26 03:20:43 +0000
irb(main):023:0> p.save
=> true
irb(main):024:0> p.updated_at
=> 2016-12-26 03:20:43 UTC
irb(main):025:0> p.reload
=> #<Profile id: 1, ...
irb(main):026:0> p.updated_at
=> 2016-12-26 03:20:43 UTC
ActiveRecord 5.0.1
> puts Time.at(1482722443.8581448)
2016-12-26 03:20:43 +0000
=> nil
> p.updated_at = Time.at(1482722443.8581448)
=> 2016-12-26 03:20:43 +0000
> p.save
=> true
> p.updated_at
=> 2016-12-26 03:20:43 UTC
> p.reload
=> #<Profile:0x0055e04486dc40
id: 1,
...
> p.updated_at
=> 2016-12-26 03:20:44 UTC
正如您所看到的,在AR4的第一个示例中,数据库返回的日期时间为43秒,因此它在{{1}提供的时间戳上执行floor
操作}。
在AR5中,它正在进行1482722443.8581448
操作,并将round
时间移动到下一整秒,从而使其从第二个43到第二个44.
这导致“将来”创建记录,我创建的示例,然后搜索created_at
为created_at
的记录没有返回任何记录,因为它实际上是在未来以毫秒为单位。
这种行为是预期的,还是这个错误?我可以在AR5中配置这种毫秒舍入行为吗?
更新
如果我这样做,它看起来像在mysql中:
<= Time.now
然后:
update alerts set created_at = '2016-12-26 04:08:19.7777' limit 1;
我得到了
select created_at from alerts;
因此,mysql正在进行“四舍五入”。是否有可能从4.2到5.0.1,ActiveRecord开始用日期时间编写查询
2016-12-26 04:08:20
而不是
2016-12-26 04:08:19.7777
使用Mysql 5.6.33?
答案 0 :(得分:0)
是的,ActiveRecord 5已根据this blog post更改了其行为。
以下是在ActiveRecord 5.0.1中添加此支持的two commits。
要恢复旧行为,我必须添加以下monkeypatch:
module ActiveRecord
module ConnectionAdapters
class AbstractMysqlAdapter < AbstractAdapter
end
class Mysql2Adapter < AbstractMysqlAdapter
def supports_datetime_with_precision?
false
end
end
end
end