Undefined local variable

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

On Apr 25, 11:16 am, Johan E. [email protected] 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?

Chris H. wrote:

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

Hi –

David A. Black wrote:

       obj_as_list.each do |att|

def load_from_file(filename)
end

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

Hi –

On Sat, 26 Apr 2008, Johan E. wrote:

Nope. I am providing the surrounding function here. (It is defined inside
obj_as_list.each do |att|
end

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

Hi –

On Sat, 26 Apr 2008, Johan E. wrote:

 yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
   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

Johan E. wrote:

Hi –

         if att[1].is_a?(String)
 require 'yaml'
       str = "new_obj.#{att[0]} = #{att[1]}"
NameError: undefined local variable or method `att' for 

the_class.class_eval %{
This is a simple example:

- name        : Puppy

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

/Johan

Hi –

David A. Black wrote:

 yaml_dict[yaml_dict.keys[0]].each do |yaml_obj|
   end

dangling att. The whole eval thing seems extremely fragile (which eval
function to a class that has just been created based on a textfile.
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

Hi –

On Sat, 26 Apr 2008, Johan E. wrote:

Hi –

         if att[1].is_a?(String)
 require 'yaml'
       str = "new_obj.#{att[0]} = #{att[1]}"
NameError: undefined local variable or method `att' for main:Object

}
dogs:

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

Hi –

David A. Black wrote:

Nope. I am providing the surrounding function here. (It is defined
obj_as_list.each do |att|
end
out are supposed to be like.
these instances and sends them back as a list. I think some

- name        : Fido

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

David A. Black wrote:

Nope. I am providing the surrounding function here. (It is defined
obj_as_list.each do |att|
end
out are supposed to be like.
these instances and sends them back as a list. I think some

- name        : Fido

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

Johan E. wrote:

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

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

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