The Enumerable#each_with_object method behaves very similarly to Enumerable#inject! There are only a couple of differences!

The block arguments are reversed

The inject method passes the block arguments in the following order:

  • The accumulator which is initially the object that inject was called with
  • The value/object for each member in the Enumerable that inject was called on

For the example below, subtotal is the accumulator and item is the value/object.

@order.line_items.inject(0) |subtotal, item|
  subtotal + (item.quantity * item.price)
end  

The arguments are the same with each_with_object but just in the reverse order!

The initial object is always returned

While inject allows you to perform some logic within a block and return a new accumulator object with each iteration, the each_with_object method always returns the initial object that it was called with.

This is useful in cases where the initial object is mutated each iteration.

quantities = LineItem.for_orders_today.each_with_object({}) |item, hash|  
  hash[item.name] ||= 0
  hash[item.name] += item.quantity
end  

Compare that to the inject equivalent!

quantities = LineItem.for_orders_today.inject({}) |hash, item|  
  hash[item.name] ||= 0
  hash[item.name] += item.quantity
  hash
end