on programming Rails for fun and profit...

Difference Between the Length, Size, and Count Methods in Rails

You can use the length, size, and count methods to find the number of elements in a collection. This post explores the difference between these methods and explains how you should choose which method to use according to your situation.

When to Use the Length, Size, and Count Methods in Rails
When to Use the Length, Size, and Count Methods in Rails

Rails takes its inspiration from Ruby and offers multiple ways to do the same thing. A good example is finding the number of elements in a collection. You can use the length, size, and count methods to accomplish this.

However, it can be confusing to understand when to use which method, as your choice may have performance implications. Before understanding the difference between these methods, I was never really sure if I had used the correct one.

This post explores the difference between these methods and explains how you should choose which method to use according to your situation.

TL;DR Here's a handy flowchart to simplify your decision-making.

When to Use the Length, Size, and Count Methods in Rails

Let's start with a brief overview of these methods in plain Ruby, specifically in the context of an Array. Then we'll move on to Rails.

length

This is the simplest of them all. It's also the method you're most familiar with.

The length method returns the number of elements in an array. It runs in O(1) constant time.

numbers = [1, 2, 3, 4, 5]

numbers.length # 5

It can't get any simpler than this.

size

This is an alias to the length method. If you try to read the Ruby docs for size, it simply redirects you to the length method.

numbers = [1, 2, 3, 4, 5]

numbers.length # 5

Should you use length or size? It's a matter of personal preference, depending on the context in which you need the number of elements in the collection. Choose the one that is most readable for your context.

For example, if I have a collection named classroom that contains a bunch of students, I'd use classroom.size instead of classroom.length.

count

This method counts the number of specified elements in the array. Use it when you need to find the count of elements matching specific criteria. There are four variations of this method.

1. With no argument and no block, returns the count of all elements

[10, 20, 30].count # => 3
[].count # => 0

2. When an argument is provided, returns the count of array elements that are equal to the argument.

[0, 1, 2, 0.0].count(0) # => 2
[0, 1, 2].count(3) # => 0

3. When a block is provided without any argument, calls the block with each array element and returns the count of elements for which the block returns a truthy value.

[0, 1, 2, 3].count {|e| e > 1} # => 2

4. If you pass both an argument and a block, it ignores the block and returns the count of elements that are equal to the argument. It also issues a warning.

[1, 2, 3].count(2) { |e| e == 0 }
(irb):2: warning: given block not used
=> 1

That's it for Ruby. Now let's turn our attention to Rails, where things get quite interesting.

Ruby on Rails

We will examine these methods in the context of the ActiveRecord::Associations::CollectionProxy class, which inherits from the ActiveRecord::Relation class. Collection proxies are used by ActiveRecord, acting as middlemen between an association and its result set.

class Post < ActiveRecord::Base
  has_many :comments
end

post = Post.last
comments = post.comments

# Comment::ActiveRecord_Associations_CollectionProxy
comments.class 

In this example, comments  is a collection proxy, delegating to a collection of posts. Now let's understand how these methods work.

length

Returns the size of the collection by calling the size method on it.

Post.all.length
# SELECT `posts`.* FROM `posts`

Not much to see here. Let's look at size.

size

This method returns the collection size.

Post.all.size
# SELECT COUNT(*) FROM `posts`

Behind the scenes, this is how the size method works.

size vs. length in Rails
size vs. length in Rails

When to use length vs. size ?

When the collection is already loaded, the size and length methods are equal.

If the collection is not loaded from the database, AND

  1. If you will need the records anyway, use the length method. It will take one less query.
  2. If you won't need the records, use the size method as it's more efficient. It will run a COUNT SQL query to fetch the count directly from the database, without loading the records in memory.
post.comments.length
  Post Load (2.4ms)  SELECT `posts`.* FROM `posts` ORDER BY `posts`.`id` ASC LIMIT 1
  Comment Load (0.5ms)  SELECT `comments`.* FROM `comments` WHERE `comments`.`post_id` = 1

post.comments.size
  Post Load (0.4ms)  SELECT `posts`.* FROM `posts` ORDER BY `posts`.`id` ASC LIMIT 1
  Comment Count (1.9ms)  SELECT COUNT(*) FROM `comments` WHERE `comments`.`post_id` = 1

count

Just like Ruby's count method, the count method in Rails counts all the records in a collection that satisfy a given condition.

There are two variations of this method:

1. When a block is not provided, returns the count of all records in the collection

posts = Post.all

# SELECT COUNT(*) FROM `posts`
posts.count

2. When a block is provided, calls the block with each collection element and returns the count of elements for which the block returns a truthy value.

Post.all.count { |p| p.title.include?('-') }

I use the count method when I need the count of elements that match a certain criteria. Otherwise, I just stick to one of the length or size methods.


I hope you liked this article and you learned something new. If you have any questions or feedback, please send me an email. I look forward to hearing from you.

Subscribe to Akshay's Blog

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe