I've just released Lafcadio 0.8.0, the new production release. It
contains more than 40 new features and bugfixes. And it adds lots of
convenience methods to DomainObject, richer query inference operators,
real-time query subset caching -- all in a slimmer codebase.

== What's Lafcadio? ==

Lafcadio is an object-relational mapping library for use with MySQL. It
supports a lot of advanced features, including extensive aid in mapping
to legacy databases, in-Ruby triggers, and an advanced query engine
that allows you to form queries in Ruby that can be run either against
the live database, or an in-memory mock store for testing purposes.

I use it in production code on a regular basis, most notably at
Rhizome.org, an online community with more than 1 million pageviews a
month.

http://lafcadio.rubyforge.org/

== What's new? ==

= Better operators for query inference:

class User < Lafcadio::DomainObject
  strings :fname, :lname, :email
end

maybe_koreans = User.get { |u| u.lname.in( 'Park', 'Lee', 'Hwang' ) }
no_fname = User.get { |u| u.fname.nil? }

As always, these queries work both against MySQL and against a much
faster, in-memory mock object store for use in testing.

= Query Caching:

Everytime you run a select against the DB, Lafcadio caches the results
in memory. Then, if you later run a second select that is a subset of
the first, Lafcadio detects it, figures out what it's a subset of,
filters out the results in memory, and returns you the results. This
all happens transparently.

What does this mean? It means a significantly faster app, because if
you run these three queries:

select * from users where lname = 'Smith'
select * from users where lname = 'Smith' and fname like '%john%'
select * from users where lname = 'Smith' and email like '%hotmail%'

Lafcadio will only ask MySQL for the results for the first select
statement, and do the rest for you without using the DB connection.

= Convenience methods for DomainObject:

puts User.exist?
u = User[15]
u.update!( :fname => 'Bill' )
u.delete!
all_users = User.all
first_user = User.first
last_user = User.last