Introduction to Ruby blocks
Tags: ruby, rails
Published: 2019-11-12 13:09:42

Blocks are ubiquitous in Ruby. They are one of the defining and most powerful characteristics of the Ruby language.  It is almost impossible to write any meaningful Ruby code without the blocks. They appear everywhere from ruby core library methods such as enumerations to Rails to Rake to almost every gem out there.

```ruby
# Core lib
10.times { puts "Ruby" }
```

```ruby
# Rails
Rails.application.routes.draw do
  resources :people
end
```

```ruby
# Rake
task :test do
  ruby "test/unittest.rb"
end
```

```ruby
# Bundler
group :development do
  gem 'pry-byebug'
end
```

_Blocks, all over the place_ :cold_sweat::scream:

![Blocks, everywere](https://media.giphy.com/media/1yn20fhZcNhHV59YXz/giphy.gif)


Yet, they can be so hard to understand for beginners and even experienced programmers that are just starting with Ruby.


In this post, we will look at what are the closures, blocks and basic usage patterns.

Let's begin!



## Scopes

### Lexical scope

Lexical scope serves to answer one important question: **What is the value of this variable at this line?**

```ruby
def speak
  message = "in the bottle"
  message
end

speak
# => "in the bottle"
```

In this example, we created a local variable inside the method, the variable is in the scope of the method, it is created there.

```ruby
message = "in the bottle"

def speak
  message
end

speak
# => NameError (undefined local variable or method `message' for main:Object)
```

In this example, we created the variable outside the method scope. When we call the variable inside the method we get an error: **Variable is out of the scope**.

Local variables are tightly scoped, we can't access a variable outside itself unless it's passed as an argument, or we define an instance variable but that is a story for another day.


 
### Inherited scopes

Yeah, yeah...we got it scoping rules explained above are nothing new and they are easy to grasp. But, wait how does this work then:


```ruby
message = "in the bottle"

2.times do
  puts message
end

# => in the bottle
# => in the bottle
```

**Blocks, Procs, Lambdas** are different. Blocks create scope between `do..end`(same as method), but they inherit references to the local variables in the context where they are created.

In our example we have 2 scopes
1. **Outer/parent** - where variable `message` is defined
2. **Inner/child**  - scope inside the block

Our block is created in the context of parent scope and he will carry a reference to the local variable defined in that scope, thus making `message` variable accessible from within the inner scope.


When block calls variable from the outer/parent scope, that variable is called a **free variable**.


Turns out, when function whose body(_lexical scope_) references a variable(_free variable_) that is declared in the parent scope we got a **CLOSURE**.



## Blocks

Blocks are effectively a type of **closure**. Blocks capture pieces of code that can be passed into methods to be executed later, they act like anonymous functions.

The ability to encapsulate behavior into blocks and pass it to the methods is an extremely useful technique. This lets you **separate general and specific pieces of your code.**


Let us imagine we are developers for the NBA. We are building a register of the most popular players:

```ruby
class Player
  attr_reader :name, :team, :salary, :age

  def initialize(name, team, salary, age)
    @name   = name
    @team   = team
    @salary = salary
    @age    = age
  end
end

players = []
palyers << Player.new("Lebron James", "Lakers", salary: 5000, age: 34)
palyers << Player.new("Kevin Durant", "Nets", salary: 4000, age: 31)
palyers << Player.new("James Harden", "Rockets", salary: 6000, age: 30)
```


We have a requirement to display players sorted by age or salary or name.

Instead of tying our class with specific sorting implementation we can leverage the power of blocks and separating general from specific like this:


```ruby
players.sort_by { |player| player.age }
players.sort_by { |player| player.salary }
players.sort_by { |player| player.name }
```


### Executing blocks

Whenever you see `yield` keyword that means execute the block, for example

```ruby
def speak
  yield
end
```

`speak` method will execute any block we give it

```ruby
speak { puts "Y" }
#=> Y
```

If we don't pass the block to the method, ruby will raise an exception.

```ruby
speak 
# => LocalJumpError (no block given (yield))
```

Luckily ruby gives as a nice way to check whether the block was passed with `block_given?`

```ruby
def speak
  if block_given?
    yield
  else
    "No block is given"
  end
end

speak { puts "Y" }
#=> Y 

speak
#=> No block is given
```

We can also pass arguments to the block to get similar behavior to this

```ruby
speak("ruby") { |message| puts "Hello #{message}" }
```

```ruby
def speak(message)
  yield(message)
end
```

Those with a sharp eye will notice that `message` variable is a free variable here.


That is all for now, in the next posts I will talk more about procs, lambdas, and interesting patterns that we can leverage procs, lambdas, and blocks for.


:v: