A little (more) syntactic sugar in Rails

Posted by trevor Mon, 12 Jun 2006 17:48:56 GMT

This little extension to Ruby’s Array class is making the rounds:


class Array
  def sum
    inject(0) { |m, v| m + v }
  end
end

# Use it thusly:
[1,2,3,4,5].sum # => 15

Nice. But what if we want to sum a member of each array element, such as the ‘price_cents’ attribute on a bunch of ActiveRecord objects?


@order.line_items.collect {|x| x.price_cents}.sum
# or (my preference) using Symbol's to_proc method:
@order.line_items.collect(&:price_cents).sum

Even with the sugar that Symbol#to_proc adds, it’s just a bit… well, blech. We can do better:


class Array
  def sum
    if block_given?
      inject(0) { |m, v| m + yield(v) }
    else
      inject(0) { |m, v| m + v }
    end
  end
end

# Now we can say:
@order.line_items.sum(&:price_cents)

That’s just so much clearer.

Update: a recent changeset in the rails trunk adds a ‘sum’ method to Enumerable. It’s different from what I present above in that it only works with a block – which is okay for me because that’s my main usage pattern anyhow.

Comments

(leave url/email »)