method

order

rails latest stable - Class: ActiveRecord::QueryMethods
order(*args)
public

Applies an ORDER BY clause to a query.

#order accepts arguments in one of several formats.

symbols

The symbol represents the name of the column you want to order the results by.

User.order(:name)
# SELECT "users".* FROM "users" ORDER BY "users"."name" ASC

By default, the order is ascending. If you want descending order, you can map the column name symbol to :desc.

User.order(email: :desc)
# SELECT "users".* FROM "users" ORDER BY "users"."email" DESC

Multiple columns can be passed this way, and they will be applied in the order specified.

User.order(:name, email: :desc)
# SELECT "users".* FROM "users" ORDER BY "users"."name" ASC, "users"."email" DESC

strings

Strings are passed directly to the database, allowing you to specify simple SQL expressions.

This could be a source of SQL injection, so only strings composed of plain column names and simple function(column_name) expressions with optional ASC/DESC modifiers are allowed.

User.order('name')
# SELECT "users".* FROM "users" ORDER BY name

User.order('name DESC')
# SELECT "users".* FROM "users" ORDER BY name DESC

User.order('name DESC, email')
# SELECT "users".* FROM "users" ORDER BY name DESC, email

Arel

If you need to pass in complicated expressions that you have verified are safe for the database, you can use Arel.

User.order(Arel.sql('end_date - start_date'))
# SELECT "users".* FROM "users" ORDER BY end_date - start_date

Custom query syntax, like JSON columns for PostgreSQL, is supported in this way.

User.order(Arel.sql("payload->>'kind'"))
# SELECT "users".* FROM "users" ORDER BY payload->>'kind'

7Notes

Reorder

stevo · Mar 27, 20127 thanks

If you want to override previously set order (even through default_scope), use reorder() instead.

E.g.

User.order('id ASC').reorder('name DESC')

would ignore ordering by id completely

Ordering on associations

rin · Oct 28, 20142 thanks

For ordering on the attribute of an associated model you have to include it:

Package.includes(:package_size).order("package_sizes.sort_order")

using hash as order

vitaly · Jan 12, 20141 thank

order can be specified as a hash, e.g.:

order(id: :desc)

This will prevent "ambiguous column" errors when the order is used with joins or includes.

Ordering on associations using merge

svegaca · Mar 11, 20161 thank

For ordering on the attribute of an associated model you can add joins to query and merge order scope: Product.joins(:category).merge(Category.order(priority: :desc))

reorder

bzsolt · Feb 12, 2015

adding to stevo's comment that reorder is also usefull when you have default scope in your model. eg: default_scope -> { order(created_at: :desc) }

arel_table order by

equivalent · Oct 5, 2015

More objected way how to achieve ORDOR BY .... DESC is like this :

class User < ActiveRecord::Base
  has_many :status_changes

  def latest_status_change
    status_changes
     .order(StatusChange.arel_table['created_at'].desc)
     .first
  end
end

class StatusChange < ActiverRecord::Base
  belongs_to :user
end

resulting in:

SELECT "status_changes".* FROM "status_changes" WHERE "status_changes"."user_id" = 1 ORDER BY "status_changes"."created_at" DESC

Benefits:

  • you are strictly bound to Modelclass name => renaming table in model will not break the sql code (of if it will, it will explicitly break the syntax on Ruby level, not DB level)
  • you still have the benefit of explicitly saying what table.column the order should be
  • easier to re-factor parts to Query Objects

Careful with arel column

gamov · May 19, 2016

I use what @equivalent suggests a lot but be careful, you MUST state the direction otherwise methods like take/last/first will fail silently!

StatusChange.arel_table['created_at']. asc

not:

StatusChange.arel_table['created_at']