YAML to objects - how?

I'm trying to read in a YAML file that has a list of database specs
(name, fields, indexes, etc.) Once that's read in, I'd like to turn
them into an array of db objects. In the end, I want to loop through
the array and generate some code based on each database spec.

Is there an easy way to do this?

I've been staring at: http://whytheluckystiff.net/ruby/yaml-defaults-mixin.rb

It seems to be about the only thing I can find that discusses
object_maker and add_domain_type which seem relevant, but may very
well have nothing to do with what I'm after.

Any suggestions? Should I point out that I've never done anything
with YAML, or is that obvious by now?

thx in advance.

···

--
Bill Guindon (aka aGorilla)

Bill Guindon wrote:

I'm trying to read in a YAML file that has a list of database specs
(name, fields, indexes, etc.) Once that's read in, I'd like to turn
them into an array of db objects. In the end, I want to loop through
the array and generate some code based on each database spec.

Is the YAML file something like this?

···

---
-
   name: Foo
   fields:
     - :x
     - :y
     - :z
   indexes:
-
   name: Bar
   fields:
     - :a
     - :b
     - :c
   indexes:

If so, then you can just YAML.load() the file, and you'll get an array of hashes, which you can iterate over.

Pretty close (should've included it)
Do I need the colons before the field names? I'm not doing that now.

Here's a couple table's worth:

···

On Mon, 7 Mar 2005 06:44:59 +0900, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

Bill Guindon wrote:
> I'm trying to read in a YAML file that has a list of database specs
> (name, fields, indexes, etc.) Once that's read in, I'd like to turn
> them into an array of db objects. In the end, I want to loop through
> the array and generate some code based on each database spec.

Is the YAML file something like this?

---
-
   name: Foo
   fields:
     - :x
     - :y
     - :z
   indexes:
-
   name: Bar
   fields:
     - :a
     - :b
     - :c
   indexes:

---
  -
    name: PM_Static_SettingsDB
    file: settings.dbf
    fdel: false
    dnoc: false
    fields:
      - key CHAR 254
      - redir CHAR 254
      - admin CHAR 254
      - hidehelp BOOL
      - last_tab CHAR 50

    indexes:
      -
        file: cats.mvx
        expr: PM_Static_catsDB.d.cat_id
        flag: nounique, ascending
  -
    name: PM_Static_KeysDB
    file: keys.dbf
    fdel: false
    dnoc: true

    fields:
      - name CHAR 50
      - value NUMBER
    indexes:
      -
        file: keys.mvx
        expr: PM_Static_KeysDB.d.name
        flag: nounique, ascending

If so, then you can just YAML.load() the file, and you'll get an array
of hashes, which you can iterate over.

I'll give that a shot, was wondering if there was a way to auto create
objects from the YAML load, but yeah, I could loop through them and do
it that way. I'll see how it goes.

--
Bill Guindon (aka aGorilla)

Bill Guindon wrote:

Do I need the colons before the field names? I'm not doing that now.

Oh, not at all. I just did that because I tend to use symbols rather than strings when I am describing attr_accessors and the like. But you can use strings for better readability in the yaml file.

I'll give that a shot, was wondering if there was a way to auto create
objects from the YAML load, but yeah, I could loop through them and do
it that way. I'll see how it goes.

If you want to autocreate, you can use the syntax for defining the class of objects, but the YAML file will look messier. You can see how it will look by creating some objects in ruby code, and them calling #to_yaml on them. F'rexample:

   require 'yaml'

   class C
     attr_accessor :x
   end

   c = C.new
   c.x = {:foo => ["bar"] }

   puts c.to_yaml

The output is

--- !ruby/object:C
x:
   :foo:
     - bar

If you YAML.load this, it will create an instance of C.

Alternately maybe there is some hook in the YAML parser that lets you say "instantiate all hashes with objects of class C", but that seems problematic if you use hashes elsewhere in the data.

Another option is to extend the YAML parser to recognize some custom types that have less cumbersome syntax than "!ruby/object:YourClass". You can find examples in yaml/types.rb in your ruby lib dir.

I ended up going with your first suggestion (after getting a slightly
firmer grasp of YAML). The alternatives seem to carry too high a
price for "auto" object creation.

In the long term, I hope that changes, in the short term, looping
through what I have will work fine.

Thx for you input.

···

On Mon, 7 Mar 2005 07:46:42 +0900, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

Bill Guindon wrote:
> Do I need the colons before the field names? I'm not doing that now.

Oh, not at all. I just did that because I tend to use symbols rather
than strings when I am describing attr_accessors and the like. But you
can use strings for better readability in the yaml file.

> I'll give that a shot, was wondering if there was a way to auto create
> objects from the YAML load, but yeah, I could loop through them and do
> it that way. I'll see how it goes.

If you want to autocreate, you can use the syntax for defining the class
of objects, but the YAML file will look messier. You can see how it will
look by creating some objects in ruby code, and them calling #to_yaml on
them. F'rexample:

   require 'yaml'

   class C
     attr_accessor :x
   end

   c = C.new
   c.x = {:foo => ["bar"] }

   puts c.to_yaml

The output is

--- !ruby/object:C
x:
   :foo:
     - bar

If you YAML.load this, it will create an instance of C.

Alternately maybe there is some hook in the YAML parser that lets you
say "instantiate all hashes with objects of class C", but that seems
problematic if you use hashes elsewhere in the data.

Another option is to extend the YAML parser to recognize some custom
types that have less cumbersome syntax than "!ruby/object:YourClass".
You can find examples in yaml/types.rb in your ruby lib dir.

--
Bill Guindon (aka aGorilla)