From: Johan Eriksson Date: 2008-04-27T02:57:28+09:00 Subject: Re: undefined local variable Hi -- David A. Black wrote: > Hi -- > > On Sat, 26 Apr 2008, Johan Eriksson wrote: > >> Hi -- >> >> David A. Black 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 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(< 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 --