Deciding Whether Part of a Code is a Block or Not

In Ruby, variable scope is defined by a block (see Local Variable Scope). A block is usually delimited by curly brace {} or do/end pair.

However this is not always the case:

Code delimited by {} or do/end is considered a block if the delimiters follows a method invocation.

arr = [9, 8, 7, 6]  # Array initialized to variable arr in the outer scope

arr.each do         # Block passed as an argument to the `Array#each` method
  b = 3             # Variable b initialized in the inner scope
end

puts b              # NameError (undefined local variable or method `b' for
                    # main:Object) because of scope rules

Blocks are a way to pass chunk of codes around in our program. This programming technique is called closure.

Blocks are alike anonymous functions in Java.

Let’s now take a look at the code below:

arr = [9, 8, 7, 6]  # Array initialized to variable arr in the outer scope

for i in arr do     # for keyword
  b = 3             # Integer 3 assigned to variable b
end

puts b              # 3

While it would seem for...do/end creates a new inner scope, it is actually not the case. for is a keyword part of the Ruby language and not a method invocation.

This is why in this case, even though it is followed by {} or do/end, no block are being defined.