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

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

This question is related to ruby-on-rails ruby activerecord

The answer is


I find that this query is better/faster for using the "pluck" method, which I love:

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

This gives an ActiveRecord as the output; so you can use .pluck on it like this:

Challenge.limit(5).order('id desc').pluck(:id)

which quickly gives the ids as an array while using optimal SQL code.


new way to do it in rails 3.1 is SomeModel.limit(5).order('id desc')


If you need to set some ordering on results then use:

Model.order('name desc').limit(n) # n= number

if you do not need any ordering, and just need records saved in the table then use:

Model.last(n) # n= any number

If you have a default scope in your model that specifies an ascending order in Rails 3 you'll need to use reorder rather than order as specified by Arthur Neves above:

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

or

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

Just try:

Model.order("field_for_sort desc").limit(5)

Add an :order parameter to the query


If you have a default scope in your model that specifies an ascending order in Rails 3 you'll need to use reorder rather than order as specified by Arthur Neves above:

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

or

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

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.


Add an :order parameter to the query


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.


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".


Just try:

Model.order("field_for_sort desc").limit(5)

we can use Model.last(5) or Model.limit(5).order(id: :desc) in rails 5.2


If you need to set some ordering on results then use:

Model.order('name desc').limit(n) # n= number

if you do not need any ordering, and just need records saved in the table then use:

Model.last(n) # n= any number

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.


Add an :order parameter to the query


new way to do it in rails 3.1 is SomeModel.limit(5).order('id desc')


For Rails 4 and above version:

You can try something like this If you want first oldest entry

YourModel.order(id: :asc).limit(5).each do |d|

You can try something like this if you want last latest entries..

YourModel.order(id: :desc).limit(5).each do |d|

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".


we can use Model.last(5) or Model.limit(5).order(id: :desc) in rails 5.2


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

In my rails (rails 4.2) project, I use

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

and it works.


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

In my rails (rails 4.2) project, I use

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

and it works.


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.


Add an :order parameter to the query


For Rails 4 and above version:

You can try something like this If you want first oldest entry

YourModel.order(id: :asc).limit(5).each do |d|

You can try something like this if you want last latest entries..

YourModel.order(id: :desc).limit(5).each do |d|

I find that this query is better/faster for using the "pluck" method, which I love:

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

This gives an ActiveRecord as the output; so you can use .pluck on it like this:

Challenge.limit(5).order('id desc').pluck(:id)

which quickly gives the ids as an array while using optimal SQL code.


Examples related to ruby-on-rails

Embed ruby within URL : Middleman Blog Titlecase all entries into a form_for text field Where do I put a single filter that filters methods in two controllers in Rails Empty brackets '[]' appearing when using .where How to integrate Dart into a Rails app Rails 2.3.4 Persisting Model on Validation Failure How to fix "Your Ruby version is 2.3.0, but your Gemfile specified 2.2.5" while server starting Is the server running on host "localhost" (::1) and accepting TCP/IP connections on port 5432? Rails: Can't verify CSRF token authenticity when making a POST request Uncaught ReferenceError: React is not defined

Examples related to ruby

Uninitialized Constant MessagesController Embed ruby within URL : Middleman Blog Titlecase all entries into a form_for text field Ruby - ignore "exit" in code Empty brackets '[]' appearing when using .where find_spec_for_exe': can't find gem bundler (>= 0.a) (Gem::GemNotFoundException) How to update Ruby Version 2.0.0 to the latest version in Mac OSX Yosemite? How to fix "Your Ruby version is 2.3.0, but your Gemfile specified 2.2.5" while server starting Is the server running on host "localhost" (::1) and accepting TCP/IP connections on port 5432? How to update Ruby with Homebrew?

Examples related to activerecord

Empty brackets '[]' appearing when using .where Get only records created today in laravel How do you manually execute SQL commands in Ruby On Rails using NuoDB Rails 4 LIKE query - ActiveRecord adds quotes Rails create or update magic? CodeIgniter query: How to move a column value to another column in the same row and save the current time in the original column? Check if record exists from controller in Rails Codeigniter's `where` and `or_where` Codeigniter LIKE with wildcard(%) Codeigniter: does $this->db->last_query(); execute a query?