undefined local variable

J

Johan Eriksson

Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end

If I type it in irb it works, but when loaded from a function I get this:

undefined local variable or method `att' for main:Object

It refers to the line inside the if-statement. Any ideas?

/Johan
 
C

Chris Hulan

Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?
 
J

Johan Eriksson

Chris said:
Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?

Nope. I am providing the surrounding function here. (It is defined
inside a class.)

def load_from_file(filename)
require 'yaml'
yaml_dict = YAML::load(File.open(filename))
object_list = [] #The list that should be returned
yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
new_obj = self.class.new
yaml_obj.each do |obj|
obj_as_list = obj.to_a
obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]}'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end
end
object_list << new_obj
end
object_list
end

And the error:

NameError: undefined local variable or method `att' for main:Object

/Johan
 
D

David A. Black

Hi --

Chris said:
Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?

Nope. I am providing the surrounding function here. (It is defined inside a
class.)

def load_from_file(filename)
require 'yaml'
yaml_dict = YAML::load(File.open(filename))
object_list = [] #The list that should be returned
yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
new_obj = self.class.new
yaml_obj.each do |obj|
obj_as_list = obj.to_a
obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]}'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end
end
object_list << new_obj
end
object_list
end

And the error:

NameError: undefined local variable or method `att' for main:Object

If att[1] is, say, :att, then "#{att[1]}" is "att" and you've got a
dangling att. The whole eval thing seems extremely fragile (which eval
things usually are). I imagine there's a more robust and probably
shorter way to do this, but I'm not sure what the data coming in and
out are supposed to be like.


David

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!
 
J

Johan Eriksson

Hi --
Hi --

Chris said:
Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?

Nope. I am providing the surrounding function here. (It is defined
inside a class.)

def load_from_file(filename)
require 'yaml'
yaml_dict = YAML::load(File.open(filename))
object_list = [] #The list that should be returned
yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
new_obj = self.class.new
yaml_obj.each do |obj|
obj_as_list = obj.to_a
obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]}'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end
end
object_list << new_obj
end
object_list
end

And the error:

NameError: undefined local variable or method `att' for main:Object

If att[1] is, say, :att, then "#{att[1]}" is "att" and you've got a
dangling att. The whole eval thing seems extremely fragile (which eval
things usually are). I imagine there's a more robust and probably
shorter way to do this, but I'm not sure what the data coming in and
out are supposed to be like.


David

I am almost positive that there is, given that I'm pretty much a noob at
ruby. The whole thing is a class_eval too. The idea is to add this
function to a class that has just been created based on a textfile. The
function will receive a file that includes a yaml description of
instances of the class, and the function then makes these instances and
sends them back as a list. I think some fragility is okay, though I'd be
keen on learning better ways to do this. Around the entire function is

the_class.class_eval %{
the function...
}

I am confused about why it doesn't work though.

/Johan
 
D

David A. Black

Hi --

Hi --
Hi --

Chris Hulan wrote:
Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?


Nope. I am providing the surrounding function here. (It is defined inside
a class.)

def load_from_file(filename)
require 'yaml'
yaml_dict = YAML::load(File.open(filename))
object_list = [] #The list that should be returned
yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
new_obj = self.class.new
yaml_obj.each do |obj|
obj_as_list = obj.to_a
obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]}'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end
end
object_list << new_obj
end
object_list
end

And the error:

NameError: undefined local variable or method `att' for main:Object

If att[1] is, say, :att, then "#{att[1]}" is "att" and you've got a
dangling att. The whole eval thing seems extremely fragile (which eval
things usually are). I imagine there's a more robust and probably
shorter way to do this, but I'm not sure what the data coming in and
out are supposed to be like.


David

I am almost positive that there is, given that I'm pretty much a noob at
ruby. The whole thing is a class_eval too. The idea is to add this function
to a class that has just been created based on a textfile. The function will
receive a file that includes a yaml description of instances of the class,
and the function then makes these instances and sends them back as a list. I
think some fragility is okay, though I'd be keen on learning better ways to
do this. Around the entire function is

the_class.class_eval %{
the function...
}

I am confused about why it doesn't work though.

Can you give some sample YAML input? I'm still not quite picturing it.


David

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!
 
J

Johan Eriksson

Hi --
Hi --

Hi --
Hi --

On Sat, 26 Apr 2008, Johan Eriksson wrote:

Chris Hulan wrote:
Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?


Nope. I am providing the surrounding function here. (It is defined
inside a class.)

def load_from_file(filename)
require 'yaml'
yaml_dict = YAML::load(File.open(filename))
object_list = [] #The list that should be returned
yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
new_obj = self.class.new
yaml_obj.each do |obj|
obj_as_list = obj.to_a
obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]}'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end
end
object_list << new_obj
end
object_list
end

And the error:

NameError: undefined local variable or method `att' for main:Object

