Skip to content

Ruby Loops and Iteration — each while until times and Enumerable Explained

DodaTech Updated 2026-06-28 9 min read

In this tutorial, you will learn about Ruby Loops and Iteration. We cover key concepts, practical examples, and best practices to help you master this topic.

Ruby loops and iteration include each for collections, while/until with conditions, times/upto for counting, and the loop keyword for infinite iteration with explicit break control.

What You'll Learn

  • All Ruby loop constructs: each, while, until, for, times, upto, downto, loop
  • Break, next, and redo for loop control
  • The Enumerable module and its iteration methods
  • When to use each type of loop

Why It Matters

Loops let you Process collections, read files, and handle repetitive tasks efficiently. In Durga Antivirus Pro, loops scan thousands of files for malware signatures. DodaZIP uses loops to compress batches of files. Doda Browser iterates over DOM elements, network requests, and cache entries. Without loops, every operation would need to be written manually for each item.

Real-World Use

A Rails background job might loop through 10,000 email recipients using each, while a data processing script uses while to read a CSV line by line until the file ends. The right loop choice makes code faster and clearer.

flowchart LR
    A["Loops & Iteration"] --> B["each"]
    B --> C["while/until"]
    C --> D["times/upto"]
    D --> E["loop + break"]
    E --> F["Arrays"]
    A:::current --> B
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style F fill:#f1f5f9,stroke:#94a3b8,color:#64748b

The Each Loop

each is the most common Ruby loop. It iterates over every element in a collection:

[1, 2, 3].each do |number|
  puts number * 2
end
# 2
# 4
# 6

The block variable |number| receives each element in turn. Ruby blocks can use do...end or { }:

[1, 2, 3].each { |n| puts n * 2 }

Each with Index

fruits = ["apple", "banana", "cherry"]
fruits.each_with_index do |fruit, index|
  puts "#{index}: #{fruit}"
end
# 0: apple
# 1: banana
# 2: cherry

Each on Different Types

# Hash
{ name: "Alice", age: 25 }.each do |key, value|
  puts "#{key}: #{value}"
end
# name: Alice
# age: 25

# Range
(1..5).each { |n| print n }
# 12345

# String lines
"line1\nline2\nline3".each_line { |line| puts line.strip }

While Loop

while runs as long as the condition is truthy:

count = 0
while count < 5
  puts "Count: #{count}"
  count += 1
end
# Count: 0
# Count: 1
# Count: 2
# Count: 3
# Count: 4

While Modifier

count = 0
puts count += 1 while count < 5
# 1 2 3 4 5

File Reading with While

file = File.open("data.txt", "r")
while line = file.gets
  puts line.chomp
end
file.close

Until Loop

until is the opposite of while — it runs while the condition is falsy:

count = 0
until count == 5
  puts "Count: #{count}"
  count += 1
end
# Count: 0
# Count: 1
# Count: 2
# Count: 3
# Count: 4

Until Modifier

count = 0
puts count += 1 until count == 5

For Loop

Ruby has a for loop, but it's rarely used because each is more idiomatic:

for i in 1..5
  puts i
end
# 1 2 3 4 5

# Equivalent each
(1..5).each { |i| puts i }

The difference: for doesn't create a new scope (the variable i exists after the loop), while each creates a block scope.

Times Loop

times repeats a block a specific number of times:

3.times { puts "Hello" }
# Hello
# Hello
# Hello

3.times do |i|
  puts "Iteration #{i}"
end
# Iteration 0
# Iteration 1
# Iteration 2

Upto and Downto

upto counts up, downto counts down:

1.upto(5) { |i| print i }
# 12345

5.downto(1) { |i| print i }
# 54321

# With step
1.step(10, 2) { |i| print i }
# 13579

The Loop Keyword

loop creates an infinite loop that you must break explicitly:

count = 0
loop do
  puts count
  count += 1
  break if count >= 5
end
# 0 1 2 3 4

This is useful for situations where you don't know the exit condition in advance:

# Read until end of file
loop do
  line = file.gets
  break if line.nil?
  puts line
end

Break, Next, and Redo

Break — Exit the Loop

[1, 2, 3, 4, 5].each do |n|
  break if n == 3
  puts n
end
# 1
# 2

Next — Skip to Next Iteration

[1, 2, 3, 4, 5].each do |n|
  next if n.even?
  puts n
end
# 1
# 3
# 5

Redo — Repeat Current Iteration

attempts = 0
[1, 2, 3].each do |n|
  attempts += 1
  puts "Attempt #{attempts}: #{n}"
  redo if attempts < 2
end
# Attempt 1: 1
# Attempt 2: 1
# Attempt 1: 2

Retry — Restart the Block (Legacy)

# In Ruby < 2.0, retry restarted the iteration
# In modern Ruby, retry only works in begin/rescue blocks

Enumerable Methods for Iteration

Ruby's Enumerable module provides sophisticated iteration beyond basic each:

numbers = [1, 2, 3, 4, 5]

# Select — filter truthy results
evens = numbers.select { |n| n.even? }
puts evens.inspect
# [2, 4]

# Reject — opposite of select
odds = numbers.reject { |n| n.even? }
puts odds.inspect
# [1, 3, 5]

# Map — transform each element
squares = numbers.map { |n| n ** 2 }
puts squares.inspect
# [1, 4, 9, 16, 25]

# Reduce — accumulate
sum = numbers.reduce(0) { |acc, n| acc + n }
puts sum
# 15

