Forward ActiveRecord::Relation#count to Enumerable#count

Rohit Arolkar

Rohit Arolkar

May 1, 2017

This blog is part of our  Rails 5.1 series.

Let's say that we want to know all the deliveries in progress for an order.

The following code would do the job.

1
2class Order
3  has_many :deliveries
4
5  def num_deliveries_in_progress
6    deliveries.select { |delivery| delivery.in_progress? }.size
7  end
8
9end
10

But usage of count should make more sense over a select, right?

1
2class Order
3  has_many :deliveries
4
5  def num_deliveries_in_progress
6    deliveries.count { |delivery| delivery.in_progress? }
7  end
8
9end
10

However the changed code would return count for all the order deliveries, rather than returning only the ones in progress.

That's because ActiveRecord::Relation#count silently discards the block argument.

Rails 5.1 fixed this issue.

1
2module ActiveRecord
3  module Calculations
4
5    def count(column_name = nil)
6      if block_given?
7        to_a.count { |*block_args| yield(*block_args) }
8      else
9        calculate(:count, column_name)
10      end
11    end
12
13  end
14end
15

So now, we can pass a block to count method.

If this blog was helpful, check out our full blog archive.

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.