November 2, 2021
This blog is part of our Rails 7 series.
Rails 7 introduces ActiveRecord::QueryMethods#in_order_of to fetch active record collection in a specific order based on the given attribute values.
We can see the similar method available for Enumerable#in_order_of
to
constrain records in a specific order from an enumerable collection by using
key-series pair. You can find more details here in
our blog
regarding Enumerable#in_order_of
method.
The newly introduced method is highly helpful to build queries by which we can
specify an explicit order that we would like to get the collection as result.
Otherwise we will have to make custom CASE
statements to specify the order in
raw SQL statement format.
# Fetch Post records in order of [3, 5, 1]
SELECT "posts".* FROM "posts" ORDER BY CASE "posts"."id" WHEN 3 THEN 1 WHEN 5 THEN 2 WHEN 1 THEN 3 ELSE 4 END ASC
Suppose we have a Course
model with status
column having possible values
like enrolled
, started
& completed
. If we want to fetch all course records
as a collection with status values in order of started
, enrolled
&
completed
, then the only option here is to build the CASE
statement as raw
SQL. Otherwise we will have to make iterations over the returned result to
modify in the specific order we wish to get back.
Course.order(
Arel.sql(
%q(
case status
when 'started' then 1
when 'enrolled' then 2
when 'completed' then 3
else 4 end
)
)
)
The ActiveRecord::QueryMethods#in_order_of
method will prepare either CASE
statement or will make use of built-in function (Eg: FIELD
in MySQL) based on
the adapter to perform the specified order.
Course.in_order_of(:status, %w(started enrolled completed))
The returned result here is an ActiveRecord::Relation
object unlike the result
for Enumerable#in_order_of
where it is an array. Hence we can chain other
scopes or query methods with the result while using
ActiveRecord::QueryMethods#in_order_of
method.
Course.in_order_of(:status, %w(started enrolled completed)).order(:created_at: :desc).pluck(:name)
Please check out this pull request for more details.
If this blog was helpful, check out our full blog archive.