Ruby: Blocks & Iterators
What you will learn
Blocks are Ruby's most distinctive feature — chunks of code you pass to methods. They power iterators, callbacks, and custom control structures.
Block syntax: do..end vs { }
# Multi-line (preferred for longer blocks)
[1, 2, 3].each do |n|
puts n * 2
end
# Single-line (preferred for short blocks)
[1, 2, 3].each { |n| puts n * 2 }
The |n| declares the block parameter(s). Each element is passed into the block.
Common iterators
Ruby's collection methods accept blocks and are the backbone of most Ruby code:
numbers = [1, 2, 3, 4, 5]
# each — iterate (most basic)
numbers.each { |n| puts n }
# map / collect — transform each element
doubled = numbers.map { |n| n * 2 } # [2, 4, 6, 8, 10]
# select / filter — keep elements that match
evens = numbers.select { |n| n.even? } # [2, 4]
# reject — keep elements that don't match
odds = numbers.reject { |n| n.even? } # [1, 3, 5]
# reduce / inject — accumulate
sum = numbers.reduce(0) { |acc, n| acc + n } # 15
Yield — calling a block from your own method
def repeat(times)
times.times { yield } # yield calls the block
end
repeat(3) { puts "Hello!" }
# Hello!
# Hello!
# Hello!
Block with explicit parameter (&block)
def with_logging(&block)
puts "Before"
result = block.call
puts "After"
result
end
with_logging { 2 + 2 } # prints Before, After, returns 4
Common mistakes
- Forgetting that
do..endand{ }have different precedence —do..endbinds to the outer call,{ }to the last argument. Use{ }for inline,do..endfor multi-line. - Confusing
map(returns new array) witheach(returns original array) - Using
returninside a block — it returns from the enclosing method, not just the block. Usenextto exit the block early instead.
Quick check below!