In ruby, as in other programming languages, it's not always intuitive when you have access to what variables. Instance variables are available anywhere within a file (or other files that load or have access to that file). Non-instance variables, though, are sometimes available within code blocks and sometimes aren't. The table below is a quick reference, but we'll dive into specifics below.
Access Non-Instance Variables Defined Outside From Within | Access Non-Instance Variables Defined Inside From Without | |
---|---|---|
Methods | no | no |
Loops | yes | no |
Conditionals | yes | yes |
Variables defined outside of methods can't be accessed within methods unless they are passed in (or the method is called on them) or they are instance variables.
x = 3
@y = 4
def print_x_and_y
p @y # => 4
p x # => undefined local variable or method `x' for main:Object (NameError)
end
print_x_and_y
Likewise, variables defined within methods cannot be accessed outside of those methods unless they are instance variables or are returned.
def some_letters
x = 3
@y = 4
z = 5
return z
end
z = some_letters
p z # => 5
p @y # => 4
p x # => undefined local variable or method `x' for main:Object (NameError)
Loops handle scope differently than methods. Variables defined outside of loops can be used within loops, but variables defined within loops (or as block variables) cannot be used outside of those loops).
i = 0
1.times do
p i # => 0
end
1.times do
i = 0
p i # => 0
end
p i # => undefined local variable or method `i' for main:Object (NameError)
Conditionals have no particular rules for scope and are therefore something of a welcome breath of fresh air. Variables defined outside of conditionals can be used within conditionals. Variables defined inside conditionals can be used outside.
x = 1
if true
p x # => 1
y = 2
else
p "!!true == false, apparently"
end
p y # => 2
Ruby reads files top to bottom. For the most part, variables can only be referenced after they are defined.
p x # => undefined local variable or method `x' for main:Object (NameError)
x = 2
An exception to this occurs with instance variables. Instance variables are "lifted out" and initialized at the beginning of runtime (before the rest of the file runs), although they are set to nil
.
p @x # => nil
@x = 2
While this isn't often useful, it could be valuable in loops that make use of conditional statements:
i = 1
until @i_is_greater_than10
i += 1
if i > 10
@i_is_greater_than10 = true
end
end
p i
It's not life changing, but it means we don't have to set @i_is_greater_than10 equal to false ourselves before starting the loop.