Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

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

6 views
Skip to first unread message

Grehom

unread,
Dec 18, 2005, 3:00:53 PM12/18/05
to
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.

Gene Tani

unread,
Dec 18, 2005, 3:27:20 PM12/18/05
to

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

Ezra Zygmuntowicz

unread,
Dec 18, 2005, 3:49:49 PM12/18/05
to

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


Joel VanderWerf

unread,
Dec 18, 2005, 4:27:40 PM12/18/05
to
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


Grehom

unread,
Dec 18, 2005, 5:26:21 PM12/18/05
to
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

unread,
Dec 18, 2005, 5:33:54 PM12/18/05
to
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?

Ezra Zygmuntowicz

unread,
Dec 18, 2005, 5:35:12 PM12/18/05
to

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


Joel VanderWerf

unread,
Dec 18, 2005, 5:46:24 PM12/18/05
to

[~/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.

why the lucky stiff

unread,
Dec 18, 2005, 6:41:18 PM12/18/05
to
Grehom wrote:

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

unread,
Dec 18, 2005, 8:40:09 PM12/18/05
to

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

-Ezra

Grehom

unread,
Dec 19, 2005, 3:10:48 AM12/19/05
to
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.

0 new messages