Newbie: require 'filename' - undefined local variable or method

I have one line of code in a file called 'stuff.rb':
     myhash = { "a" => "ay", "b" => "bee", "c" => "sea" }

and I wish to include it in another program called 'mainprog.rb' thus:

     require 'stuff'

     puts " a = " + myhash["a"]

when I run it I get an error message:
    mainprog.rb:4: undefined local variable or method `myhash' for
main:Object (NameError)

I guess I must be doing something dumb - I am basing this code on
examples in 'Why's (poignant) guide to Ruby'. I am using the very
latest Windows version under XP Pro:
C:\rubysrcs>ruby -v
ruby 1.8.2 (2004-12-25) [i386-mswin32]

which I installed using the exe file: ruby182-15.exe

everything else I've tried seems to be working fine. Thanks.

The exact details of why this I'm not familiar w/ but it is a scope
issue. The require won't make the local variable into global for you.

The 'myhash' isn't global just because it is declared outside of other
things.. prefix that myhash w/ a $ and make it a global.

$myhash = { "a" => "ay", "b" => "bee", "c" => "sea" }

···

-----------

puts $myhash['a']

-dayne

On 12/18/05, Grehom <grehom@ntlworld.com> wrote:

I have one line of code in a file called 'stuff.rb':
     myhash = { "a" => "ay", "b" => "bee", "c" => "sea" }

and I wish to include it in another program called 'mainprog.rb' thus:

     require 'stuff'

     puts " a = " + myhash["a"]

when I run it I get an error message:
    mainprog.rb:4: undefined local variable or method `myhash' for
main:Object (NameError)

I guess I must be doing something dumb - I am basing this code on
examples in 'Why's (poignant) guide to Ruby'. I am using the very
latest Windows version under XP Pro:
C:\rubysrcs>ruby -v
ruby 1.8.2 (2004-12-25) [i386-mswin32]

which I installed using the exe file: ruby182-15.exe

everything else I've tried seems to be working fine. Thanks.

Grehom wrote:

I have one line of code in a file called 'stuff.rb':
     myhash = { "a" => "ay", "b" => "bee", "c" => "sea" }

and I wish to include it in another program called 'mainprog.rb' thus:

     require 'stuff'

     puts " a = " + myhash["a"]

when I run it I get an error message:
    mainprog.rb:4: undefined local variable or method `myhash' for
main:Object (NameError)

I guess I must be doing something dumb - I am basing this code on
examples in 'Why's (poignant) guide to Ruby'. I am using the very
latest Windows version under XP Pro:
C:\rubysrcs>ruby -v
ruby 1.8.2 (2004-12-25) [i386-mswin32]

which I installed using the exe file: ruby182-15.exe

everything else I've tried seems to be working fine. Thanks.

this is a common gotcha, ruby doesn't include "." in $LOAD_PATH, which
is different from perl @INC and python PYTHONPATH so you have to

$:.unshift Dir.pwd

or somehtin like that

Try using this instead:

load 'stuff'

local variables outside of class like that will not be imported when you require that file. Load should do what you want.

Cheers-

-Ezra

···

On Dec 18, 2005, at 12:02 PM, Grehom wrote:

I have one line of code in a file called 'stuff.rb':
     myhash = { "a" => "ay", "b" => "bee", "c" => "sea" }

and I wish to include it in another program called 'mainprog.rb' thus:

     require 'stuff'

     puts " a = " + myhash["a"]

when I run it I get an error message:
    mainprog.rb:4: undefined local variable or method `myhash' for
main:Object (NameError)

I guess I must be doing something dumb - I am basing this code on
examples in 'Why's (poignant) guide to Ruby'. I am using the very
latest Windows version under XP Pro:
C:\rubysrcs>ruby -v
ruby 1.8.2 (2004-12-25) [i386-mswin32]

which I installed using the exe file: ruby182-15.exe

everything else I've tried seems to be working fine. Thanks.

Grehom wrote:

I have one line of code in a file called 'stuff.rb':
     myhash = { "a" => "ay", "b" => "bee", "c" => "sea" }

and I wish to include it in another program called 'mainprog.rb' thus:

     require 'stuff'

     puts " a = " + myhash["a"]

