Reputation: 515
Is there a way to order records alphabetically, excluding one record, which I want at the end?
class Category < ActiveRecord::Base
default_scope -> { order(:name) }
end
I always want the category named 'Other' to be at the end.
Upvotes: 1
Views: 98
Reputation: 774
I would recommend just to add an additional field "position" and sort everything by it. Or you can order by 2 fields (position, name). All Categories will have position equal = 0, and "Other" equal to 999 for example
Upvotes: 0
Reputation: 140
You can try the below ActiveRecord query
Category.order("CASE WHEN name = 'Other' then 0 else 1 END DESC, name ASC")
Upvotes: 2
Reputation: 176472
This is a little bit tricky. In SQL you can add CASE
statements to your ORDER BY
. In your case the SQL would be something similar to.
SELECT *
FROM categories
ORDER BY
(
CASE
WHEN name = 'Other' THEN 1
ELSE 0
END
)
Here's a live example.
As far as I know, the ActiveRecord order
method accepts arbitrary string, so you could (not tested) be able to pass the case to the method
Category.order("CASE WHEN name = 'Other' ... ")
This approach seems complicated, but if you can get it to work is by far the most efficient.
The second alternative is to play a little bit with ActiveRecord.
class Category < ActiveRecord::Base
def self.ordered(condition = nil)
# Get the ID of the record to exclude
excluded = self.where(name: 'Other').pluck(:id).first
# order the records and collect the ids
ids = where('id <> ?', excluded).order(condition).pluck(:id)
# append the excluded at the end
ids << excluded
# recreate the scope and return it.
where(id: ids)
end
end
Category.where(...).ordered
Generally speaking, I encourage you to avoid default_scopes
in ActiveRecord. It's so easy to add them, but very hard to remove them when you need.
Upvotes: 1