Certain Ruby methods return Enumerator objects (not to be confused with the Enumerable module) when they are not passed a block. For example, the map() method returns an Enumerator object when it is not passed a block:
["foo", "bar"].map # => #<Enumerator: ["foo", "bar"]:map>
The Enumerator class has several useful methods to call on Enumerator objects, such as with_index(), with_object(), peek(), and next().
Use the with_index() method to convert [“a”, “b”, “c”] to [[1, “a”], [2, “b”], [3, “c”]].
["a", "b", "c"].map.with_index(1) do |letter, index| [index, letter] end
Enumerator objects can be initialized with the Enumerator#new method:
e = Enumerator.new([1, 2, 3])
The peek method shows the next object of the enumerator, but does not move the internal position forward.
e.peek() # => 1
e.peek() returns 1 because the iteration has not started yet, so the “next” object is still the first object in the array.
The next() method shows the next object of the enumerator and moves the internal position forward. The documentation has more Enumerator methods that may be handy.
I find the with_index() Enumerator object to be the most useful. I find inject() to be easier to work with than with_object() and have yet to find good practical applications for peek(), next(), etc.