Ruby Blocks 101

For the longest time, yield had my mind spinning in circles. The teachers here at Flatiron have provided us with many articles on the topic, and I’ve even done my own research to really try to get a handle on it.

You could just watch this instead

If you’re like me and struggling with Ruby blocks, I recommend this slideshow created by Jonathan Cairns.

What I like about Jonathan’s slideshow: it reads exactly like a tutorial. He starts out with some simple examples and then ramps it up. Best of all, he’ll show you some code, you can think about the answer, then he shows you the answer when you navigate forward. BRILLIANT.

In this post, I’ll attempt to share what I understand about Ruby blocks and yield.

WTB: What the block?

A block is simply one or more lines of code. Let’s look at some Ruby examples.

A one-line block is bound by curly braces { }.

1
2
3
# Example 1: a one-liner block

5.times { puts "hello world" }

For longer blocks, they’re bound by the keywords do and end.

1
2
3
4
5
6
# Example 2: a multi-line block

5.times do
  puts "hello world"
  puts "goodnight y'all"
end

The following is functionally equivalent to the first example, but convention dictates that one-liners should be enclosed with curly braces { } as demonstrated in Example 1.

1
2
3
4
5
# Example 3: a one-liner written with do-end

5.times do
  puts "hello world"
end

Passing the block

Let’s start with some examples. They do the same exact thing. The only difference is the first does it by accepting an argument, the other with a block.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Example 4: say_3_times method with arguments

def say_3_times(string)  # method
  puts string
  puts string
  puts string
end

say_3_times("Let it be")  # the caller

# OUTPUT:
Let it be
Let it be
Let it be
1
2
3
4
5
6
7
8
9
# Example 5: say_3_times method with block

def say_3_times  #method
  yield
  yield
  yield
end

say_3_times { puts "Let it be" }  # the caller

Order of execution:

  1. say_3_times is called
  2. we enter the method definition def say_3_times
  3. the 1st yield is called
  4. we enter the block of the caller
  5. puts is executed once
  6. we return to next line of def say_3_times
  7. the 2nd yield is called
  8. we enter the block of the caller
  9. puts is executed once
  10. we return to next line of def say_3_times
  11. the 3rd yield is called
  12. we enter the block of the caller
  13. puts is executed once
  14. we return to next line of def say_3_times
  15. we reach end of method definition def say_3_times
  16. done!

What it means to yield

Based on the order of execution, we can make the following conclusion on yield’s behavior.

yield will execute the block of the caller

Why would you ever use yield?

When I first saw yield demonstrated, I thought, “Well, that’s nice. When would I ever use it?”

Turns out that it’s used everywhere by Ruby experts. It’s used in your BFF array method: .each.

I’ll expand on practical use of yield in future posts. Stay tuned.

Additional References

Definition of block according to _why http://mislav.uniqpath.com/poignant-guide/book/chapter-3.html