Reputation: 458
The problem is the following: I have a model - MyModel1 and MyModel2, which have the relation - MyModel1 has_many MyModel2's. Now, the database is postgres, and there is a database trigger on MyModel2, which on insert/update/delete updates the updated_at
field of MyModel1 in some moment:
UPDATE my_model1 SET updated_at = (now() at time zone 'utc')
Now, I have a spec, which verifies whether it has really done what I wanted:
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
I believe there can be a delay or something. The weird thing is that mymodel2build.updated_at
field is 1 second AHEAD of Time.now.utc.
Spec result:
expected: "2013-12-17 13:30:33 UTC"
got: "2013-12-17 13:30:32 UTC" (using ==)
Remark: spec doesn't ALWAYS fail, it just fails from time to time. Can anyone explain why this is happening ?
Upvotes: 2
Views: 695
Reputation: 78503
In Postgres, you have now()
and clock_timestamp()
:
now()
will return the timestamp at which the current transaction started. (Or that of the statement, if it's a read-only query outside of a transaction.)clock_timestamp()
will, like Ruby's Time.now
, return the timestamp of the clock.An as aside, your test amounts to testing that a) Ruby returns the system clock's current time and b) Postgres updates on a single field actually occur. That makes it about as useful as writing a test to verify that 2 + 2 = 4
. Not saying that these tests can't possibly fail, of course; just that, imho, you probably have more important things to be spending time on, namely testing things that are several levels of abstraction higher such as public API endpoints. (The latter are orders of magnitude more important than freezing your own internals with unit tests.)
Upvotes: 3