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