Ruby's #each_with_object

Ruby’s #inject method is pretty popular. We often use it so that we don’t have to initialize local variables prior to executing a block. Check out the refactored code below using the inject method for an example:

hash = {}
['red', 'green', 'blue'].each do |color|
  hash[color] = 'primary'
end

# Using inject, we don't have to initialize the hash ahead of time

['red', 'green', 'blue'].inject({}) do |hash, color|
  hash[color] = 'primary'
  hash
end

While inject can be great for cleaning up blocks of code, I don’t like that you have to explicity return the hash on the last line of the block so that it can be passed to the next iteration. If, for example, I removed hash as the last line of the block, I would get an error that looks like this:

IndexError: string not matched
  from (irb):10:in `[]='
  from (irb):10:in `block in irb_binding'
  from (irb):9:in `each'
  from (irb):9:in `inject'
  from (irb):9

That’s no good. Luckily for us we have #each_with_object

['red', 'green', 'blue'].each_with_object({}) do |color, hash|
  hash[color] = 'primary'
end

As you can see, #each_with_object behaves like inject with two key differences:

The arguments you are sending to the block are reversed
You don’t need to explicity return the value to be passed on on the last line