Photo by Jack Anstey on Unsplash

Scope Gates in Ruby: Flat Scopes

An overview of the execution context of blocks

Tech - RubyCademy
Published in
2 min readSep 20, 2019

--

In this article, we’re going to explore the following topics:

  • scopes and blocks
  • flat scope guard in class/module

First, feel free to browse the Scope Gates in Ruby: Part II article.

Scope and blocks

In Ruby, a block can access the outer scope

In this example, we can access the outer_scope_variable variable within our block. Our block gets access to this variable even though the variable is declared at a main level scope. In this case, we say that the block flattens scopes. This is why we commonly call this mechanism: Flat Scope.

On the other hand, the block creates an isolated scope — even if the value of self within the block remains the main object.

So we can’t access local variables defined within the block

Here, we can’t access the block_variable from the outer scope. Now that we’re more familiar with the notion of flat scope in Ruby let’s see if this notion impacts class definition.

Class, module, and block

In Ruby, what you commonly call a class is, behind the scenes, an instance of the Class class

Here, we create the Hello and Greeting classes in two different ways:

  • using the class keyword
  • by assigning an instance of the Class class to the Greeting constant

Note that we are passing a block to the Class.new method. This block will be interpreted as the content of the class. Normally a class can’t access variables defined in the outer scope — as the class keyword changes the value of self and creates an isolated scope.

So, as we use a block to create our Greeting class then we should be able to use the flat scope mechanism. Really?

Here we can see that the value of self changes when using class or Class.new.

Also, our Class#message block is still isolated from the main object because of the use of def keyword. Indeed, as our block is executed in the context of the method then the block flattens scope within this given object — and not with a higher scope as the main object.

That’s why we don’t have access to outer_variable within message.

But if we use define_method to define message then the scope is flattened

Here, as define_method(:message) takes a block as an argument, the scope of this block is flattened and this method has access to outer_variable.

Ruby Mastery

We’re currently finalizing our first online course: Ruby Mastery.

Join the list for an exclusive release alert! 🔔

🔗 Ruby Mastery by RubyCademy

Also, you can follow us on x.com as we’re very active on this platform. Indeed, we post elaborate code examples every day.

💚

--

--