Ruby Blocks Tutorial

In this section, we will learn what the blocks are and how to use them in Ruby.

What is block in Ruby?

A Ruby block is just a body where you can write code there and pass this block to methods that accept block as their input.

The methods then run the written source code in the block when we call those methods.

You can somehow think about it as a method without a name! But there are some differences here and in order to learn them, let’s first get into the details of how to create a block in the first place.

Defining a Method that Takes a Block in Ruby

Alright, creating a block has two phases:

  • First, you define a method that can take a block.
  • Then you create a block that can be passed to a method (this part is explained in the section down below).

So in order to create a method to take a block as its argument, we set its last parameter like this:

&block

Note that the last parameter starts with the & character. (The name of the parameter doesn’t matter and it could be anything as long as it starts with the & symbol.)

For example:

def function_name (param1, param2, &block)

Now within the body of the method, if we want to call that block, we need to use the specified name (but without the & symbol) and call the “call” method.

Note: a block is treated as an object within the body of a method and it has a method called “call”. Now in order to invoke the target block in your method, all you need to do is to invoke the “call” method.

For example:

def function_name (param1, param2, &block)

    block.call #this will invoke the body of the target block to be executed.

end

How to create a block in Ruby? (Ruby Block Syntax)

Alright, after creating a method that is able to take blocks, now we need to know how to create a block and pass that to such type of method!

Well, first of all, a block is created whenever we are calling a method that takes a block! Basically, it’s not like we first create a block somewhere and store it for later use! No, a block is created right when a method that needs a block is getting called.

We can create a block in two different ways:

– using do-end: The do-end syntax defines the border of a block and then we can write the necessary instructions within the body of that block.

Example:

function_name (argument1, argument2) do

#instructions of the block…

end

In this example we’re calling the function_name as if it has two parameters and so we’re passing two arguments for those parameters. But then comes the `do-end` block, where we defined the instructions of the block.

As you can see the block is created right where the function is called.

Note: we don’t need to pass a block as the argument of a method, just like the way we pass arguments to other parameters of a method! The accepted method of passing a block to a method is the way you saw above.

Note that other than using `do-end` syntax, we can use a pair of curly braces `{}` that defines the border to the block.

Be aware that the convention is to use the curly braces when there’s only one expression in the target block!

For example:

function_name(argument1, argument2) { #expression of the block }

Example: creating a block in Ruby using do-end syntax

def block_function (&block)
    puts "The message before calling the block" 
    block.call
    puts "The message after calling the block"
end 

block_function do
    puts "The message of the block"
end

Output:

The message before calling the block

The message of the block

The message after calling the block

Flow of control between a Method and Block

In this example, the `block_function` does not take any parameter except for the &block. This means the method is of those types that need a block when we call it.

Also, you can see that in the body of the `block_function` we’ve called the block using the `call` method.

Now, whenever this method is called, it should be followed with a block.

Alright, a little about the flow of control now:

When we first called the `block_function`, the program started to run the first and second instructions within the body of the method.

After that, it faces a call to the block.

So at this stage, it stops executing instructions within the block_function and moves into the body of the block we’ve defined for it.

Now it runs the instructions within the body of the block (which there’s only one statement and that’s a call to the puts method).

After finishing the execution of the entire instructions within the body of the block, your program will return to the body of the function right where the call to the block happened and continues to run the rest of instructions in that function.

Note: if there’s a method that takes a block and you don’t set a block for it at the time of calling it, you’ll get an error as a result.

Example: creating a block in Ruby using a pair of braces

Alright, let’s refactor the example above, and this time use the curly braces to define the border of the block.

def block_function (&block)
    puts "The message before calling the block" 
    block.call
    puts "The message after calling the block"
end 

block_function { puts "The message of the block"}


Output:

The message before calling the block

The message of the block

The message after calling the block

Defining a Method that takes a Block using Ruby yield Keyword

Other than setting the last parameter of a method to make it accept blocks, we can use the yield keyword as well.

If we use this keyword inside the body of a method, that means the method takes a block as well. Basically, just by using the yield keyword within the body of a method, we won’t need to modify the last parameter of the target parameter.

Example: using yield keyword to create a method that takes a block

def block_function 
    puts "The message before calling the block" 
    yield
    puts "The message after calling the block"
end 

block_function { puts "The message of the block"}

Output:

The message before calling the block

The message of the block

The message after calling the block

As you can see, now the method is capable of taking a block, but yet we didn’t add a parameter using & for this method.

Calling the same method with different Block in Ruby

When setting a method to work with a block, we can set different blocks with different body for that method every time the method is called.

Example: calling the same method with different block in Ruby

def block_function 
    puts "The message before calling the block" 
    yield
    puts "The message after calling the block"
end 

block_function { puts "The message of the block"}

puts "The second time we call the method..............."

block_function do
    puts "This is another block with different body"
    puts "Hello from the second block 🙂 "
end

Output:

The message before calling the block

The message of the block

The message after calling the block

The second time we call the method...............

The message before calling the block

This is another block with different body

Hello from the second block 🙂

The message after calling the block

Here, every time we call a method that takes a block, your program will jump into that block right after the yield statement is executed within the method.

Ruby Blocks with Parameters

So far, we’ve been working with blocks that didn’t take any argument! But blocks are also capable of taking arguments!

This is done when calling the `yield` statement. Basically, here we put any number of arguments that the target block needs.

For example:

yield arg1, arg2, arg3

The statement above means the target block needs three arguments to function properly.

Now let’s see how we can define a set of parameters for a block.

Ruby Blocks with Parameters Syntax:

{ |param1, param2, param_n| #instructions}

do

|param1, param2, param_n|

#instructions…

end

As you can see, within the body of the block we put two pipes `||` and inside those pipes, define the needed parameters.

Example: creating blocks with parameters

def block_function 
    puts "The message before calling the block" 
    yield "John","Doe"
    puts "The message after calling the block"
end 

block_function do |first_name, last_name|
    puts "The values that was passed to the block are: #{first_name}, #{last_name}"
end

Output:

The message before calling the block

The values that was passed to the block are: John, Doe

The message after calling the block

Ruby Blocks with Parameters Note:

Just like the parameters of methods that can take optional (default) default values, we can set optional values for the parameters of blocks as well.

Ruby Block: Calling a block multiple times

Within the body of a method, you’re not limited to just call a block once! As a matter of fact, you can call the block using the yield statement as many times as you needed.

That way, every time your program sees the yield statement, it will stop the program and jump into the block to run the instructions there and after that it will return to the method again to continue running the rest of instructions there.

Example: calling a block multiple times in Ruby

def block_function 
    puts "The message before calling the block" 
    yield "John","Doe"
    puts "***"
    yield "Omid","Dehghan"
    puts "***"
    yield "Elon","Musk"
    puts "The message after calling the block"
end 

block_function do |first_name, last_name|
    puts "The values that was passed to the block are: #{first_name}, #{last_name}"
end

Output:

The message before calling the block
The values that was passed to the block are: John, Doe
***
The values that was passed to the block are: Omid, Dehghan
***
The values that was passed to the block are: Elon, Musk
The message after calling the block

In this example, within the body of the block_function we have three calls to the block using the yield statement and so your program will jump into the block to run its instructions three times as a result.

More to Read:

Ruby blocks with return value Tutorial

Facebook
Twitter
Pinterest
LinkedIn

Top Technologies