[Ruby-on-rails] How to get last N records with activerecord?


Answers

This is the Rails 3 way

SomeModel.last(5) # last 5 records in ascending order

SomeModel.last(5).reverse # last 5 records in descending order
Question

With :limit in query, I will get first N records. What is the easiest way to get last N records?




Let's say N = 5 and your model is Message, you can do something like this:

Message.order(id: :asc).from(Message.all.order(id: :desc).limit(5), :messages)

Look at the sql:

SELECT "messages".* FROM (
  SELECT  "messages".* FROM "messages"  ORDER BY "messages"."created_at" DESC LIMIT 5
) messages  ORDER BY "messages"."created_at" ASC

The key is the subselect. First we need to define what are the last messages we want and then we have to order them in ascending order.




Just try:

Model.all.order("id asc").limit(5)



Solution is here:

SomeModel.last(5).reverse

Since rails is lazy, it will eventually hit the database with SQL like: "SELECT table.* FROM table ORDER BY table.id DESC LIMIT 5".




For Rails 5 (and likely Rails 4)

Bad:

Something.last(5)

because:

Something.last(5).class
=> Array

so:

Something.last(50000).count

will likely blow up your memory or take forever.

Good approach:

Something.limit(5).order('id desc')

because:

Something.limit(5).order('id desc').class
=> Image::ActiveRecord_Relation

Something.limit(5).order('id desc').to_sql
=> "SELECT  \"somethings\".* FROM \"somethings\" ORDER BY id desc LIMIT 5"

The latter is an unevaluated scope. You can chain it, or convert it to an array via .to_a. So:

Something.limit(50000).order('id desc').count

... takes a second.




In my rails (rails 4.2) project, I use

Model.last(10) # get the last 10 record order by id

and it works.