Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: How do I access module local variables?

Tags:

ruby

I get this error: MyModule.rb:4:in getName': undefined local variable or methods' for MyModule:Module (NameError)

file1

module MyModule
  s = "some name"
  def self.getName()
    puts s
  end 
end

file2

require './MyModule.rb'

include MyModule
MyModule.getName()

This has something to do with scope, but I'm not comprehending why this is happening if I declared it before the method. does include only mixin methods and not variables? How do I change my module so that it can print out variables I define within the module?

like image 783
user1099123 Avatar asked Aug 22 '13 04:08

user1099123


1 Answers

This has something to do with scope, but I'm not comprehending why this is happening

A def creates a new scope. In some languages, an inner scope can see the local variables in the surrounding scope--but not in ruby. You could use a constant instead:

module MyModule
  S = "some name"

  def getName()
    puts S
  end 
end

include MyModule

getName

--output:--
some name

But constants can be accessed from anywhere:

module MyModule
  S = "some name"

  def getName()
    puts S
    puts Dog::S
  end 
end

module Dog
  S = "hello"
end

include MyModule

getName

--output:--
some name
hello

A more advanced solution involves using a closure. Unlike a def, a block can see the local variables in the surrounding scope, which is known as closing over the variables. Here is an example:

module MyModule
  s = "some name"
  define_method(:getName) { puts s }
end

include MyModule

getName

--output:--
some name

The advantage of using a closure is that nothing but the block can access s.

does include only mixin methods and not variables?

It depends on the kind of variable:

module MyModule
  A = 'hello'
  s = 'goodbye'
end

include MyModule

puts A
puts s

--output:--
hello

1.rb:9:in `<main>': undefined local variable or method `s' for main:Object (NameError)

The module keyword, like def, creates a new scope. You know how local variables are destroyed when a method finishes executing? When a module finishes executing, its local variables are destroyed too:

module MyModule
  puts "MyModule is executing"
  s = 'goodbye'
end

include MyModule

puts s

--output:--
MyModule is executing

1.rb:7:in `<main>': undefined local variable or method `s' for main:Object (NameError)
like image 185
7stud Avatar answered Sep 28 '22 18:09

7stud