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

G

Grehom

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.
 
G

Gene Tani

Grehom said:
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
 
E

Ezra Zygmuntowicz

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.

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
 
J

Joel VanderWerf

Grehom said:
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>
 
G

Grehom

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
 
G

Grehom

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?
 
E

Ezra Zygmuntowicz

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
 
J

Joel VanderWerf

Ezra said:
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.
 
W

why the lucky stiff

Grehom said:
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
 
E

Ezra Zygmuntowicz

Ezra said:
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.

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

-Ezra
 
G

Grehom

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top