Rails - order on column's values (priority column)
A simple CASE WHEN
can do the trick (postgreSQL syntax used here):
scope :urgency_ordered {
order(<<-SQL)
CASE tasks.urgency
WHEN 'HIGH' THEN 'a'
WHEN 'MEDIUM' THEN 'b'
WHEN 'LOW' THEN 'c'
ELSE 'z'
END ASC,
id ASC
SQL
}
Call it this way:
Task.urgency_ordered
If using Rails 4.1+, consider using Active Record enums (Release Notes and Documentation) for a DB agnostic solution:
class Task < ActiveRecord::Base
enum priority: [ :high, :medium, :low ]
# Or enum priority: { high: 0, medium: 1, low: 2 }
scope :priority_order, ->{ order(:priority) }
scope :reverse_priority_order, ->{ order(priority: :desc) }
end
This will require a new integer column for the priority, and copying/moving the text data that you have to the new integer column, which could be done in a migration. then calling Task.priority_order
should do the trick.
It is late but here my 2cents. (Rails 4.2.1)
If you use the solution directly like this:
class Task < ActiveRecord::Base
enum priority: { high: 0, medium: 1, low: 2 }
scope :priority_order, order(:priority)
end
You will get this error: The scope body needs to be callable.
You need to call the scope like this.
scope :priority_order, -> {
order(:priority)
}
define it like Proc
or Lambda
.
Why, you may ask :)
It makes sure what you have in the block is used each time the scope is triggered.