Why you might not want to use Rails timestamps

Ran into an interesting issue today. I inherited some code that did this sort of thing:

  ActionLog.rejections.last

which would nearly always actually give you the last rejection, but in a SQL database, this is not guaranteed.

The solution might be to add a default scope:

  default_scope ->{order 'created_at ASC'}

interestingly, though, when I added this, which you would think was virtually a noop as far as logic goes, several tests failed.

It turned out that the resolution on timestamps from Rails (at least with MySQL, as in this instance) was 1/100 of a second. In testing, this meant that the test records were all getting created with the same timestamp.

The test did some things and then asserted something about the last record. The order actually made that pick essentially a random record, so the test failed.

I’ve long thought that it was better anyway to have the database record timestamps. A single source of truth for time, and it might be a tad bit faster.

The solution would be to add a default timestamp value of NOW() to all the created_at fields, but this doesn’t set updated_at. You could set that using a trigger. I should benchmark whether that is faster or slower than having Rails do it…