If att[1] is, say, :att, then "#{att[1]}" is "att" and you've got a
dangling att. The whole eval thing seems extremely fragile (which eval
things usually are). I imagine there's a more robust and probably
shorter way to do this, but I'm not sure what the data coming in and
out are supposed to be like.


David

I am almost positive that there is, given that I'm pretty much a noob
at ruby. The whole thing is a class_eval too. The idea is to add this
function to a class that has just been created based on a textfile.
The function will receive a file that includes a yaml description of
instances of the class, and the function then makes these instances
and sends them back as a list. I think some fragility is okay, though
I'd be keen on learning better ways to do this. Around the entire
function is

the_class.class_eval %{
the function...
}

I am confused about why it doesn't work though.

Can you give some sample YAML input? I'm still not quite picturing it.


David

This is a simple example:

dogs:
- name : Fido
age : 2

- name : Rufus

- name : Doggie
age : 4

- name : Puppy
age : 1

The function should then create four instances of dog, assign them the
names and ages specified, put them in a list and return them.

Thanks for taking the time to help me out!

/Johan
 
J

Johan Eriksson

Johan said:
Hi --
Hi --

Hi --

David A. Black wrote:
Hi --

On Sat, 26 Apr 2008, Johan Eriksson wrote:

Chris Hulan wrote:
Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?


Nope. I am providing the surrounding function here. (It is defined
inside a class.)

def load_from_file(filename)
require 'yaml'
yaml_dict = YAML::load(File.open(filename))
object_list = [] #The list that should be returned
yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
new_obj = self.class.new
yaml_obj.each do |obj|
obj_as_list = obj.to_a
obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]}'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end
end
object_list << new_obj
end
object_list
end

And the error:

NameError: undefined local variable or method `att' for
main:Object

If att[1] is, say, :att, then "#{att[1]}" is "att" and you've got a
dangling att. The whole eval thing seems extremely fragile (which eval
things usually are). I imagine there's a more robust and probably
shorter way to do this, but I'm not sure what the data coming in and
out are supposed to be like.


David


I am almost positive that there is, given that I'm pretty much a noob
at ruby. The whole thing is a class_eval too. The idea is to add this
function to a class that has just been created based on a textfile.
The function will receive a file that includes a yaml description of
instances of the class, and the function then makes these instances
and sends them back as a list. I think some fragility is okay, though
I'd be keen on learning better ways to do this. Around the entire
function is

the_class.class_eval %{
the function...
}

I am confused about why it doesn't work though.

Can you give some sample YAML input? I'm still not quite picturing it.


David

This is a simple example:

dogs:
- name : Fido
age : 2

- name : Rufus

- name : Doggie
age : 4

- name : Puppy
age : 1

The function should then create four instances of dog, assign them the
names and ages specified, put them in a list and return them.

Thanks for taking the time to help me out!

/Johan

No ideas, anybody? I really don't see why it does not find the variable
there, as it finds it in if-statement.

/Johan
 
D

David A. Black

Hi --

Hi --
Hi --

Hi --

David A. Black wrote:
Hi --

On Sat, 26 Apr 2008, Johan Eriksson wrote:

Chris Hulan wrote:
Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?


Nope. I am providing the surrounding function here. (It is defined
inside a class.)

def load_from_file(filename)
require 'yaml'
yaml_dict = YAML::load(File.open(filename))
object_list = [] #The list that should be returned
yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
new_obj = self.class.new
yaml_obj.each do |obj|
obj_as_list = obj.to_a
obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]}'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end
end
object_list << new_obj
end
object_list
end

And the error:

NameError: undefined local variable or method `att' for main:Object

If att[1] is, say, :att, then "#{att[1]}" is "att" and you've got a
dangling att. The whole eval thing seems extremely fragile (which eval
things usually are). I imagine there's a more robust and probably
shorter way to do this, but I'm not sure what the data coming in and
out are supposed to be like.


David


I am almost positive that there is, given that I'm pretty much a noob at
ruby. The whole thing is a class_eval too. The idea is to add this
function to a class that has just been created based on a textfile. The
function will receive a file that includes a yaml description of instances
of the class, and the function then makes these instances and sends them
back as a list. I think some fragility is okay, though I'd be keen on
learning better ways to do this. Around the entire function is

the_class.class_eval %{
the function...
}

