Imagine a situation where you have a collection of string that you want to map to tag objects, but you want the first one to have a default flag.
first = true tags = line.split(",").map do |name| tag = Tag.new(default: first, name: name) first = false tag end
Alright, that works, but it’s not pretty. Is there a way to make it nicer?
Of course there is, at least for ruby 1.9.3 and higher. If you call a
map method on a collection without any block it returns an
Enumerator class since ruby 1.9.
And a method
Enumerator#with_index that was introduced in ruby 1.9.3 adds an index to our iteration, so combining those two together we get
tags = line.split(",").map.with_index do |name, index| Tag.new(default: index == 0, name: tag_name) end
Elegant and much easier to read.
Enumerator is very powerful and helpful concept and with the combination of
Enumerable module only the sky is the limit.
Also omitting the block and returning
Enumerator instead of an array works not just for
map, but for similar methods like
group_by and others. Check out the docs and make your code nicer.