Blocks
Ruby is a dynamic, beginner-friendly programming language, and blocks — chunks of code you hand to a method — are the feature that makes Ruby feel uniquely expressive.
Learn Blocks in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
By the end of this lesson you'll pass blocks with do...end and {' '} , and write your own methods that run them with yield .
What You'll Learn in This Lesson
1️⃣ Passing Blocks to Methods
Many built-in methods accept a block. You write the block right after the call, using do...end for several lines or {' '} for one. The method feeds values to your block through parameters named between |pipes| .
2️⃣ Writing Methods that Take Blocks (yield)
Your own methods can accept blocks too. Call yield to run the block — as often as you like — and pass arguments with yield(value) . To make a block optional, check block_given? first so you never yield into thin air.
Your turn. A repeat method is sketched for you — it yields the current count. Run it as-is, then customise the block message.
Write a method that prints a line before and after running a block. This "do something around a block" pattern appears all over Ruby (think File.open ). Run with ruby banner.rb .
📋 Quick Reference — Blocks
Practice quiz
What does yield do inside a method?
- Returns from the method immediately
- Runs the block that was passed to the method
- Pauses execution for one second
- Defines a new block
Answer: Runs the block that was passed to the method. yield invokes the block attached to the current method call.
Which two syntaxes can you use to write a block?
Blocks use do...end (usually multi-line) or curly braces { } (usually one-line).
By convention, when do you use { } instead of do...end?
- For short, single-line blocks
- Only inside classes
- When the block takes no parameters
- For multi-line blocks
Answer: For short, single-line blocks. Convention reserves { } for short one-liners and do...end for multi-line blocks.
What does block_given? return?
- The block's return value
- true only when a block was passed to the current method
- The number of block parameters
- Always true inside a method
Answer: true only when a block was passed to the current method. block_given? is true exactly when a block was attached to the call, so you can yield safely.
Calling yield when no block was passed raises which error?
- NoMethodError
- ArgumentError
- LocalJumpError
- FrozenError
Answer: LocalJumpError. yield with no block raises LocalJumpError; guard with block_given? to avoid it.
Where do block parameters go?
- In parentheses after the method name
- Between vertical bars (pipes), like |n|
- Inside square brackets
- After the keyword yield only
Answer: Between vertical bars (pipes), like |n|. Block parameters are named between pipes: { |n| n * 2 } or do |item, i| ... end.
Given def twice; yield; yield; end, how many times does the block run?
- Zero
- Once
- Twice
- It raises an error
Answer: Twice. Each yield runs the block once, so two yields run it twice.
each_with_index yields how many values to its block?
- One (the element)
- Two (the element and its index)
- Three
- Zero
Answer: Two (the element and its index). each_with_index yields the element and its position, so name two parameters |item, i|.
With def with_tax(p); yield(p * 1.2); end, what does with_tax(100) { |t| puts t } print?
- 100
- 120.0
- 20.0
- 1.2
Answer: 120.0. yield passes 100 * 1.2 = 120.0 into the block, which prints it.
How many times does [1, 2, 3].each { |n| puts n } run the block?
- Once
- Twice
- Three times
- Zero times
Answer: Three times. each runs the block once per element — three times for a three-element array.