I am confused about why it doesn't work though.

Can you give some sample YAML input? I'm still not quite picturing it.


David

This is a simple example:

dogs:
- name : Fido
age : 2

- name : Rufus

- name : Doggie
age : 4

- name : Puppy
age : 1

The function should then create four instances of dog, assign them the names
and ages specified, put them in a list and return them.

Thanks for taking the time to help me out!

Why not do this (or something similar):

require 'yaml'

class Dog
attr_accessor :name, :age
end

animals = YAML.load(<<EOA)
dogs:
- name : Fido
age : 2

- name : Rufus

- name : Doggie
age : 4

- name : Puppy
age : 1
EOA

dogs = animals["dogs"]
dog_objects = dogs.map do |name,age|
d = Dog.new
d.name = name
d.age = age
d
end

p dog_objects


David

--
Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!
 
J

Johan Eriksson

Hi --
Hi --

Hi --
Hi --

On Sat, 26 Apr 2008, Johan Eriksson wrote:

Hi --

David A. Black wrote:
Hi --

On Sat, 26 Apr 2008, Johan Eriksson wrote:

Chris Hulan wrote:
Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?


Nope. I am providing the surrounding function here. (It is defined
inside a class.)

def load_from_file(filename)
require 'yaml'
yaml_dict = YAML::load(File.open(filename))
object_list = [] #The list that should be returned
yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
new_obj = self.class.new
yaml_obj.each do |obj|
obj_as_list = obj.to_a
obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]}'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end
end
object_list << new_obj
end
object_list
end

And the error:

NameError: undefined local variable or method `att' for
main:Object

If att[1] is, say, :att, then "#{att[1]}" is "att" and you've got a
dangling att. The whole eval thing seems extremely fragile (which eval
things usually are). I imagine there's a more robust and probably
shorter way to do this, but I'm not sure what the data coming in and
out are supposed to be like.


David


I am almost positive that there is, given that I'm pretty much a
noob at ruby. The whole thing is a class_eval too. The idea is to
add this function to a class that has just been created based on a
textfile. The function will receive a file that includes a yaml
description of instances of the class, and the function then makes
these instances and sends them back as a list. I think some
fragility is okay, though I'd be keen on learning better ways to do
this. Around the entire function is

the_class.class_eval %{
the function...
}

I am confused about why it doesn't work though.

Can you give some sample YAML input? I'm still not quite picturing it.


David

This is a simple example:

dogs:
- name : Fido
age : 2

- name : Rufus

- name : Doggie
age : 4

- name : Puppy
age : 1

The function should then create four instances of dog, assign them the
names and ages specified, put them in a list and return them.

Thanks for taking the time to help me out!

Why not do this (or something similar):

require 'yaml'

class Dog
attr_accessor :name, :age
end

animals = YAML.load(<<EOA)
dogs:
- name : Fido
age : 2

- name : Rufus

- name : Doggie
age : 4

- name : Puppy
age : 1
EOA

dogs = animals["dogs"]
dog_objects = dogs.map do |name,age|
d = Dog.new
d.name = name
d.age = age
d
end

p dog_objects


David

Thanks a lot! I think this will be very helpful. I didn't know map
worked like this. I'll need to adapt it to work even though I don't know
the name of the class in advance, but that's workable, right?

/Johan

--
 
J

Johan Eriksson

David said:
Hi --

Hi --
Hi --

On Sat, 26 Apr 2008, Johan Eriksson wrote:

Hi --

David A. Black wrote:
Hi --

On Sat, 26 Apr 2008, Johan Eriksson wrote:

Chris Hulan wrote:
Hi!

I have some troubles with this.

obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]'"
You're missing a '}' here ----------^

does that help?


Nope. I am providing the surrounding function here. (It is defined
inside a class.)

def load_from_file(filename)
require 'yaml'
yaml_dict = YAML::load(File.open(filename))
object_list = [] #The list that should be returned
yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
new_obj = self.class.new
yaml_obj.each do |obj|
obj_as_list = obj.to_a
obj_as_list.each do |att|
if att[1].is_a?(String)
att[1] = "'#{att[1]}'"
end
str = "new_obj.#{att[0]} = #{att[1]}"
eval(str)
end
end
object_list << new_obj
end
object_list
end

And the error:

NameError: undefined local variable or method `att' for
main:Object

If att[1] is, say, :att, then "#{att[1]}" is "att" and you've got a
dangling att. The whole eval thing seems extremely fragile (which eval
things usually are). I imagine there's a more robust and probably
shorter way to do this, but I'm not sure what the data coming in and
out are supposed to be like.


