11
votes

I want to order all the items in a model Item so it displays the most recent ones first. According to the Rails guide, the following code should work:

 Item.order("created_at DESC")

However, when I type that (or varieties) in the terminal, the most recent item always shows up last, and that's how they show up on my page. How do I efficiently retrieve them with he most recent first? (I'm going to display only some of them at a time on each page.)

Note that my default scope for items is oldest first.

Update: This is the SQL I get:

SELECT "comments".* FROM "comments" ORDER BY comments.created_at ASC, created_at DESC

So I guess I shouldn't use default scopes...

6
The query you posted is correct. There must be something else conflicting with it. Post the SQL that is executed (you can see it in the console). - Simone Carletti

6 Answers

12
votes

The query you posted is correct

Item.order("created_at DESC")

The only reason why it would not work is if there is anything else conflicting with it. In general, the conflict is represented by a default_scope.

If you have a default scope that overrides your order, you should first unscope the query

Item.unscoped { Item.order("created_at DESC") } 

If you are using default scopes, I strongly encourage you to avoid them. They are very hard to debug and unscope.

There are very few cases where default scopes make sense. You can simply pass the (default) scope at select time in the controller or create a custom method for it.

11
votes

I realise this is a really old question, but none of the answers contain the solution without writing raw SQL, which is available since Rails 3+:

Item.order(created_at: :desc)

or using the reverse_order method:

Item.order(:created_at).reverse_order

See more at http://guides.rubyonrails.org/active_record_querying.html#ordering and http://guides.rubyonrails.org/active_record_querying.html#reverse-order.

4
votes

I modified CDub's answer with reverse so it now works:

 Item.order(:created_at).reverse

I'm still not sure why the Rails guide's way doesn't work. Also the above method doesn't work well with pagination.

1
votes

Item.unscoped.order('created_at DESC') should work.Using reverse might decrease the performance when the number of records increases

0
votes

Correct one and tested

@purchase_orders = current_company.purchase_orders.order(:date)
@purchase_orders = @purchase_orders.reverse_order 
-1
votes

you can add You can also define the default order in Item model

default_scope order('created_at DESC')