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

You're missing a '}' here ----------^

does that help?

···

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> wrote:

Hi!

I have some troubles with this.

           obj_as_list.each do |att|
             if att[1].is_a?(String)
               att[1] = "'#{att[1]'"

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

/Johan

···

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> wrote:

Hi --

···

On Sat, 26 Apr 2008, Johan Eriksson wrote:

Chris Hulan wrote:

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> 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

--
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!

Hi --

David A. Black wrote:

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.

/Johan

···

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> wrote:

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:

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> 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!

Hi --

David A. Black wrote:

Hi --

Hi --

David A. Black wrote:

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

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

···

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> wrote:

Johan Eriksson wrote:

Hi --

David A. Black wrote:

Hi --

Hi --

David A. Black wrote:

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

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

···

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> wrote:

Hi --

Hi --

David A. Black wrote:

Hi --

Hi --

David A. Black wrote:

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

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

···

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> wrote:

--
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!

Hi --

David A. Black wrote:

Hi --

Hi --

David A. Black wrote:

Hi --

Hi --

David A. Black wrote:

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

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

···

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> wrote:

--

David A. Black wrote:

Hi --

Hi --

David A. Black wrote:

Hi --

Hi --

David A. Black wrote:

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

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

···

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Sat, 26 Apr 2008, Johan Eriksson wrote:

On Apr 25, 11:16 am, Johan Eriksson <jo...@johaneriksson.se> wrote:

--
Right Wing Liberal - http://johaneriksson.se
Kulturrevolution - http://kulturrevolution.se

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

* ts <decoux@moulon.inra.fr> (2008-04-28) schrieb:

   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