Rails does not support sub-second precision with Oracle

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
test failure:

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:
oracle_adapter.rb
at line 100.

Paul Gross

Paul Gross

I'm a lead software developer in Seattle working for Braintree Payments.

Read More