Ruby Blocks
Tags: beginners, ruby
Published: 2020-04-13 21:16:38

---
title: Ruby Blocks
published: true
description: Whats is Ruby Block and what does it do?
tags: beginners, ruby
---
## Ruby Block - what is that, and what does it do?
It has long been said that "Everying is an object in Ruby". Well, it is almost true. 

Despite such classes as [Class](https://ruby-doc.org/core-2.7.1/Class.html), [Module](https://ruby-doc.org/core-2.7.1/Module.html), as well as many others eventually being objects, there's an exception to the rule.
As you probably guessed, **block** is not an object. We cannot assign it to a variable or call a method [class](https://ruby-doc.org/core-2.7.1/Object.html#method-i-class) on it.

It is a chunk of code that we want to execute dynamically by putting it between `do...end` or between curly braces `{...}`. The benefit of blocks is that we don't need to store some statements into a method. Blocks serve as **part of a method signature** (method signature includes method name, list of arguments and a block) and must start on the same line after method arguments.

We often use blocks when we read or write into files, or when we want to perform certain operations while iterating via a collection, such as an Array or a Hash.

As an example let's take a look into [times](https://ruby-doc.org/core-2.7.1/Integer.html#method-i-times) method of the Integer class. 

```ruby
# Block written in one line
5.times { puts "Some code within a block" }

# Block written in multiple lines
5.times do
  puts "Some code within a block"
end
```
```
# Output in both cases
Some code within a block
Some code within a block
Some code within a block
Some code within a block
Some code within a block
=> 5
```

As per the implementation of the `times` method, an output `Some code within a block` will be printed out five times and integer `5` will be returned after that.

A block has to start on the same line as the method name and its parameters if any.
```ruby
# This is wrong
5.times
  { puts "Some code within a block" }
```

## Difference between `do..end` and curly braces `{}`.
- According to the [Ruby Style Guide](https://github.com/github/rubocop-github/blob/master/STYLEGUIDE.md) it is recommended to use `do...end` for multi-line blocks and `{...}` for single-line blocks.
- Curly braces `{...}` syntax has higher precedence than `do...end` syntax. We can observe when a block is passed to a method without using parentheses `()`:
```ruby
# Using {...}
puts [1,2,3].select{ |number| number.even? }
2
=> nil # method "puts" returns nil

# Using do...end
puts [1, 2, 3].select do |number| number.even? end
#<Enumerator:0x00007fefbebca498>
=> nil # method "puts" returns nil
```
In the first case, we see `2` is printed back because the method `puts` accepts everything till the end of the block as one parameter.
In the second case, [enumerator](https://ruby-doc.org/core-2.7.1/Enumerator.html) is returned instead because the method `puts` does not see `do..end` as a part of a parameter.

## Block Parameters

A block can have parameters that are stored between vertical lines called pipes `||`. 
```ruby
2.times do |number|
  puts number
end
```
```
# Output printed
0
1
=> 2 # returned value of the "times" method
```

## Block Variable Scope

Block variables (parameters between the pipes `||`) can behave differently from variables that are coming from the method scope. Let's review some examples:

- A variable is declared in the method and the same variable is used inside a block. We can see that block has access to the `x`:
```ruby
def block_variable_example
  x = 1
  3.times do
    puts "x inside the block: #{x}"
  end
  
  puts "x outside the block: #{x}"
end
```
```
# Call method
block_variable_example

# Output
x inside the block: 1
x inside the block: 1
x inside the block: 1
x outside the block: 1

=> nil
```

- A variable is declared in the method and the same variable is being re-assigned inside the block. Same as in the first example, variable inside a block is the same as the one outside:

```ruby
def block_variable_example
  x = 1
  3.times do
    x = 2
    puts "x inside the block: #{x}"
  end
  
  puts "x outside the block: #{x}"
end
```
```
# Call method
block_variable_example

# Output
x inside the block: 2
x inside the block: 2
x inside the block: 2
x outside the block: 2

=> nil
```

- A variable `x` is declared in the method and the block parameter has the same name `x`. It appears that variable inside the block is different from the one that was declared in the method:

```ruby
def block_variable_example
  x = 1
  3.times do |x|
    puts "x inside the block: #{x}"
  end
  
  puts "x outside the block: #{x}"
end

# Call method
block_variable_example
```
```
# Output
x inside the block: 0
x inside the block: 1
x inside the block: 2
x outside the block: 1

=> nil
```

## What is `yield` keyword?

If you want to execute a block inside a method `yield` is your friend. In many countries, there's a traffic sign `yield` which means you need to give right of way to another car. 
- Similar logic applies here. During a method execution when Ruby parser sees `yield` it gives the right of way to the code within a block and executes it. After that, it comes back to the method scope and executes the remaining code. 
- In case there are situations when a block is going to be optional when calling your method it is better to use the `Kernel#block_given?` method so that no exception is thrown.
Here are some examples of using `yield` keyword:
```ruby
def my_yield_method
  puts "Code before yield"
  
  if block_given?
    yield
  else
    puts "No block was given"
  end

  puts "Code after yield"
end

# =================== Call method with a block
my_yield_method { puts "Code inside a block" }
```

```
# Output
Code before yield
Code inside a block
Code after yield

=>nil
```

```ruby
# =================== Call method without a block
my_yield_method
```

```
# Output
Code before yield
No block was given
Code after yield

=> nil
```

- `yield` keyword can have arguments that are going to be passed to a block

```ruby
def my_yield_method_with_params
  str = "Awesome parameter"
  
  puts "Code before yield"
  yield str if block_given?
  puts "Code after yield"
end

# =================== Call method with a block
my_yield_method_with_params do |param|
  puts "This is what we got: #{param}"
end
```
```
# Output:
Code before yield
This is what we got: Awesome parameter
Code after yield

=> nil
```

I hope you found this information helpful :slightly_smiling_face: