a-b-r-o-w-n
a-b-r-o-w-n

Reputation: 515

Rails 4 named scope with record always at end

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

Answers (3)

Igor Kasyanchuk
Igor Kasyanchuk

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

Lucky
Lucky

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

Simone Carletti
Simone Carletti

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

Related Questions