when I run it I get an error message:
    mainprog.rb:4: undefined local variable or method `myhash' for
main:Object (NameError)

I guess I must be doing something dumb - I am basing this code on
examples in 'Why's (poignant) guide to Ruby'. I am using the very
latest Windows version under XP Pro:
C:\rubysrcs>ruby -v
ruby 1.8.2 (2004-12-25) [i386-mswin32]

which I installed using the exe file: ruby182-15.exe

everything else I've tried seems to be working fine. Thanks.

myhash is a local variable in stuff.rb and will thus not
be available when you #require the file. There are a few
options you have: you could either make it a constant
(MY_HASH), a global ($my_hash) or you could wrap it inside
a method and then call the method in your main file.

E

···

--
Posted via http://www.ruby-forum.com/\.

Grehom wrote:

I have one line of code in a file called 'stuff.rb':
     myhash = { "a" => "ay", "b" => "bee", "c" => "sea" }

and I wish to include it in another program called 'mainprog.rb' thus:

     require 'stuff'

     puts " a = " + myhash["a"]

when I run it I get an error message:
    mainprog.rb:4: undefined local variable or method `myhash' for
main:Object (NameError)

Local vars are scoped to the file they are defined in, when you use
require or load. You could make it global, but unless this is just a
quick hack, it's not a good solution.

Another option is to read and eval the file. If the myhash variable has
been assigned *before* you eval, then the assignment in stuff.rb will
propagate to the mainprog.rb. Like so:

  myhash = nil
  eval File.read("stuff.rb")
  p myhash

This is ok for some purposes, but you have to know in advance which
variables the file is going to define. Also, you may have scope
collisions: any other local var in mainprog.rb can be affected by
assignments in stuff.rb.

My preference is to read the file as a string and use module_eval:

# mainprog.rb
  m = Module.new
  m.module_eval(File.read("stuff.rb"), File.expand_path("stuff.rb"))
  p m::Myhash

# stuff.rb
  Myhash = { "a" => "ay", "b" => "bee", "c" => "sea" }

Local vars stay local. Constants are accessible in the scope of the
newly defined module m. The second arg to module_eval means that errors
are reported with the correct file name.

<plug> This is the approach used by my "script" lib on raa. It adds some
sugar and features. </plug>

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Thanks Gene and Ezra, I tried your suggestions but with no luck. I
modified the main program 'mainprog.rb' as follows:
   puts $:
   load("stuff.rb", wrap=false)
   puts myhash["a"]

This produced following output:
  C:\rubysrcs>ruby mainprog.rb
    c:/ruby/lib/ruby/site_ruby/1.8
    c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt
    c:/ruby/lib/ruby/site_ruby
    c:/ruby/lib/ruby/1.8
    c:/ruby/lib/ruby/1.8/i386-mswin32
    .
    mainprog.rb:5: undefined local variable or method `myhash' for
main:Object (NameError)

and it seems the pwd '.' is part of the Load Path already (without me
changing anything)

So I'm still puzzled (there are a few examples of code like this in
aforementioned tutorial book)!

Thanks Joel, that worked but it's way different from a number of
examples in the book ('Why's (poignant) guide to Ruby), how did they
ever work there?

Yeah I was wrong in thinking that load would load local vars. So like others have said you will have to wrap your var in a method or class. Or you could eval the file by reading the file in and running eval on it.

#a.rb
a = [1,2,3,4,5,6]

···

On Dec 18, 2005, at 2:27 PM, Grehom wrote:

Thanks Gene and Ezra, I tried your suggestions but with no luck. I
modified the main program 'mainprog.rb' as follows:
   puts $:
   load("stuff.rb", wrap=false)
   puts myhash["a"]

This produced following output:
  C:\rubysrcs>ruby mainprog.rb
    c:/ruby/lib/ruby/site_ruby/1.8
    c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt
    c:/ruby/lib/ruby/site_ruby
    c:/ruby/lib/ruby/1.8
    c:/ruby/lib/ruby/1.8/i386-mswin32
    .
    mainprog.rb:5: undefined local variable or method `myhash' for
main:Object (NameError)

and it seems the pwd '.' is part of the Load Path already (without me
changing anything)

So I'm still puzzled (there are a few examples of code like this in
aforementioned tutorial book)!

__________________

#b.rb
a_contents = File.open("a.rb"){|f| f.read}
eval a_contents
p a

# => [1, 2, 3, 4, 5]

-Ezra

I think there may be a problem with the gateway again..

The problem you have is that myhash is local to stuff.rb and
will not be made available if you #require or #load the file.
Instead, you have a few options: either make myhash a constant
(MY_HASH), a global ($my_hash) or set up a method to retrieve
it (def my_hash(); ...; end) and call the method from your
main file.

E

···

On 2005.12.19 07:27, "Grehom" <grehom@ntlworld.com> wrote:

Thanks Gene and Ezra, I tried your suggestions but with no luck. I
modified the main program 'mainprog.rb' as follows:
   puts $:
   load("stuff.rb", wrap=false)
   puts myhash["a"]

