Background Information
At one of my projects, we were using UUIDs as a primary key for a Foo
resource. We were serving the resource with corresponding page
and per_page
parameters to consume it. Later, we've received a report that as a user went through the pages, they noticed duplicate records appearing.
Upon investigation, it appears that the resource was implicitly ordered and since it was not explicitly ordered and that it was using UUIDs, the order returned by SQL was sorted not by their time component but by their memory layout. 1
Implicit Ordering by Rails
The Foo
resource used the implicit_order_column
:
class ApplicationRecord < ActiveRecord::Base
primary_abstract_class
self.implicit_order_column = 'created_at'
end
It turns out, based on a Github Issue on the above method 2, retrieving all records of a resource (e.g. Foo.all
) will not apply implicit_order_column
because it is not an ordered finder call, since under the hood it executes SELECT * FROM table
.
Only #first
and #last
methods are affected by the implicit_order_column
since both methods order by primary key by default.
Explicit Ordering
So since we needed to paginate the resource, our solution was to make an explicit ordered call to the resource Foo.order(created_at: :asc)
. We also wanted to avoid using default_scope order(created_at: :asc)
as if you needed to specify a different order, you'd have to chain a #reorder
method. 3
As another precaution, we added a compound index on the table based on created_at
and id
. This sorts by created_at
first and then by id
so that records are ordered more predictably (i.e. when records have the same created_at
they are then sorted by id
). 4