Labs ICT
โญ Pro Login

The Enumerable Module

Powerful iteration built into Ruby.

3 min read | Ruby Tutorial
โญ

Want the full learning experience?

Get structured courses, certificates, projects, and instructor support with LabsICT Pro.

Explore Pro Courses

The Enumerable Module

Enumerable is one of Ruby's most powerful modules. When you define a single method called each, you automatically get access to dozens of methods: map, select, reject, sort, min, max, and many more. This is the magic of Ruby's design โ€” define one thing, get everything.

class WordCollection
  include Enumerable

  def initialize(words)
    @words = words
  end

  def each(&block)
    @words.each(&block)
  end
end

words = WordCollection.new(["apple", "banana", "cherry", "date"])

# All these work automatically:
puts words.map(&:length).inspect     # => [5, 6, 6, 4]
puts words.select { |w| w.start_with?("b") }.inspect  # => ["banana"]
puts words.sort.inspect              # => ["apple", "banana", "cherry", "date"]
puts words.min                       # => "apple"
puts words.max                       # => "date"
puts words.any? { |w| w.length > 5 } # => true
puts words.count                     # => 4

Enumerable is Everywhere

Array, Hash, and Range all include Enumerable. That's why you can use map on a hash, select on a range, and sort on an array. They all define each, which gives them everything.

# Array includes Enumerable
puts [3, 1, 2].sort.inspect       # => [1, 2, 3]
puts [1, 2, 3, 4].select(&:even?).inspect  # => [2, 4]

# Hash includes Enumerable
hash = { a: 1, b: 2, c: 3 }
puts hash.map { |k, v| "#{k}=#{v}" }.inspect
# => ["a=1", "b=2", "c=3"]

# Range includes Enumerable
puts (1..10).select(&:odd?).inspect  # => [1, 3, 5, 7, 9]
puts (1..5).reduce(:+)              # => 15

Custom Enumerable: Build Your Own

You can create your own Enumerable class. Define each, and you get map, select, sort, min, max, group_by, partition, and dozens more for free. One method, endless possibilities.

class Fibonacci
  include Enumerable

  def initialize(limit)
    @limit = limit
  end

  def each
    a, b = 0, 1
    while a <= @limit
      yield a
      a, b = b, a + b
    end
  end
end

fib = Fibonacci.new(100)

puts fib.select(&:even?).inspect
# => [0, 2, 8, 34]

puts fib.map { |n| n * 2 }.inspect
# => [0, 2, 2, 6, 10, 16, 26, 42, 68, 110]

puts fib.max  # => 89
puts fib.min  # => 0

Enumerable Methods You'll Use

Here are the most commonly used Enumerable methods. Once you internalize these, you'll write Ruby code that reads like English.

data = [5, 3, 8, 1, 9, 2, 7]

# Finding things
puts data.find { |n| n > 6 }         # => 8 (first match)
puts data.select { |n| n.odd? }.inspect  # => [5, 3, 1, 9, 7]
puts data.reject { |n| n > 5 }.inspect   # => [5, 3, 1, 2]

# Aggregating
puts data.reduce(:+)                 # => 35
puts data.min                        # => 1
puts data.max                        # => 9
puts data.sum                        # => 35

# Transforming
puts data.map { |n| n * 10 }.inspect  # => [50, 30, 80, 10, 90, 20, 70]
puts data.sort.inspect               # => [1, 2, 3, 5, 7, 8, 9]
puts data.reverse.inspect            # => [7, 2, 9, 1, 8, 3, 5]

# Checking
puts data.any? { |n| n > 8 }        # => true
puts data.all? { |n| n > 0 }        # => true
puts data.none? { |n| n < 0 }       # => true
puts data.include?(5)               # => true

The Power of One Method

This is Ruby's philosophy in action. Instead of giving you a hundred methods to implement, Ruby says: just define each, and we'll handle the rest. It's elegant, DRY, and powerful. When you truly understand Enumerable, you understand what makes Ruby special.

class Primes
  include Enumerable

  def initialize(count)
    @count = count
  end

  def each
    n = 2
    yielded = 0
    while yielded < @count
      yield n if prime?(n)
      yielded += 1 if prime?(n)
      n += 1
    end
  end

  private

  def prime?(n)
    return false if n < 2
    (2..Math.sqrt(n)).none? { |i| n % i == 0 }
  end
end

primes = Primes.new(10)
puts primes.inspect              # => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
puts primes.select { |p| p > 10 }.inspect  # => [11, 13, 17, 19, 23, 29]
puts primes.map { |p| p * 2 }.inspect      # => [4, 6, 10, 14, 22, 26, 34, 38, 46, 58]

๐Ÿงช Quick Quiz

What module gives you free iteration methods?