Overview

10 Collections central: Enumerable and Enumerator

The chapter explains that Ruby’s collection behavior is built around a simple agreement: if a class defines each and includes Enumerable, it automatically gains a large set of powerful querying, filtering, transforming, and traversal methods. This lets arrays, hashes, ranges, and sets share a common interface even though each collection still has its own special rules. The chapter also shows how this pattern can be extended to your own classes, and how Ruby sometimes optimizes or overrides enumerable behavior in specific collection classes when needed.

Much of the chapter is devoted to practical uses of enumerable methods. It covers Boolean checks like all?, any?, none?, and one?; searching and selecting with find, select, reject, and grep; grouping with group_by and partition; and element-focused operations such as first, take, drop, min, and max. It also highlights the difference between methods that return a single matching value, methods that return arrays, and methods whose usefulness depends on whether the underlying collection can actually be traversed in a finite way.

The later part of the chapter broadens the discussion to related iteration tools. It introduces methods that behave like specialized versions of each, including reverse_each, each_with_index, each_slice, each_cons, cycle, and inject, then moves to map as the key transformation method. From there, it explains strings as quasi-enumerable sequences of bytes, characters, code points, or lines, and then develops Enumerator as an object that stores iteration logic, supports chaining, protects collections from mutation, and even makes non-enumerable objects feel enumerable. The chapter ends by showing how lazy enumerators make it possible to work with infinite collections while still producing finite, useful results.

Summary

  • The Enumerable module and Enumerator class are two entities with close ties.
  • Enumerable methods are defined in terms of each and become available when a class mixes in Enumerable and responds to each.
  • Enumerators encapsulate iteration by binding their each method to a designated method on another object, providing Enumerable functionality.
  • Enumerators are not general-purpose proxies to another object; they siphon off values from one method on the other object.
  • Enumerators can be initialized by “loading” a Yielder object with the values to be provided during iteration.

FAQ

What is the role of the Enumerable module in Ruby collections?Enumerable provides a shared set of collection behaviors for objects that can be iterated over. It builds many useful methods on top of an object’s each method, giving collections common querying, searching, selecting, and transforming capabilities.
What must a class define before it can include Enumerable effectively?A class must define an each instance method that yields elements one at a time to a block. Once each exists, including Enumerable gives the class access to many collection-style methods.
How does Enumerable#find work?find iterates through a collection and returns the first element for which the block evaluates to true. If no element matches, it returns nil.
What is the difference between find_all, select, and reject?find_all and select are synonyms that return all matching elements in a new collection, usually an array. reject returns the elements that do not match the block condition.
How does grep differ from select?grep selects elements using the case-equality operator === rather than a boolean block condition. It is commonly used for pattern matching with regular expressions, but it also works with classes and ranges.
What is the difference between group_by and partition?group_by returns a hash that groups elements by the value returned from the block. partition returns two arrays: one for elements where the block is true and one for elements where it is false.
Why does Enumerable#first exist, but not Enumerable#last?first is general enough because iteration naturally begins at the start. last is not always meaningful, especially for infinite or non-finite iteration, where there may be no final element to find.
How do map and each differ?each is mainly for side effects and returns its receiver. map transforms each element, collects the results into a new array, and returns that array.
What is an Enumerator in Ruby?An enumerator is an object that encapsulates iteration behavior. It can provide an each method, support Enumerable methods, and let you control, chain, or defer iteration independently of the original collection.
How do lazy enumerators help with infinite collections?Lazy enumerators postpone work until results are needed, so operations on infinite collections can still produce finite answers. For example, you can lazily select values and then take only the first few results without evaluating the whole infinite sequence.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Well-Grounded Rubyist, Fourth Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Well-Grounded Rubyist, Fourth Edition ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • The Well-Grounded Rubyist, Fourth Edition ebook for free