ActiveRecord::Relation#order Adds Support For Hash Values In Rails 7.2.

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})

Need help on your Ruby on Rails or React project?

Join Our Newsletter