Lesson Weekend

Understanding scope is one of the most important aspects of mastering any coding language. Ruby is no different. In this lesson, we'll cover how local variables are scoped. Then we’ll move on to a brief discussion of scope gates, where the scope we’re in changes. Finally, we’ll briefly cover global, class and instance variables. Some of this material may be confusing at first; in the future, you can use this lesson as a reference when needed.

Local Variables


We’ll find local variables everywhere we go in a Ruby program. The top-level main has a local scope. All method definitions have their own local scope. Classes and modules, which we haven’t covered yet, both have their own local scope.

Local variables inside of a block cannot be accessed outside of that block. Here’s a silly example:

> counter = 0
> 1.times do
  counter +=1
  greeting = "hello"
end
> counter
=> 1
> greeting
=> undefined local variable or method `greeting' for main:Object

We define the local variable greeting inside of our do...end block. However, when we try to call it outside the block, we get an undefined local variable error. In other words, greeting is only available inside the block.

Now let’s look at our other local variable: counter. counter is defined outside the block in the top-level scope. Our block has access to the local variables declared outside it, including counter. We can then check the value of counter outside the block because that’s where it was defined.

There are certain points in an application when all local variables fall out of scope. These are called scope gates.

Scope Gates


When we reach a scope gate in our application, all local variables fall out of scope. Certain keywords represent these gates; these keywords are def, class, module, and end. In other words, whenever we enter a new method definition, class or module, we’re entering a new scope. (It’s possible to work around this by using an advanced Ruby concept called a flat scope, but that’s beyond the scope of our curriculum.)

Here’s an example of a scope gate in action:

> greeting = "hi"
> def return_the_greeting
  greeting
end
> return_the_greeting()
=> undefined local variable or method `greeting' for main:Object

Our method doesn’t know about the variable greeting, which is a local variable in the top-level scope. It only knows about local variables in its own scope.

Whenever you enter a new method definition with def, you’re entering a new scope. That scope ends with the end keyword.

We’ll revisit the concept of scope gates when we build our own custom classes. The principle, however, is the same for both classes and modules. A new scope begins with the class or module keyword and ends with the end keyword that closes that class or module.

There are also three other types of variables in Ruby: global, class and instance.

Global Variables


Global variables are essentially the opposite of local variables because they’re available everywhere in a Ruby program. These variables are always preceded by the $ symbol:

> $global = "This is a global variable"
> defined? $global
=> "global-variable"

Here we define a global method by adding the $ sign. We then use the Ruby method defined? to check what kind of variable it is. (Interestingly enough, this method uses a ? even though it doesn’t return a boolean.)

In general, global variables should be avoided. They can "pollute" the rest of an application and cause harm simply because they're always around! There are important use cases for them but there’s absolutely no need to use them while you’re a student at Epicodus.

Class Variables


A class variable is available everywhere inside of a class. We will cover these in depth when we build our own custom classes. These variables use @@. For example, we might have a variable called @@widgets. Class variables can be useful but they can also be problematic as well, for reasons we’ll discuss in a future lesson.

Instance Variables


An instance variable is available to a single instance of an object. These variables use @, so we might see something like this: @height. Instance variables are very useful and we'll use them regularly in Ruby. They are often used to store an object's properties. We’ll be covering instance variables in much greater depth soon.

Summary


In this lesson, we covered the basic rules of variable scope in Ruby. We focused mainly on local variables and scope gates and touched briefly on global, class and instance variables. Global variables should be avoided entirely if possible. We’ll cover class and instance variables more later in this section.

Local Variable: The most common type of variable. They can not live outside of the scope in which they are declared and cannot pass through scope gates. We declare a local variable like this:

number = 5

Instance variable: Available to a single instance of an object. These variables use @:

@name = "Milo"

Class variable: Available everywhere inside of a class. These variables use @@:

@@widgets = []

Global variable: Available everywhere in a Ruby program. These variables are always preceded by the $ symbol:

$global = "This is a global variable"

Scope gate: All local variables fall out of scope when we reach a scope gate. The keywords are scope gates: def, class, module and end.

Lesson 7 of 10
Last updated August 7, 2022