Ruby

What is the Meaning of DO in Ruby?

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.

# single line - {}
['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:

def hello
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:

def hello(name)
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:

def hello
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:

hello {puts "Hello world" }

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:

def hello
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:

before yield
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.

def hello
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:

def area
yield(7)
end
area do
puts "The area of the cirle is #{7 * 3.14159}cm2"
end

The output from the above example is:

The area of the cirle is 21.99113cm2

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.

def example(&block)
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:

def hello
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 {puts "Hello there!"}
Hello there!

On the other hand, calling the method without yield will execute the else block as:

hello
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!

About the author

John Otieno

My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list