#GopherDiggingRuby: Intro to blocks in Ruby
Tags: ruby, codenewbie, beginners, go
Published: 2022-01-22 21:27:05

---
title: #GopherDiggingRuby: Intro to blocks in Ruby
published: true
description: 
tags: #ruby #codenewbie #beginners #go
---

When you're coding in Ruby, one piece of syntax you'll see a lot of is **blocks**, with either the curly braces or `do...end` syntax. So in this tutorial, we will take a look at how we can use blocks as convenient feature of a Ruby developer's toolbelt, and how that compares to Go.

## 🐼 Looping over collections with Lola

In Go, the idiomatic way to loop over a slice is with the `range` keyword, like this:

```go
var doggoTricks = []string{
    "roll over", "speak", "shake paws", "toodle-oo",
}

for _, trick := range doggoTricks {
    fmt.Printf("Lola! Can you %s?\n", trick)
    lola.DoTrick(trick)
}
fmt.Println("Good pupper! Have a biscuit! 🦴")
```

In the for loop's top line, we loop over the `doggoTricks` slice one item at a time, putting the current dog trick in the variable `trick`. Then, inside the block, we use the `trick` variable to tell my dog Lola to do that trick, and then she does the trick using the function `lola.DoTrick`. And because of the curly braces block, the varable `trick` is scoped to only exist inside the for loop.

