I have the following Ruby code:
local_var = "Hello"
def hello
puts local_var
end
hello
I get the following error:
local_variables.rb:4:in 'hello': undefined local variable or method 'local_var'
for main:Object (NameError) from local_variables.rb:7:in '<main>'
I always thought that local variables are not accessible from outside of the block, function, closure, etc.
But now I defined local variable in the file and try to get an access from the function INSIDE the same file.
What's wrong with my understanding?
In Ruby local variables only accessible in the scope that they are defined. Whenever you enter/leave a Class, a Module or a Method definiton your scope changes in Ruby.
For instance :
v1 = 1
class MyClass # SCOPE GATE: entering class
v2 = 2
local_variables # => ["v2"]
def my_method # SCOPE GATE: entering def
v3 = 3
local_variables # => ["v3"]
end # SCOPE GATE: leaving def
local_variables # => ["v2"]
end # SCOPE GATE: leaving class
These entering and leaving points are called Scope Gates. Since you enter through Scope Gate via method definition you cannot access your local_var
inside hello
method.
You can use Scope Flattening concept the pass your variable through these gates.
For instance instead of using def
for defining your method you can use Module#define_method
.
local_var = "Hello"
define_method :hello do
puts local_var
end
In the same way you can define your classes via Class#New
so that your scope does not change when you pass through class definition.
local_var = 'test'
MyClass = Class.new do
puts local_var #valid
end
instead of
class MyClass
puts local_var #invalid
end
In the same way you should use Module#New
if you want to pass your local variables through Module gates.
Example is taken from Metaprogramming Ruby