Accessing a YAML loaded object without the object's definition?

Discussion in 'Ruby' started by Steve Litt, Sep 29, 2008.

  1. Steve Litt

    Steve Litt Guest

    Hi all,

    In Ruby, I have a fairly complex nested object structure that I serialize to a
    yaml file. Then, in another program, I read it into a varaible like this:

    obj = YAML::load_file("myfile.yaml");

    I can see all objects and names in obj within irb, but I can't access them
    individually. For instance, in the original native that created the yaml,
    there's this:

    obj.customer.city

    You cannot access that from the object read in with load_file. It creates an
    error condition.

    What DOES work is:

    obj = Purchase.new(nil, nil)
    obj = YAML::load_file("myfile.yaml");

    puts obj.customer.city

    That prints "Apopka".

    A sample program is at the bottom of this email. As long as the classes are
    defined in the program, they can be accessed. But if an object is created via
    YAML::load_file(), I'm not able to access its data members.

    Is there any way I can do it without including the class definition in the
    code?

    Thanks

    SteveT

    Steve Litt
    Recession Relief Package
    http://www.recession-relief.US

    ############ SAMPLE PROGRAM ###################
    #!/usr/bin/ruby -w

    require "yaml"

    class Address
    attr_accessor :street, :city, :state, :zip
    def initialize(street, city, state, zip)
    @street = street
    @city = city
    @state = state
    @zip=zip
    end
    end

    class Customer
    attr_accessor :fname, :lname, :address
    def initialize( fname, lname, address)
    @fname = fname
    @lname = lname
    @address = address
    end
    end


    class Item
    attr_accessor :quantity, :priceper, :name
    def initialize(name, quantity, priceper)
    @name = name
    @quantity = quantity
    @priceper = priceper
    end
    end

    class Purchase
    attr_accessor :customer
    attr_reader :amount
    attr_accessor :date
    attr_reader :items

    def initialize(customer, date)
    @customer = customer
    @amount = amount
    @date = date
    @items = Array.new()
    end
    def additem(item)
    @items.push(item)
    end
    def update_amount()
    @amount = 0
    @items.each do
    |item|
    @amount += (item.quantity.to_f * item.priceper.to_f)
    end
    end
    end

    #### MAIN ROUTINE
    #### Load objects
    address = Address.new(["121 Main Street", "Suite
    201"], "Apopka", "FL", "33333");

    customer = Customer.new("Steve", "Litt", address)

    purchase = Purchase.new(customer, "3/3/2033")
    purchase.additem(Item.new("Widget", 1, 1.00));
    purchase.additem(Item.new("Gadget", 2, 2.00));
    purchase.additem(Item.new("Left handed smoke bender", 3, 3.00));
    purchase.update_amount()

    #### Write out YAML to junk.yaml
    ouf = File.new("./junk.yaml", "w");
    ouf.write(YAML::dump(purchase))
    ouf.close()

    #### WRITE REPORT
    #### Read YAML file and load into Purchase object p
    p=Purchase.new(nil, nil)
    p=YAML::load_file("./junk.yaml");

    #### Date and total
    printf "Purchase on %s, total cost $%0.2f\n", p.date, p.amount

    #### Customer data
    printf "\nCUSTOMER DATA:\n"
    printf "%s %s\n", p.customer.fname, p.customer.lname
    p.customer.address.street.each {|i| puts i}
    printf "%s, %s, %s\n", p.customer.address.city, p.customer.address.state,
    p.customer.address.zip

    #### Items
    printf "\nITEMS PURCHASED\n"
    printf "%30s %10s %10s %10s\n", "ITEM NAME", "QUANTITY", "@", "TOTAL"
    p.items.each do
    |item|
    printf "%30s %10d %10.2f %10.2f\n", item.name, item.quantity, item.priceper,
    item.quantity * item.priceper

    end
    printf "%30s %10s %10s %10s\n", " ", " ", " ", "----------"
    printf "%30s %10s %10s %10.2f\n", "TOTAL", " ", " ", p.amount

    ############ END OF SAMPLE PROGRAM ###################
    Steve Litt, Sep 29, 2008
    #1
    1. Advertising

  2. Steve Litt wrote:
    > Hi all,
    >
    > In Ruby, I have a fairly complex nested object structure that I serialize to a
    > yaml file. Then, in another program, I read it into a varaible like this:
    >
    > obj = YAML::load_file("myfile.yaml");
    >
    > I can see all objects and names in obj within irb, but I can't access them
    > individually. For instance, in the original native that created the yaml,
    > there's this:
    >
    > obj.customer.city
    >
    > You cannot access that from the object read in with load_file. It creates an
    > error condition.
    >
    > What DOES work is:
    >
    > obj = Purchase.new(nil, nil)
    >


    That line is unnecessary (I tried your code and commented out that line,
    worked fine.)

    > obj = YAML::load_file("myfile.yaml");
    >
    > puts obj.customer.city
    >
    > That prints "Apopka".
    >
    > A sample program is at the bottom of this email. As long as the classes are
    > defined in the program, they can be accessed. But if an object is created via
    > YAML::load_file(), I'm not able to access its data members.
    >
    > Is there any way I can do it without including the class definition in the
    > code?
    >


    Not really. It cannot generate the classes out of thin air and the YAML
    files just store the name of the class. But you could put the class
    definitions in separate files so they can be 'required' anywhere you
    need them.

    -Justin
    Justin Collins, Sep 29, 2008
    #2
    1. Advertising

  3. Steve Litt

    Dejan Dimic Guest

    On Sep 29, 8:05 pm, Steve Litt <> wrote:
    > Hi all,
    >
    > In Ruby, I have a fairly complex nested object structure that I serializeto a
    > yaml file. Then, in another program, I read it into a varaible like this:
    >
    > obj = YAML::load_file("myfile.yaml");
    >
    > I can see all objects and names in obj within irb, but I can't access them
    > individually. For instance, in the original native that created the yaml,
    > there's this:
    >
    > obj.customer.city
    >
    > You cannot access that from the object read in with load_file. It createsan
    > error condition.
    >
    > What DOES work is:
    >
    > obj = Purchase.new(nil, nil)
    > obj = YAML::load_file("myfile.yaml");
    >
    > puts obj.customer.city
    >
    > That prints "Apopka".
    >
    > A sample program is at the bottom of this email. As long as the classes are
    > defined in the program, they can be accessed. But if an object is createdvia
    > YAML::load_file(), I'm not able to access its data members.
    >
    > Is there any way I can do it without including the class definition in the
    > code?
    >
    > Thanks
    >
    > SteveT
    >
    > Steve Litt
    > Recession Relief Packagehttp://www.recession-relief.US
    >
    > ############ SAMPLE PROGRAM ###################
    > #!/usr/bin/ruby -w
    >
    > require "yaml"
    >
    > class Address
    >         attr_accessor :street, :city, :state, :zip
    >         def initialize(street, city, state, zip)
    >                 @street = street
    >                 @city = city
    >                 @state = state
    >                 @zip=zip
    >         end
    > end
    >
    > class Customer
    >         attr_accessor :fname, :lname, :address
    >         def initialize( fname, lname, address)
    >                 @fname = fname
    >                 @lname = lname
    >                 @address = address
    >         end
    > end
    >
    > class Item
    >         attr_accessor :quantity, :priceper, :name
    >         def initialize(name, quantity, priceper)
    >                 @name = name
    >                 @quantity = quantity
    >                 @priceper = priceper
    >         end
    > end
    >
    > class Purchase
    >         attr_accessor :customer
    >         attr_reader :amount
    >         attr_accessor :date
    >         attr_reader :items
    >
    >         def initialize(customer, date)
    >                 @customer = customer
    >                 @amount = amount
    >                 @date = date
    >                 @items = Array.new()
    >         end
    >         def additem(item)
    >                 @items.push(item)
    >         end
    >         def update_amount()
    >                 @amount = 0
    >                 @items.each do
    >                         |item|
    >                         @amount += (item.quantity.to_f * item.priceper.to_f)
    >                 end
    >         end
    > end
    >
    > #### MAIN ROUTINE
    > #### Load objects
    > address = Address.new(["121 Main Street", "Suite
    > 201"], "Apopka", "FL", "33333");
    >
    > customer = Customer.new("Steve", "Litt", address)
    >
    > purchase = Purchase.new(customer, "3/3/2033")
    > purchase.additem(Item.new("Widget", 1, 1.00));
    > purchase.additem(Item.new("Gadget", 2, 2.00));
    > purchase.additem(Item.new("Left handed smoke bender", 3, 3.00));
    > purchase.update_amount()
    >
    > #### Write out YAML to junk.yaml
    > ouf = File.new("./junk.yaml", "w");
    > ouf.write(YAML::dump(purchase))
    > ouf.close()
    >
    > #### WRITE REPORT
    > #### Read YAML file and load into Purchase object p
    > p=Purchase.new(nil, nil)
    > p=YAML::load_file("./junk.yaml");
    >
    > #### Date and total
    > printf "Purchase on %s, total cost $%0.2f\n", p.date, p.amount
    >
    > #### Customer data
    > printf "\nCUSTOMER DATA:\n"
    > printf "%s %s\n", p.customer.fname, p.customer.lname
    > p.customer.address.street.each {|i| puts i}
    > printf "%s, %s, %s\n", p.customer.address.city, p.customer.address.state,
    > p.customer.address.zip
    >
    > #### Items
    > printf "\nITEMS PURCHASED\n"
    > printf "%30s %10s %10s %10s\n", "ITEM NAME", "QUANTITY", "@", "TOTAL"
    > p.items.each do
    >         |item|
    >         printf "%30s %10d %10.2f %10.2f\n", item.name, item.quantity, item.priceper,
    > item.quantity * item.priceper
    >
    > end
    > printf "%30s %10s %10s %10s\n", " ", " ", " ", "----------"
    > printf "%30s %10s %10s %10.2f\n", "TOTAL", " ", " ", p.amount
    >
    > ############ END OF SAMPLE PROGRAM ###################


    take look at: http://yaml4r.sourceforge.net/doc/page/type_families.htm
    Dejan Dimic, Sep 29, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. RubyQuestions
    Replies:
    0
    Views:
    220
    RubyQuestions
    Dec 3, 2003
  2. Paul Battley

    YAML.dump/YAML.load bug

    Paul Battley, Aug 3, 2005, in forum: Ruby
    Replies:
    0
    Views:
    176
    Paul Battley
    Aug 3, 2005
  3. Eric Promislow
    Replies:
    4
    Views:
    207
    Eric Promislow
    Oct 31, 2006
  4. Fransiscus Xaverius

    YAML Problem YAML::Object

    Fransiscus Xaverius, Dec 14, 2007, in forum: Ruby
    Replies:
    2
    Views:
    156
    Fransiscus Xaverius
    Dec 14, 2007
  5. Jonathan Gold
    Replies:
    0
    Views:
    138
    Jonathan Gold
    May 19, 2009
Loading...

Share This Page