This produced following output:
  C:\rubysrcs>ruby mainprog.rb
    c:/ruby/lib/ruby/site_ruby/1.8
    c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt
    c:/ruby/lib/ruby/site_ruby
    c:/ruby/lib/ruby/1.8
    c:/ruby/lib/ruby/1.8/i386-mswin32
    .
    mainprog.rb:5: undefined local variable or method `myhash' for
main:Object (NameError)

and it seems the pwd '.' is part of the Load Path already (without me
changing anything)

So I'm still puzzled (there are a few examples of code like this in
aforementioned tutorial book)!

Grehom wrote:

Thanks Joel, that worked but it's way different from a number of
examples in the book ('Why's (poignant) guide to Ruby), how did they
ever work there?

I'm very sorry about this, Grehom. There is an update to the guide at: http://qa.poignantguide.net/\. This will all be rolled out soon with the new design and the German and French editions of the Guide.

_why

Ezra Zygmuntowicz wrote:

Thanks Gene and Ezra, I tried your suggestions but with no luck. I
modified the main program 'mainprog.rb' as follows:
   puts $:
   load("stuff.rb", wrap=false)
   puts myhash["a"]

This produced following output:
  C:\rubysrcs>ruby mainprog.rb
    c:/ruby/lib/ruby/site_ruby/1.8
    c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt
    c:/ruby/lib/ruby/site_ruby
    c:/ruby/lib/ruby/1.8
    c:/ruby/lib/ruby/1.8/i386-mswin32
    .
    mainprog.rb:5: undefined local variable or method `myhash' for
main:Object (NameError)

and it seems the pwd '.' is part of the Load Path already (without me
changing anything)

So I'm still puzzled (there are a few examples of code like this in
aforementioned tutorial book)!

Yeah I was wrong in thinking that load would load local vars. So like
others have said you will have to wrap your var in a method or class.
Or you could eval the file by reading the file in and running eval on it.

#a.rb
a = [1,2,3,4,5,6]
__________________

#b.rb
a_contents = File.open("a.rb"){|f| f.read}
eval a_contents
p a

# => [1, 2, 3, 4, 5]

-Ezra

[~/tmp] cat >a.rb
a = [1,2,3,4,5,6]
[~/tmp] cat >b.rb
a_contents = File.open("a.rb"){|f| f.read}
eval a_contents
p a
[~/tmp] ruby b.rb
b.rb:3: undefined local variable or method `a' for main:Object (NameError)
[~/tmp] ruby -v
ruby 1.8.2 (2004-12-25) [i686-linux]

This only works if you assign to 'a' somewhere in b.rb before the eval.

···

On Dec 18, 2005, at 2:27 PM, Grehom wrote:

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Thanks _why,
   I hate it when there is something like that I can't get my head
around. I love the book, a little wierd as programming tutorials go,
but the programming stuff is very readable and I am finding it very
useful
G.

Shows what I get for typing b.rb into irb instead of making it a real file.

-Ezra

···

On Dec 18, 2005, at 2:46 PM, Joel VanderWerf wrote:

Ezra Zygmuntowicz wrote:

On Dec 18, 2005, at 2:27 PM, Grehom wrote:

Thanks Gene and Ezra, I tried your suggestions but with no luck. I
modified the main program 'mainprog.rb' as follows:
   puts $:
   load("stuff.rb", wrap=false)
   puts myhash["a"]

This produced following output:
  C:\rubysrcs>ruby mainprog.rb
    c:/ruby/lib/ruby/site_ruby/1.8
    c:/ruby/lib/ruby/site_ruby/1.8/i386-msvcrt
    c:/ruby/lib/ruby/site_ruby
    c:/ruby/lib/ruby/1.8
    c:/ruby/lib/ruby/1.8/i386-mswin32
    .
    mainprog.rb:5: undefined local variable or method `myhash' for
main:Object (NameError)

and it seems the pwd '.' is part of the Load Path already (without me
changing anything)

So I'm still puzzled (there are a few examples of code like this in
aforementioned tutorial book)!

Yeah I was wrong in thinking that load would load local vars. So like
others have said you will have to wrap your var in a method or class.
Or you could eval the file by reading the file in and running eval on it.

#a.rb
a = [1,2,3,4,5,6]
__________________

#b.rb
a_contents = File.open("a.rb"){|f| f.read}
eval a_contents
p a

# => [1, 2, 3, 4, 5]

-Ezra

[~/tmp] cat >a.rb
a = [1,2,3,4,5,6]
[~/tmp] cat >b.rb
a_contents = File.open("a.rb"){|f| f.read}
eval a_contents
p a
[~/tmp] ruby b.rb
b.rb:3: undefined local variable or method `a' for main:Object (NameError)
[~/tmp] ruby -v
ruby 1.8.2 (2004-12-25) [i686-linux]

This only works if you assign to 'a' somewhere in b.rb before the eval.