“Time.now.utc”Rails和`now()在时区'utc'` postgres之间的区别

时间:2013-12-17 13:40:36

标签: ruby-on-rails postgresql

问题如下:我有一个模型 - MyModel1和MyModel2,它们具有MyModel1 has_many MyModel2的关系。现在,数据库是postgres,MyModel2上有一个数据库触发器,在插入/更新/删除时会在某个时刻更新MyModel1的updated_at字段:

UPDATE my_model1 SET updated_at = (now() at time zone 'utc')

现在,我有一个规范,它验证它是否真的完成了我想要的事情:

it "updates the updated_at field" do
    mymodel1instance.update_attributes(updated_at: Time.now - 1.day)
    mymodel2build.save!   # mymodel2build belongs_to mymodel1instance
    mymodel1instance.updated_at.to_s.should == Time.now.utc.to_s
  end

我相信会有延迟或其他什么。奇怪的是,mymodel2build.updated_at字段是Time.now.utc的1秒AHEAD。

规格结果:

   expected: "2013-12-17 13:30:33 UTC"
        got: "2013-12-17 13:30:32 UTC" (using ==)

备注:规格并不总是失败,它会不时失败。 任何人都可以解释为什么会这样吗?

1 个答案:

答案 0 :(得分:2)

在Postgres中,您有now()clock_timestamp()

  • now()将返回当前事务开始的时间戳。 (或者语句的,如果它是事务之外的只读查询。)
  • clock_timestamp()将像Ruby的Time.now一样返回时钟的时间戳。

另外,您的测试相当于测试a)Ruby返回系统时钟的当前时间,b)实际发生单个字段的Postgres更新。这使得它与编写测试以验证2 + 2 = 4一样有用。当然,并不是说这些测试不可能失败;就是这样,imho,你可能有更重要的事情要花时间,即测试几个抽象级别的东西,比如公共API端点。 (后者比通过单元测试冻结自己的内部构件更重要。)