David


I am almost positive that there is, given that I'm pretty much a
noob at ruby. The whole thing is a class_eval too. The idea is to
add this function to a class that has just been created based on a
textfile. The function will receive a file that includes a yaml
description of instances of the class, and the function then makes
these instances and sends them back as a list. I think some
fragility is okay, though I'd be keen on learning better ways to do
this. Around the entire function is

the_class.class_eval %{
the function...
}

I am confused about why it doesn't work though.

Can you give some sample YAML input? I'm still not quite picturing it.


David

This is a simple example:

dogs:
- name : Fido
age : 2

- name : Rufus

- name : Doggie
age : 4

- name : Puppy
age : 1

The function should then create four instances of dog, assign them the
names and ages specified, put them in a list and return them.

Thanks for taking the time to help me out!

Why not do this (or something similar):

require 'yaml'

class Dog
attr_accessor :name, :age
end

animals = YAML.load(<<EOA)
dogs:
- name : Fido
age : 2

- name : Rufus

- name : Doggie
age : 4

- name : Puppy
age : 1
EOA

dogs = animals["dogs"]
dog_objects = dogs.map do |name,age|
d = Dog.new
d.name = name
d.age = age
d
end

p dog_objects


David

Okay. The problem with this is that name gets bound to "name" => "Alice"
and age to "age" => 20 or something similar. Also I don't know in
advance what attributes the objects will have, as the class is also
generated from a textfile (earlier).

Again, thank for the help!

/Johan
 
J

Johan Eriksson

Hi --

This is what I've got now.

the_class.class_eval <<-EOA

def self.load_from_file(filename)
yaml_dict = YAML::load(File.open(filename))
object_list = yaml_dict[yaml_dict.keys[0]].map do |from_file|
puts "from_file: #{from_file}"
new_obj = self.class.new
from_file.map do |obj|
puts "obj: #{obj}"
obj_as_list = obj.to_a
puts "obj_as_list: #{obj_as_list}"
if obj_as_list[1].is_a? String
obj_as_list[1] = "'#{obj_as_list[1]}'"
end
str = "new_obj.#{obj_as_list[0]} = #{obj_as_list[1]}"
eval(str)
end
new_obj
end
object_list
end
EOA

It gets me this: undefined local variable or method `from_file' for
main:Object


If I do the same thing outside of a class_eval it works fine, but I need
to add it to a class I have just generated. Why does it not recognise
the variable.

Any help is much appreciated!

/Johan
 
T

ts

Johan said:
the_class.class_eval <<-EOA

First, you don't need the evil eval
def self.load_from_file(filename)
yaml_dict = YAML::load(File.open(filename))
object_list = yaml_dict[yaml_dict.keys[0]].map do |from_file|
puts "from_file: #{from_file}"
new_obj = self.class.new

self will be `the_class', this mean that you must write

new_obj = new
from_file.map do |obj|
puts "obj: #{obj}"
obj_as_list = obj.to_a
puts "obj_as_list: #{obj_as_list}"
if obj_as_list[1].is_a? String
obj_as_list[1] = "'#{obj_as_list[1]}'"
end
str = "new_obj.#{obj_as_list[0]} = #{obj_as_list[1]}"

Another occurence of the evil eval
eval(str)
end
new_obj
end
object_list
end
EOA

Try something like this

def the_class.load_from_file(filename)
yaml_dict = YAML::load(File.open(filename))
object_list = yaml_dict[yaml_dict.keys[0]].map do |from_file|
puts "from_file: #{from_file}"
new_obj = new
from_file.map do |obj|
puts "obj: #{obj}"
obj_as_list = obj.to_a
puts "obj_as_list: #{obj_as_list}"
new_obj.send("#{obj_as_list[0]}=", obj_as_list[1])
end
new_obj
end
object_list
end


Guy Decoux
 
S

Simon Krahnke

* ts said:
def the_class.load_from_file(filename)
yaml_dict = YAML::load(File.open(filename))
object_list = yaml_dict[yaml_dict.keys[0]].map do |from_file|
puts "from_file: #{from_file}"
new_obj = new
from_file.map do |obj|
puts "obj: #{obj}"
obj_as_list = obj.to_a

Why not attr, value = *obj.to_a
puts "obj_as_list: #{obj_as_list}"
new_obj.send("#{obj_as_list[0]}=", obj_as_list[1])

And use attr and value instead of ...[0] and ...[1].
end
new_obj
end
object_list
end

The object_list variable seems to be useless, the method would return
value without it.

mfg, simon .... l
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top