Block arguments

Blocks make a lot of sense on methods that are defined on collections like arrays and hashes.

Let’s have a look at some examples with arrays.

In our previous example that used the method times our block did not accept an argument. A block that accepts an argument looks like this:

[1, 2, 3, 4, 5].each do |number|
  puts "#{number} was passed to the block"
end

And, again, this is the same as:

[1, 2, 3, 4, 5].each { |number| puts "#{number} was passed to the block" }

It is unknown to us why Matz has chosen to not enclose the argument list of a block with round parentheses just like method argument lists. Instead, Ruby wants us to use vertical bars (we call them “pipes”).

So, for blocks, do |number| is the same that is def add_two (number) for a method definition, except that the method wants a name while a block is anonymous: |number| and (number) both are argument lists. The first one is used for blocks, the second one for methods.

Block arguments are listed between pipes |, instead of parentheses.

Now, when you run the code example above, you’ll see the message printed out for each of the numbers contained in the array.

Does that make sense? Again, our code almost reads like an English sentence:

With this array for each of its elements, naming it number, output the following message.

The method each is defined on arrays, and it does just this:

It takes each of the elements in the array and calls the block, passing the element as an argument. The block can then do whatever you want it to do with the element. In our case we interpolate it into a string and print it out to the screen.