Ruby is an incredible programming language packed with modern features and tools for most development environments. Ruby has one powerful, often overlooked feature: blocks.
The essence of this article is to discuss and understand what Ruby blocks are, how they work, and how we can use them in our Ruby programs.
We will start with the basic syntax and then discuss features such as yield, which can be intimidating for new Ruby users.
What are Ruby Blocks?
As is the case in other programming languages, a block or closure is an anonymous function that you enclose inside a do and end keywords for inline blocks.
Blocks allow you to group a code block into separate components that you can pass during method call as parameters.
There are two ways of defining a block in Ruby: The first is using the do..end keyword, the other is using a pair of curly braces.
Do..end block is mainly used when defining a block of code that spans multiple lines, while curly braces {} are used when defining a block of code that spans a single line.
You pass the arguments of a block between a pair of pipe characters | |
HINT: Whether you use a single line or multi-line block, the functionality does not change. However, for readability purposes, use curly braces for a single line block and do-end for multi-line blocks.
Basic Example
The following are two simple examples of a Ruby block, one using curly braces while the other uses do..end.
['Java', 'C', 'C++'].each { |i| puts i}
# multi-line -> do..end
['Java', 'C', 'C++'].each do |i|
puts i
end
Both of the examples above produces similar results:
- Java
- C
- C++
The above example applies ruby blocks in the simplest form: we pass the block in each method of the array object. Pass the block’s arguments inside a pair of pipe characters; in the above example, the argument is i. Finally, we output the block functionality inside the block’s body (in this example, puts).
Understanding Ruby Yield Keyword
You can use Ruby blocks inside a standard method. The functionality to perform that action is courtesy of the yield keyword.
Let us discuss the yield keyword in detail.
What is Yield in Ruby?
The keyword yield in Ruby allows you to call a defined block inside a Ruby method.
How it Works
Let us consider an example that will help us understand how the yield keyword work. Consider the simple Ruby method shown below:
puts "Hello!"
end
The example above is a simple Ruby method that prints “Hello!”.
If we want to add more flexibility to the program, we can allow the user to pass an argument during method invocation.
Hence, we can code the method as:
puts "Hello, " + name
end
hello("USA")
In the second example, we have a little flexibility as we can pass any name to the method as an argument.
We can extend this even further by using a Ruby block. When we pass the block inside the method, it will be executed and return the results.
Yield Method Definition
To create a method that accepts a block, we use the keyword yield. The general syntax is as shown:
yield
end
Upon definition, we can call the method and pass a block of code. The method will execute the code and return the result.
Passing a Ruby Block to a Method
We can pass a block to the method using the block syntax. For example, we can call the above method with a syntax as:
As long as the method contains the yield keyword, you can pass any code block and execute it.
NOTE: Once you define a yield keyword inside a method, you MUST pass a block when calling the method. Otherwise, you will get a “no block given (yield)” error.
Example 2
Let’s take another example:
puts "before yield."
yield
puts "after yield."
end
hello {puts "I yield"}
The above example illustrates how the execution of a method using yield works. The program output is below:
I am yield
after yield
Ruby Block Arguments
Ruby allows you to pass arguments to the Ruby block. Block arguments are defined in the yield block and serve as the block parameters.
The order in which you pass the argument is critical as the block will accept them in the set order.
yield("John Doe", 20)
end
hello { |name, age| puts "Hello #{name}, you are #{age} years old"}
The parameters defined inside the block have a local scope and are only available in the context of the block.
Hence, you will get an undefined variable used outside the block scope.
Example 3
The functionality of the block does not change on single-line or multi-line blocks. We can illustrate this using the example below:
yield(7)
end
area do
puts "The area of the cirle is #{7 * 3.14159}cm2"
end
The output from the above example is:
This shows that either multi-line or single-line blocks, the functionality remains the same.
Explicit Blocks
In the previous examples, we have defined the blocks as implicit. However, we can also describe them as explicit.
Explicit blocks mean we assign a name to the parameter list of the method.
block.call
end
example {puts "Explicit block example" }
You pass the name of the block inside after the ampersand. Using the block’s name, you can pass the saved block to another method.
Block Error Handling
In the previous sections, we mentioned that the yield block is mandatory. However, you can implement a simple error handling logic if the yield is provided. We do this by using the block_given? Kernel method.
The method returns a Boolean value of true if the yield is available and false if otherwise.
Consider the simple example below:
if block_given?
yield
else
puts "Nothing happened...[ERROR]"
end
end
If we call the method with the required yield value, the output will be:
Hello there!
On the other hand, calling the method without yield will execute the else block as:
Nothing happened...[ERROR]
Using the value from the block_given? method, you can implement error handling logic when there is no yield value.
Conclusion
In this guide, we discussed Ruby blocks, what they are, how they work, and how to use them in your projects.
Thank for reading!