The Life‑Changing Magic of Ruby and Rails

How to Access Variables Outside Scopes in Ruby

In C# and Java, variables from the outer scope are visible to the inner scope. In Ruby, scopes are sharply separated, and nested visibility is not allowed. As soon as the control enters a new scope, i.e. a class, module, or a method, the previous bindings are replaced by a new set of bindings.

The following example illustrates this. When the program control enters the class Runner, the variable num falls out of scope and is no longer visible inside the class or the run method.

num = 1

class Runner
  puts "#{num} from class"

  def run
    puts "#{num} from method"
  end
end

Runner.new.run

# (NameError): undefined local variable or method `num' for Runner:Class

A workaround is to use Ruby’s powerful meta-programming features. Ruby allows you to define new classes and methods on the fly, using Class.new and define_method respectively. Both methods accept a block which becomes the body of the class or method.

num = 1

Runner = Class.new do
  puts "#{num} from class"

  define_method :run do
    puts "#{num} from method"
  end
end

Runner.new.run

# Output
# ==============
# 1 from class
# 1 from method

Replacing the scope gates (class, method, etc.) with a method call allows one scope to see variables from the outside scope. This is also known as "flattening the scope".

Credits: Metaprogramming Ruby 2

Subscribe to Akshay's Blog

Sign up now to get access to the library of members-only issues.
Jamie Larson
Subscribe