# Find — first match
first_even = numbers.find { |n| n.even? }
puts first_even
# 2

Loop Performance Considerations

# Different ways to sum 1 to 1_000_000

# each — most idiomatic
sum = (1..1_000_000).reduce(:+)

# while — fastest for simple loops
i, sum = 0, 0
while i < 1_000_000
  sum += i
  i += 1
end

# times — clean for known counts
sum = 0
1_000_000.times { |i| sum += i }

Common Mistakes

1. Infinite Loops

# Wrong — no increment
count = 0
while count < 10
  puts count
  # count never changes!
end

# Right
count = 0
while count < 10
  puts count
  count += 1
end

2. Modifying Collection During Iteration

# Wrong — skips elements
arr = [1, 2, 3, 4]
arr.each do |n|
  arr.delete(n)
end
# arr becomes [2, 4]

# Right — iterate over a copy
arr = [1, 2, 3, 4]
arr.dup.each do |n|
  arr.delete(n)
end
# arr becomes []

3. Forgetting Break Condition in Loop

# Wrong — runs forever
loop do
  puts "Running..."
end

# Right
loop do
  puts "Running..."
  break if condition_met?
end

4. Using For Instead of Each

# Less idiomatic
for fruit in fruits
  puts fruit
end

# More idiomatic
fruits.each { |fruit| puts fruit }

5. Confusing Next and Break

[1, 2, 3].each do |n|
  break if n == 2  # Stops iteration completely
  puts n           # Only prints 1
end

[1, 2, 3].each do |n|
  next if n == 2   # Skips to next element
  puts n           # Prints 1 and 3
end

6. Scoping Issues with For

# for doesn't create a new scope
for i in 1..3
  # ...
end
puts i  # 3 — i leaks!

# each creates a new block scope
(1..3).each do |j|
  # ...
end
puts j  # NameError — j is undefined

Practice Questions

1. What's the difference between while and until?

while runs while the condition is truthy. until runs while the condition is falsy. until x == 5 is the same as while x != 5.

2. How do you skip to the next iteration in a loop?

Use next. It jumps to the next iteration without executing the rest of the block.

3. What does break do in a loop?

break exits the loop entirely, stopping all further iterations.

4. Why is each preferred over for in Ruby?

each is more idiomatic, creates a new scope (no variable leakage), and allows chaining with other Enumerable methods. for is a holdover from other languages and is rarely used in idiomatic Ruby.

Challenge: Write a Ruby program that uses loop with break, next, and redo to simulate a retry mechanism that attempts an operation up to 3 times, with a 1-second delay between retries.

Solution
def unreliable_operation(attempt)
  puts "Attempt #{attempt}..."
  # Simulate failure for attempts 1 and 2
  attempt < 3 ? false : true
end

max_retries = 3
attempt = 1

loop do
  result = unreliable_operation(attempt)

  if result
    puts "Operation succeeded!"
    break
  elsif attempt >= max_retries
    puts "All attempts failed"
    break
  else
    puts "Failed, retrying..."
    attempt += 1
    sleep 1
    redo
  end
end

FAQ

{{< faq question="Which loop should I use most of the time?" >}} Use each for nearly everything. It's Ruby's most idiomatic loop and works with arrays, hashes, ranges, and any enumerable collection. Only use while/until when you need a condition-based loop without a collection. {{< /faq >}}

{{< faq question="What's the difference between each and map?" >}} each iterates and returns the original collection. map iterates and returns a new array with the transformed values. Use each for side effects and map for transformations. {{< /faq >}}

{{< faq question="How do I loop infinitely?" >}} Use loop do ... end with an explicit break condition. Ruby also supports while true or until false, but loop is the most idiomatic infinite loop. {{< /faq >}}

{{< faq question="Can I break out of nested loops?" >}} Yes. Use break to exit the innermost loop. Ruby doesn't have labeled breaks, so you may need to use a flag variable or catch/throw for deeply nested structures. {{< /faq >}}

{{< faq question="What happens if I call next inside a times loop?" >}} next works just like in any loop — it skips to the next iteration. The current iteration stops executing and the next one begins. {{< /faq >}}

Try It Yourself

Run this comprehensive loop demonstration:

# loops_demo.rb
puts "=== each example ==="
[1, 2, 3].each { |n| print "#{n * 2} " }
puts

puts "=== while example ==="
count = 0
while count < 3
  print "#{count} "
  count += 1
end
puts

puts "=== until example ==="
count = 0
until count == 3
  print "#{count} "
  count += 1
end
puts

puts "=== times example ==="
3.times { |i| print "#{i} " }
puts

puts "=== upto example ==="
1.upto(5) { |i| print "#{i} " }
puts

puts "=== loop + break example ==="
count = 0
loop do
  print "#{count} "
  count += 1
  break if count >= 3
end
puts

Expected output:

=== each example ===
2 4 6
=== while example ===
0 1 2
=== until example ===
0 1 2
=== times example ===
0 1 2
=== upto example ===
1 2 3 4 5
=== loop + break example ===
0 1 2

What's Next

Now that you understand loops, explore arrays in depth for storing and manipulating collections of data.

Topic Description Link
Ruby Arrays Array methods, map, select, reduce {{< ref "06-arrays" >}}
Ruby Hashes Hash syntax, symbol keys, merge {{< ref "07-hashes" >}}
Python Loops Compare Python iteration patterns Python

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro