ActiveSupport's Array#sum Mar 3

I found a great use for ActiveSupport’s Enumerable#sum while browsing through the Rails source code.

Ever write code where you need to gather a flattened array of child objects from the current array of ActiveRecord objects? For example:

  class Post < ActiveRecord::Base
    has_many :categories
  end

  class Category < ActiveRecord::Base
    belongs_to :post
  end

  posts = Post.includes(:categories).all

  # Gather all the categories into one array using #collect
  all_categories = posts.collect { |post| post.categories }
  all_categroies.flatten!

  # Another way to do it with inject - no need for the #flatten call
  all_categories = posts.inject([]) { |sum, post| sum += post.categories }

The code is verbose. If you use Enumberable#sum you don’t have to write the inject or the flatten line:

  post = Post.includes(:categories).all

  # Gathers all categories into one array
  all_categories = post.sum { |post| post.categories }

You could also use the shortcut form of that block:

  all_categories = post.sum(&:categories)

My favorite part of the code is the use of the + operator and applying that to Arrays. Array + Array = Bigger Array.