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.
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.
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 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.
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.
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.
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