Last updated on December 12, 2021
There are some notable differences between the #take, #first & #limit methods that we, as Rails developers, should be aware of.
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 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.
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.
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.
Articles, guides and interviews about web development and career progression.
Max 1-2x times per month.