Understanding Block Arguments in Ruby

Ryan David Workman
Aug 8, 2017 · 6 min read
It’s a Teenyverse inside a Miniverse inside a Microverse. Credit: RosesMakesArt

Thanks to its readability and friendly-nature, Ruby is a great first language for any budding-developer to learn. The language abstracts a lot of the more complex concepts involved in software development allowing learners to jump right in and get familiar with the basic nature of writing code and opening a dialogue with a computer. One of the powerful advantages to using Ruby is its wide variety of enumerables that come right out of the box. With just a little insight, any new developer will be able to traverse, manipulate and control arrays and hashes within minutes using these powerful tools. The real strength of enumerables is unlocked, however, when one takes a look under the hood and begins to understand the “magic” and how to apply the basic concepts to his or her own codebase.

Before diving into the structure of enumerables and the power of passing blocks of code into methods, let’s take a minute refreshing ourselves on their general function. An enumeration, a term commonly used in mathematics and computer science, refers all of the elements of a set. This can be anything from an array of integers ([0,4,1,5,23,25]) to a hash of symbols and strings ({foo: ‘bar', bar: ‘foo'}). These sets of data can be enumerated by means of natural ordering meaning they can be iterated over from the zeroeth index to the last. In the world of Ruby an enumerator is simply a class that allows iteration both internally and externally. While enumerators can get a bit complicated, at a high level, the class just takes a set of data and iterates over it.

An enumerable in Ruby essentially abstracts the enumerator class and provides a user with several traversal and searching methods for collection classes. The simplest enumerable being #each which executes a set of instructions on a collection of data and returns the original data structure.

Notice that when we call #each on fib, we pass in code telling it to print the number multiplied by two. Looking back at our enumerator example, we see that the number variable is whatever fib.next returns, so the first run-through of our #each method, number is equal to 1 since the zeroeth index of fib is one. One times two is two, so Ruby prints two. The enumerator now calls fib.next and gets one again, since that is the value of the first index. Ruby then prints the result of one times two and proceeds to call fib.next and so forth until it gets to the end of the array. The real magic is happening within the do and end. It may not look like it at first but, behind the syntactic sugar, all that is happening is the method #each is being called with a block of code being passed into it.

Take a look at the example on the left. While these look slightly different, they are doing exactly the same thing. It’s convention that simple, one-line blocks of code are passed in using curly-braces and inline styling, while more complex blocks of code use the multi-line do and end. At the end of the day though, do and end translate to { and }. Now that we have seen how we are just passing blocks of code into enumerable methods, let’s take a look at how all of this is being executed behind the curtain.


As we begin to dive into utilizing blocks of code in Ruby methods, it’s important to keep in mind that these concepts can get a bit confusing and the idea of yield and #call tend to trip people up at first. Just take it slow and don’t be too hard on yourself. You’ll be a master of blocks before you know it.

In the simplest sense, yield just executes the code in the block passed to the method. Any method written in Ruby without any defined parameters can have a block of code passed to it. Calling yield within that method then executes the code that was passed to it.

In #bar we call yield before printing ‘bar’ and then call a second yield before printing ‘barbar.’ When we call #bar we pass a block of code using do and end which prints ‘foo.’ Therefore, when we run that code, #bar will execute the block of code passed to it printing ‘foo,’ it will then print ‘bar’ and a new line. After that, #bar will execute that same block of code passed to it a second time which will print ‘foo’ and then print ‘barbar.’ In this simple example, we see that yield is doing nothing more than executing the block of code passed to it.

Now that we know how yield is handling the block of code passed to the method, what do the pipes mean when we call fib.each{ |num| puts num }? The simplest way to think of the pipes is that they are defining parameters that yield will pass.

We can see in this example that calling #say_hi will execute any block of code passed to it and expect to pass ‘George’ and ‘red’ as two arguments into the block of code passed to it. Notice that the second time we call #say_hi we drop the sentence and names of the parameters. yield still passes ‘George’ and ‘red’ to the block of code and executes it.

Now that we have a basic idea of how yield is handling blocks passed to methods, let’s look at other ways we can achieve this. Many times, developers will have a &block tacked at the end of a list of parameters. While it may look intimidating at first, we’ll see that &block can achieve the same results as yield.

The method #double takes two arguments, a number and a block of code. Since the variable&block is denoted using an ampersand, Ruby expects a block of code to be passed in and converted to a Proc class. These classes are just blocks of code bound to a set of local variables. Calling #call on the Proc object then executes the code exactly the same as yield. With all that being said, block.call(number * 2) could be replaced with yield(number * 2) and execute exactly the same way.


Now that understand the basic constructs of passing blocks to methods in Ruby, we can bring it full-circle and build out our very own #each method to iterate over an array which will be passed in as an argument.

Without using any of Ruby’s out-of-the-box enumerables, we recreated the functionality of #each by passing the array we are iterating over as well as the block of code that we want to perform on each element of that array as arguments. Then, using a simple while loop, we go through the array and call the block of code that was passed through on the given element of the array. With just this basic construction, we can start to understand what is happening under the hood when we call enumerables in Ruby and think of ways to develop our own enumerables.


If you are looking for a good way to practice these techniques and get more comfortable with using blocks of code and Procs, I highly going through a list of the most popular enumerables and recreating them. Feel free to take a look at some of the Ruby methods I recreated in this repo. For more information regarding Procs, check out the Ruby docs.

Ryan David Workman

Written by

Lead engineer at Airbo. Turing School of Software and Design alumnus. Lover of food, beer, bash. :(){ :|:& };:

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade