We recently discovered that Rails maps a :timestamp in a migration file
to an Oracle DATE instead of a TIMESTAMP. DATE
types only have second precision, not millisecond.
To make things even weirder, rails still maps that column to a ruby Time
object which has sub-second precision. This can lead to the following
Create a table with:
create_table :posts do |t| t.column :posted_at, :timestamp end
And then try:
now = Time.now Post.create(:posted_at => now) assert_equal now, Post.find(1).posted_at
The failure occurs because now has milliseconds, but they are truncated
when the Post is saved (since the table uses a DATE). When the record is read back in, the two
times are different.
In order to get our tests passing, we decided to just compare the string
versions of the two times rather than the times themselves. Since the
string representations do not include milliseconds, the test will pass.
assert_equal now.to_s, Post.find(1).posted_at.to_s
You can read more about the Oracle date/time weirdness in the source:
at line 100.