Today I Learned

A Zero One initiative

Make fancy enums with `enum_for`

Did you know you can make your own enumerators in Ruby?

e = Enumerator.new do |y|
 [1,2,3].each { |i| y << i }
end

e.next    # => 1
e.next    # => 2
e.rewind
e.next => # => 1

Methods like each help convert things to an enumerable (using to_enum), but there is another way to create enums in Ruby. enum_for takes one argument which points to a method to bind to for enumeration. It allows make something enumerable when it technically isn’t, or when we can’t/don’t want to.

class DoReMi
  def sing
    lyrics.each { |l| yield l }
  end

  private

  def lyrics
    [
      "Doe, a deer, a female deer",
      ...
    ]
  end
end

Use enum_for to enumerate at your own pace. Let’s learn to shout the song backwards!

d = DoReMi.new
d.sing { |l| puts l }
# => Doe, a deer, a female deer
# => ...
e = d.enum_for :sing
e.map { |l| l.upcase }.reverse.each { |l| puts l }
# => ME, A NAME I CALL MYSELF
# => ...

# Wait, what's the last lyric again?
e.rewind
e.next.upcase # => "DOE, A DEER, A FEMALE DEER"
Looking for help? Each developer at Zero One has years of experience working with Ruby applications of all types and sizes. We're an active presence at Ruby conferences, and have worked on many of the web's Ruby on Rails success stories. Contact us today to talk about your Ruby project.