I Have Written Ruby for Years and Just Discovered Enumerator#feed

I Have Written Ruby for Years and Just Discovered Enumerator#feed
I Have Written Ruby for Years and Just Discovered Enumerator#feed

June 15, 2026

Ruby is full of delightful surprises.

Even after years of writing Ruby professionally, I still occasionally stumble upon a feature that makes me stop and think:

“Wait… Ruby can do that?”

Recently, that feature was Enumerator#feed.

Most Ruby developers are familiar with Enumerators. We use them every day through methods like map, select, and each. Some of us have even created custom Enumerators using Enumerator.new.

But very few developers seem to know about feed.

Tokyo Topographic Map
Built for Ruby on Rails

Build Maps Without
Google APIs

Generate beautiful production-ready maps directly from your Rails backend. Fast rendering, zero external dependencies, full control.

✓ No API fees ✓ Self-hosted ✓ Rails Native ✓ Fast Rendering
Why developers switch
Replace expensive map stacks.

Stop relying on third-party map billing and bloated JS libraries. Render static or dynamic maps directly in Ruby.

Try It Now
Tokyo MapView Demo

A Simple Enumerator

Let’s start with something familiar:

e = Enumerator.new do |y|
y << 1
y << 2
y << 3
end
e.next # => 1
e.next # => 2
e.next # => 3

The Enumerator yields values, and the caller consumes them one at a time.

Nothing unusual so far.

When Enumerators Need Input

Now let’s look at something different.

e = Enumerator.new do |y|
input = y.yield("What is your name?")
y << "Hello #{input}"
end

Running it produces something interesting:

e.next
# => "What is your name?"
e.feed("Rubyist")
e.next
# => "Hello Rubyist"

The value passed to feed becomes the return value of yield inside the Enumerator.

This means the Enumerator isn’t just producing values.

It’s receiving them too.

A Two-Way Conversation

Most developers think of Enumerators as one-way streams:

Enumerator -> Caller

With feed, the relationship becomes bidirectional:

Enumerator <-> Caller

The Enumerator pauses execution.

The caller injects a value.

Execution resumes using that value.

At this point, Enumerators start feeling surprisingly similar to coroutines.

Building a Tiny Interactive Workflow

Here’s a more complete example:

calculator = Enumerator.new do |y|
a = y.yield("First number?")
b = y.yield("Second number?")
y << a + b
end
calculator.next
# => "First number?"
calculator.feed(10)
calculator.next
# => "Second number?"
calculator.feed(20)
calculator.next
# => 30

The Enumerator maintains state between pauses without requiring:

  • Instance variables
  • Classes
  • External state management

Everything happens naturally inside the Enumerator itself.

How Does It Work?

The important detail is that:

value = y.yield("something")

doesn’t simply emit a value.

It creates a suspension point.

When execution resumes, value becomes whatever was provided through:

enumerator.feed(...)

In other words:

input = y.yield("Enter value")

behaves almost like:

input = receive_value_from_caller

except the Enumerator controls when the pause happens.

Why Does Ruby Have This?

Ruby’s Enumerator implementation borrows ideas from generators and coroutine-like execution models.

The feed method allows a suspended Enumerator to receive information from the outside world before continuing.

Most day-to-day Ruby code doesn’t need this capability, which is probably why so many developers never encounter it.

When developers need bidirectional communication, they typically reach for:

  • Plain objects
  • Service classes
  • State machines
  • Fibers
  • Callbacks

As a result, feed remains one of Ruby’s lesser-known features.

Is It Useful?

For a typical Rails application?

Probably not.

You won’t suddenly improve your controllers or Active Record models by introducing Enumerator#feed.

However, it becomes interesting when building:

  • Interactive workflows
  • DSLs
  • Parsers
  • Custom interpreters
  • Educational tools
  • Experimental concurrency systems

Even if you never use it in production, understanding it provides insight into how Ruby’s execution model works under the hood.

Final Thoughts

One of Ruby’s greatest strengths is its depth.

You can be productive for years without learning every corner of the language, yet occasionally discover a feature that changes how you think about familiar concepts.

Enumerator#feed is one of those features.

It’s not something you’ll use every day.

But it’s a fascinating reminder that Ruby’s simple APIs often hide surprisingly sophisticated behavior.

And sometimes, years into your Ruby journey, you still find yourself saying:

“Wait… Ruby can do that?”

Article content

Leave a comment