At the core of any enumerator is the ability to respond to an #each
call.
With that in mind, we prepare any class for being turned into an enumerator.
Consider this class SquaresCollection
that allows you to turn an array of
integers into an array of its squares.
class SquaresCollection
def initialize(items)
@items = items
end
def run
@items.map { |item| item * item }
end
end
SquaresCollection.new([1,2,3]).run #=> [1,4,9]
We can work with this, but it opts out of Ruby's enumerator offerings.
We can, instead, provide an #each
method which allows instances of our
SquaresCollection
class to be turned into enumerators.
class SquaresCollection
def initialize(items)
@items = items
end
def each
return enum_for(:each) unless block_given?
@items.each do |item|
yield item * item
end
end
end
Here is how we can use it:
sc = SquaresCollection.new([1,2,3])
puts sc.to_enum
#=> <Enumerator ...>
puts sc.to_enum.map { |item| "* #{item} *" }
#=> ["* 1 *", "* 4 *", "* 9 *"]
The #to_enum
method
looks for an #each
method on the instance's class and uses that to create an
enumerator.