9

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?

1
  • 1
    Please, can you read bbatsov's styleguide and accommodate to it? Commented Aug 22, 2013 at 9:10

1 Answer 1

35

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)
Sign up to request clarification or add additional context in comments.

1 Comment

One of the most under-rated answers I’ve ever seen.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.