ActiveRecord::Relation#order
is used to specify the order in which records should be retrieved from the database.
Recently in Rails 7.2 ActiveRecord::Relation#order
added support
for hash values.
ActiveRecord::Relation
can take a hash where keys are table name, value is a hash of key (column name)
and value (order direction). For example:
Client.includes(:projects).order(projects: { created_at: :desc })
Let’s see some examples with the Client
and
Project
models.
class Client < ApplicationRecord
# id, name, description
has_many :projects
end
class Project < ApplicationRecord
# id, name, price, client_id
belongs_to :client
end
Before
Before 7.2, we were able to order records with the following syntax:
# order client records based on projects created_at.
Client.includes(:projects).order('projects.created_at')
# order client records based on projects created_at in descending manner.
Client.includes(:projects).order('projects.created_at': :desc)
# order client records based on projects created_at in ascending manner and in projects name in descending manner.
Client.includes(:projects).order('projects.created_at, projects.name DESC')
# order client records based on projects created_at in ascending manner, client name and projects name in descending manner.
Client.includes(:projects).order('projects.created_at', { name: :desc }, 'projects.name desc' )
After
After ActiveRecord::Relation#order added support for hash we don’t need to use the raw version of the query anymore.
Let’s take a look at the same code after this change.
# order client records based on projects created_at.
Client.includes(:projects).order(projects: { created_at: :asc })
# order client records based on projects created_at in descending manner.
Client.includes(:projects).order(projects: { created_at: :desc })
# order client records based on projects created_at in ascending manner and in projects name in descending manner.
Client.includes(:projects).order(projects: { created_at: :asc, name: :desc })
# order client records based on projects created_at in ascending manner, client name and projects name in descending manner.
Client.includes(:projects).order(
{ projects: { created_at: :asc, name: :desc } },
{ clients: { name: :desc } }
)
or
Client.includes(:projects).order(
projects: { created_at: :asc, name: :desc },
clients: { name: :desc }
)
Or written in combination with the other existing strategies:
Client.includes(:projects).order('projects.created_at', { name: :desc }, posts: { name: :desc})