First vs take vs Limit methods in Rails

There are some notable differences between the #take, #first & #limit methods that we, as Rails developers, should be aware of.

Take method

The Take method returns a record without any implied order. You can also specify a parameter, for example, #take(5) which will return the number of records you have specified in your parameter.

#take generates the following SQL

> User.take
User Load (0.5ms)  SELECT "users".* FROM "users" LIMIT $1  [["LIMIT", 1]]

> User.take(5)
  User Load (0.5ms)  SELECT "users".* FROM "users" LIMIT $1  [["LIMIT", 5]]

The order is indeed at random

> User.take(5).map(&:id)
  User Load (0.6ms)  SELECT "users".* FROM "users" LIMIT $1  [["LIMIT", 5]]
 => [2, 108, 37, 487, 20] 

If you don't care about the order or if you want an arbitrary record, #take is a good way to go.

Notice that #take is also an array method which works in a slightly different way. If you call Array#take, a parameter is required and it returns the first N records in the form of an array.

Therefore, User.take(5).take(1) is a valid syntax but User.take(5).take will throws an error.

First method

The First method is similar to #take, but it returns the first record (or N records if a parameter is specified).

#first generates the SQL

> User.first
  User Load (10.6ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
> User.first(5)
  User Load (0.6ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 5]]

Notice that the #first adds an additional ordering query to the SQL command. This means that in general #take will be faster than #first since #take can stop as soon as it finds the first row. The difference often might be negligible, but if you don't need the first record just, I recommend you to just use #take.

Just like #take, #first also has its array version. It works very similarly its Rails version and as well as Array#take.

Array#first doesn't require an argument, unlike Array#take. You should also note that Array#first(1) will return an array unlike Array#first, which will return a single value.

Another difference can be found when you call the methods on empty arrays

> [].take(1)
 => [] 

> [].first
 => nil 

You should decide which behaviour you want in a given scenario within your app.

Limit method

The Limit method specifies a limit for the number of records to retrieve. Unlike the previous two methods, #limit requires a parameter. It always returns an Active Record Relation.

#limit generates the SQL

> User.limit(5)
  User Load (0.5ms)  SELECT "users".* FROM "users" LIMIT $1  [["LIMIT", 5]]
> User.limit(5).class
 => User::ActiveRecord_Relation 

Since #limit returns an Active Record Relation, this means that you can continue scoping afterwards

> User.limit(5).where(id: 1)
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 5]]

This won't work with either #take or #first because these methods return an array. Therefore, an error will be thrown at you.

Limit does not have a corresponding Array method, so if you call it on an Array, it will throw an error.

Level up your web development skills

Get articles, guides and interviews right in your inbox. Join a community of fellow developers.

No spam. Unsubscribe at any time.

Full Stack Heroes logo

© 2020 Full Stack Heroes