Ruby does have [loops of its own](https://www.geeksforgeeks.org/ruby-loops-for-while-do-while-until), but another cool, and in my opinion quite satisfying way of looping over a Ruby array is with the [Array#each method](https://ruby-doc.org/core-3.1.0/Array.html#method-i-each). Doing the same loop in Ruby looks like this:

```ruby
doggo_tricks = ['roll over', 'speak', 'shake paws', 'toodle-oo']

doggo_tricks.each do |trick|
  puts "Lola! Can you #{trick}?"
  lola.do_trick trick
end
puts "Good pupper! Have a biscuit! 🦴"
```

The part `do |trick| ... end` is the block, and inside the pair of pipe (these `|`) characters, you name the variable that's scoped to the block. Then, inside the block, you can use that variable, such as printing it with `puts` and passing it into `lola.do_trick`.

In addition to looping over arrays, there's also an [each method for hashes](https://ruby-doc.org/core-3.1.0/Hash.html#method-i-each) that works similarly to looping over maps in Go. And `each` isn't the only method that takes in a block; you can also use blocks on methods like `Array#sort` to influence how an array is sorted, `Array#map` to create a new array by running the code in the block on each item in the current array, and `Array#filter` to return an array of only the items where the block's code would return true.

As an example, if we had code like

```ruby
with_paws = doggo_tricks.filter { |trick| uses_paws trick }
```

then the `with_paws` array would only have tricks where `uses_paws` is true, which includes `toodle-oo` and `shake paws`.

If you read [my last tutorial](https://dev.to/andyhaskell/gopherdiggingruby-make-a-devto-link-fetcher-in-ruby-18mb) on building a dev.to fetcher in Ruby, by the way, a couple places where we used blocks in this way were:

* with `Array.map` to convert an array of Ruby hashes to an array of `Article` objects
* walking a Markdown document's nodes

By the way, toodle-oo is Lola's signature trick, and it's really cute!

![Animated gif of adorable black and white Havanese dog who looks like a panda standing on her hind legs and waving her front paws up and down](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/82ba8xoox3525xy209sb.gif)

## 🌺 Having an object only in the part of the code where you need it, as told by making a smoothie

Another great use of blocks in your code is when you want to declare a variable, use it, and then do any clean-up code afterwards, like if you're opening a file, reading it into some kind of data structure, and then closing it when you no longer need that `File` variable, for example. When a Ruby API has use cases following that pattern, blocks are a common way to do that pattern.

As a more fun example, when it's a hot day out, nothing cools off a sloth like a refreshing hibiscus and cecropia leaf smoothie, fresh from the blender. Without blocks, the Ruby code would look something like this:

```ruby
blender = get_blender()
blender.add('ice cubes', 'hibiscus flowers', 'cecropia leaves')

blender.serve_drinks()

# now on to more Ruby code for the rest of a sloth's day! 
```

The one problem with this code is, the `blender` variable is still in scope, and if this is in the middle of a long section of Ruby code, it's easy to forget to call `clean_up(blender)` and `put_back(blender)`.

The Go approach to making sure that code gets called would be to either use `defer` like this:

```go
blender := getBlender()
defer func() {
    cleanUp(blender)
    putBack(blender)
}

blender.Add("ice cubes", "hibiscus flowers", "cecropia leaves")
blender.ServeDrinks()

// now on to more Ruby code for the rest of a sloth's day!
```

The Go function in the `defer` statement runs at the end of the Go code block we're in, so no matter what branches of code we take, `cleanUp(blender)` and `putBack()` blender will be called.

For a Ruby approach with blocks, let's say that this `get_blender` function had `clean_up(blender)` and `put_back(blender)` built-in. Then, the Ruby code for serving smoothies for sloths would look like this:

```ruby
get_blender do |blender|
  blender.add(
    'ice cubes', 'hibiscus flowers', 'cecropia leaves'
  )
  blender.serve_drinks
end
```

We put the code we want to run into the block, and use the variable `blender` inside the block to add the ingredients and then serve the smoothies. Then, behind the scenes, `get_blender` calls the cleanup code. The person using our blender API, and the people reviewing their code, don't need to pore over lines of code to make sure all the cleanup code is called, because that's built right in, saving time and bug fixes for your dev team!

In my last tutorial on building a dev.to image link fetcher in Ruby, by the way, a couple places where we used blocks in this way were:

* Sending an HTTP request to dev.to, deserializing the response from JSON, and then no longer needing the response body to be in-scope
* Generating a CSV file object, and then inside the block adding the image links as rows of the CSV

## 🍹 Making your own functions that use blocks

One final thing to look at for demystifying Ruby blocks, is how to make your own code that works with them. To do that, we use a keyword called `yield`. This keyword confused me when I was first learning Rails, but essentially you can use `yield` to do the pattern of:

1. Run any code that's before the yield keyword
2. `yield` 0 or more Ruby objects that can be passed into the block
3. Then, run any code past the yield keyword

Let's try that out by giving the `get_blender` function a definition:

```ruby
def get_blender
  blender = take_blender_out_of_cabinet()
  blender.plug_in()

  yield blender
  clean_up blender
  put_away blender
end
```

We first run `take_blender_out_of_cabinet()` and `blender.plug_in()` to get the blender ready. Then, we run `yield blender`. At that point, the coder using our blender can run a block that has the `blender` passed in as a variable in the block's scope. We run that code, and then return to the body of the `get_blender` function, where we call `clean_up blender` and `put_away blender` to clean up after the sloths enjoy a nice tasty smoothie!

You don't need to necessarily just use a block once in a function, by the way. Remember how we used the Array `filter` and `each` methods with blocks that run on each item in an array? Let's say we had some prep work to do before putting the ingredients into the blender. Before blending the hibiscus flowers and cecropia leaves, let's wash them, which we can do by using `yield` inside a loop, like this:

```ruby
class Blender
  def add(*ingredients)
    # do prep work for the smoothie here!
    for ingredient in ingredients
      yield ingredient
      add_ingredient_to_blender ingredient
    end

    self.now_make_the_smoothie!
  end
end
```

For each ingredient we pass into `add`, we `yield` the ingredient to the block passed in before putting it in the blender. Finally, with all that done, we `now_make_the_smoothie!`

So now, the code for adding our smoothie ingredients would look like this:

```ruby
blender.add(
  'ice cubes', 'hibiscus flowers', 'cecropia leaves'
) do |ingredient|
  if need_to_wash? ingredient
    wash ingredient
  end
end
```

In the block we are using, we pass the ingredient into `need_to_wash?`, and then wash the ones where `need_to_wash?` returns true (ice cubes are already made of water to begin with so no need to wash them). We run the block for each ingredient one at a time, so with all our smoothie ingredients prepped and put in the blender, we finally call `blender.now_make_the_smoothies!` to get refreshing hibiscus-cecropia smoothies to get just the energy you need for a long slothful day, brought to you by blocks!

For more information about how `yield` and `yield_self`, I recommend looking at [this blog post by RubyGuides](https://www.rubyguides.com/2019/12/yield-keyword/).