Well after hacking away today for a couple of hours I've come up with  
the beginnings of a rudimentary ORM for KirbyBase. I'll post what I  
have so far, and people can let me know if they are interested in a  
more complete version. It currently looks a lot like ActiveRecord,  
but obviously not as powerful. First it doesn't do ActiveRecords  
pluralization magic, although that should be easy to add. Secondly it  
doesn't have as many variations of find (but that's mitigated by  
KirbyBases's use of ruby syntax to perform selections). I've only  
implemented one kind of relationship (one-to-many, or is it many-to- 
one, some db guy can correct me on my terminology) using a  
ActiveRecord-esque has_many method. Some other problems include that  
it doesn't yet do ruby-esque getters and setters (ie. obj.something,  
and obj.something = value) instead it has get_something and  
set_something methods. I did this since I was just hacking away its  
easily remedied if anyone shows any interest in my continuing this.  
One other thing, it does not make use of KirbyBase's Link type yet,  
although if it did, it would probably be better. Again something to  
add if anyone really wants to use this. I learned a couple of things  
developing this, mostly that @@variables are evil, and that class  
instance vars are better. Without further ado here is the code. Its  
followed by some examples:

$ cat kirbyrecord.rb
require 'kirbybase'
module KirbyRecord
         class Base

                 def self.open_database( *kirby_base_new_args )
                         @@db = KirbyBase.new( *kirby_base_new_args )
                 end

                 def self.get_database
                         @@db
                 end

                 def initialize
                         @state = {}
                 end

                 def self.inherited(subclass)
                         subclass.inform_about_table
                         subclass.class_eval do
                                 subclass.fields.each do |name, type|
                                         define_method("get_# 
{name}".intern) do
                                                 @state[name]
                                         end

                                         define_method("set_# 
{name}".intern) do |value|
                                                 @state[name] = case  
type
                                                                  
when :String
                                                                         
  value.to_s
                                                                  
when :Integer
                                                                         
  value.to_i
                                                                  
when :Float
                                                                         
  value.to_f
                                                                  
when :Boolean
                                                                         
  if value then true else false end
                                                                  
when :Date
                                                                         
  value
                                                                  
when :DateTime
                                                                         
  value
                                                                 end
                                         end
                                 end
                         end
                 end

         def self.inform_about_table
                 table = get_database.get_table(table_name)
                 @fields = {}
                 table.field_names.zip( table.field_types ) do | 
field_name, field_type|
                         @fields[field_name] = field_type
                 end
                 self
         end

         def self.find(card)
                 db = get_database
                 tbl = db.get_table(table_name)
                 results = if block_given? then tbl.select { |r| yield 
(r) } else tbl.select end
                 obj_results = []
                 if card == :all
                         results.each do |res|
                                 obj = self.new
                                 self.fields.each do |field, type|
                                         obj.instance_eval { @state 
[field] = res.send(field) }
                                 end
                                 obj_results << obj
                         end
                         return obj_results
                 elsif card == :first
                         obj = self.new
                         res = results.first
                         self.fields.each do |field, type|
                                 obj.instance_eval { @state[field] =  
res.send(field) }
                         end
                         return obj
                 end
         end

         def self.table_name
                 self.to_s.split(/::/).last.downcase
         end

         def self.fields
                 @fields
         end

         def self.has_many(table_sym)
                 class_eval do
                         define_method("get_#{table_sym}".intern) do
                                 table_class_name =  
table_sym.to_s.capitalize
                                 rel_table_class = Object.const_get 
(table_class_name)
                                 results = rel_table_class.find(:all)  
{ |r| r.send("#{self.class.table_name}_id") == @state[:recno] }
                         end
                 end
         end

         def new_record?
                 @state[:recno].nil?
         end

         def save
                 db = self.class.get_database( )
                 tbl = db.get_table(self.class.table_name.intern)
                 data = @state.dup
                 data.delete(:recno)

                 if new_record?
                         @state[:recno] = tbl.insert(data)
                 else
                         tbl.update(data) { |r| r.recno == @state 
[:recno] }
                 end
                 self
         end

end
end

% cat setup_example_db.rb
require 'kirbybase'
db = KirbyBase.new

author_tbl = db.create_table(:author, :name, :String)
book_tbl = db.create_table(:book, :title, :String, :author_id, :Integer)

rn = author_tbl.insert(:name => "John Doe")
book_tbl.insert(:title => "Ruby for Dummies", :author_id => rn)
book_tbl.insert(:title => "ORM for REAL Dummies", :author_id => rn)

% ruby setup_example_db.rb

% cat has_many_example.rb
require 'kirbyrecord'

KirbyRecord::Base.open_database( )

class Author < KirbyRecord::Base
         has_many :book
end

class Book < KirbyRecord::Base
end

john_doe = Author.find(:first)  { |r| r.name =~ /John Doe/ }
john_doe.get_book.each do |book|
         puts "#{john_doe.get_name} wrote #{book.get_title}"
end

% ruby has_many_example.rb
John Doe wrote Ruby for Dummies
John Doe wrote ORM for REAL Dummies

And so on.

Other neat things

% cat setup_db.rb
require 'kirbybase'
db = KirbyBase.new

person_tbl = db.create_table(:person, :name, :String, :age, :Integer)


% ruby setup_db.rb

% cat person_ex.rb
require 'kirbyrecord'

KirbyRecord::Base.open_database( )

class Person < KirbyRecord::Base
end

person1 = Person.new
person1.set_name "John Doe"
person1.set_age 25
person1.save

person2 = Person.new
person2.set_name "Jane Doe"
person2.set_age  23
person2.save

people = Person.find(:all)

people.each do |person|
         puts "name: #{person.get_name}, age: #{person.get_age}"
         person.set_name( person.get_name + " Smith" )
         person.save
end

people = Person.find(:all)

puts "After updates:"
people.each do |person|
         puts "name: #{person.get_name}, age: #{person.get_age}"
end


% ruby person_ex.rb
name: John Doe, age: 25
name: Jane Doe, age: 23
After updates:
name: John Doe Smith, age: 25
name: Jane Doe Smith, age: 23

Other than that the only thing to mention is that  
KirbyRecord::Base.open_database( ) takes the same arguments as  
KirbyBase.new and that you should call it before inheriting from  
KirbyRecord::Base (incidently anyone have any ideas on how to avoid  
having to do this?). Also KirbyRecord::Base#find can take a block  
just like KBTable#select. There are probably lots and lots of bugs.