Blocks & Yield Mastery
Master Ruby blocks and the yield keyword. Learn how to create flexible, reusable code with blocks, understand the difference between do/end and curly braces, and harness the power of yield for creating elegant APIs and DSLs.
What are Blocks?
Blocks are chunks of code that can be passed to methods. They're Ruby's way of implementing closures - code that can be executed later with access to variables from its original scope.
Key Insight: Blocks are not objects - they're syntactic constructs that allow you to pass code to methods.
Block Syntax: do/end vs {}
Ruby provides two ways to write blocks: curly braces {} for single-line blocks and do/end for multi-line blocks.
Precedence Warning: Curly braces have higher precedence than do/end. Use do/end for method chaining.
The Yield Keyword
The yield keyword is how methods execute blocks. It's the bridge between your method and the block passed to it.
block_given? Method
Use block_given? to check if a block was passed to your method. This makes your methods more flexible.
Block Parameters
Blocks can accept parameters, and you can pass multiple values to yield.
Block Return Values
Blocks can return values, and yield can capture and use those return values.
Common Block Patterns
Interactive Code Runner
Practice Time: Try these block and yield examples and experiment with different block patterns. Understanding blocks will make you a more effective Ruby programmer.
Interactive Code Runner
Ruby Code Editor
Example 1: Custom Map Method
Example 2: Resource Management
Best Practices
1. Use do/end for Multi-line Blocks
Use do/end for blocks that span multiple lines and {} for single-line blocks. This improves readability.
2. Always Check block_given?
If your method can work with or without a block, always use block_given? to check before calling yield.
3. Use Blocks for Resource Management
Blocks are perfect for ensuring resources are properly cleaned up, like file handles or database connections.
4. Consider Method Chaining
When chaining methods, use do/end to avoid precedence issues with curly braces.
Common Pitfalls
1. Precedence Issues with {} vs do/end
Curly braces have higher precedence than do/end. This can cause unexpected behavior in method chaining.
2. Forgetting block_given?
Calling yield without checking block_given? will raise a LocalJumpError if no block is provided.
3. Variable Scope Confusion
Blocks create a new scope. Variables defined inside blocks don't affect the outer scope unless they're already defined.
Summary
Blocks and yield are fundamental to Ruby's expressiveness. They enable:
- Flexible method APIs that accept custom behavior
- Resource management with automatic cleanup
- Functional programming patterns
- Domain-specific languages (DSLs)
- Iteration and collection processing
Master blocks and yield to write more expressive, flexible, and Ruby-like code.