Arrays in Ruby: Take vs Limit vs First
Solution 1
- limit is not an array method
- take requires an argument; it returns an empty array if the array is empty.
- first can be called without an argument; it returns nil if the array is empty and the argument is absent.
Source for 2.0 take
static VALUE
rb_ary_take(VALUE obj, VALUE n)
{
long len = NUM2LONG(n);
if (len < 0) {
rb_raise(rb_eArgError, "attempt to take negative size");
}
return rb_ary_subseq(obj, 0, len);
}
Source for 2.0 first:
static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
if (argc == 0) {
if (RARRAY_LEN(ary) == 0) return Qnil;
return RARRAY_PTR(ary)[0];
}
else {
return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
}
}
In terms of Rails:
limit(5)
will add the scope oflimit(5)
to anActiveRecord::Relation
. It can not be called on an array, solimit(5).limit(4)
will fail.first(5)
will add the scope oflimit(5)
to anActiveRecord::Relation
. It can also be called on an array so.first(4).first(3)
will be the same as.limit(4).first(3)
.take(5)
will run the query in the current scope, build all the objects and return the first 5. It only works on arrays, soModel.take(5)
will not work, though the other two will work.
Solution 2
The answer chosen answer seems to be outdated (in terms of Rails) so I would like to update some information.
-
limit
on anActiveRecord::Relation
will still be aRelation
. So if you call:Model.limit(5).limit(4)
will be same as:
Model.limit(4)
-
first
on anActiveRecord::Relation
will make the result anArray
. So you cannot call any scope afterfirst
like:Model.first(5).where(id: 1)
But you can do this:
Model.limit(5).where(id: 1)
-
take
Model.take(5)
works now. It will return an array, so you cannot call any
scope
either.
On an ActiveRecord::Relation
object, if you call first
it will include ORDER BY 'tables'.id
. Whereas with limit
and take
there is no ORDER BY
included but the sorting is depended by the database sorting implementation.
Related videos on Youtube
Prem
Updated on October 08, 2022Comments
-
Prem over 1 year
Suppose you have an array of objects in Rails
@objects
If I want to display the first 5 objects, what is the difference between using:
@objects.limit(5)
@objects.take(5)
@objects.first(5)
I am talking about the front end (Ruby), NOT SQL. The reason why the objects are not limited in SQL is because the same array may be used elsewhere without applying a limit to it.
Does it have anything to do with object instantiation?
-
Larry McKenzie@objects is probably not an array but rather an ActiveRecord relation. That is why you use of limit(5) is working.
-
seandAre you sure @objects is an Array? I've never heard of a #limit method. #first however is a standard method to return the first element. #take is also a method.
-
Prem about 11 yearsAre you sure
#limit
is not an array method? I applied it to a view on an object array@objects
and it performed the same task as#take
and#first
.#first
can take an argument (optional). Try it yourself -
0112 over 9 years
take()
can be called without an argument. -
Shawn Balestracci over 9 years@alex0112 Not in ruby 1.8.7, 1.9.3, 2.0.0 or 2.1.0
-
0112 over 9 years
-
user1063998 about 7 yearscalling
#take
on a relation with also add alimit
to the query