I've just released Lafcadio 0.9.0, the new development release. This
release adds transactions, more query options for queries that will run
both against MySQL or against an in-memory mock database, convenience
methods for reducing setup code for test cases, and more.

As always, odd-numbered releases should be considered beta; if you want
to play it safe, use the stable release 0.8.1 instead.

== 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? ==

= Transaction support:

Obviously, such support only applies if the underlying table is one
that supports transactions; so far I've tested this with InnoDB.

  object_store = Lafcadio::ObjectStore.get_object_store
  object_store.transaction do |tr|
    Client.new( 'name' => 'some company' ).commit
    tr.rollback
    raise "We'll never get to this line"
  end
  Client.all.size # => 0
  object_store.transaction do |tr|
    Client.new( 'name' => 'some company' ).commit
  end
  Client.all.size # => 1

= Queries support count clauses and multi-row order clauses:

As always, these new query features work both against MySQL and the
in-memory mock database.

  # Count querying
  3.times do
    Client.new( 'name' => 'name' ).commit
  end
  Client.get( :group => :count ).only[:count] # => 3

  # Multi-row order clause
  qry = Query.infer(
    SKU,
    :order_by => [ :standardPrice, :salePrice ],
    :order_by_order => Query::DESC
  ) { |s| s.sku.nil? }
  qry.to_sql     # => "select * from skus where skus.sku is null
                 #     order by standardPrice, salePrice desc"

= Default mocking behavior:

When you're writing lots of tests, particularly when you're dealing
with lots of domain classes that relate to one another, setups can be
time-consuming and boring. Lafcadio 0.9.0 adds functionality to
DomainObject to ease this pain.

  require 'lafcadio/test'
  # DomainObject.default_mock guesses as default, non-nil
  # values, and fills in relations, too
  catalog_order = CatalogOrder.default_mock
  ship_country = catalog_order.ship_address.country
  # DomainObject.custom_mock allows you to override default
  # values
  catalog_order2 = CatalogOrder.custom_mock( :amount => 100.99 )
  # You can set class-specific default values, too
  class User < Lafcadio::DomainObject
    mock_values :fname => 'John', :lname => 'Doe',
                :email => 'john.doe / email.com',
                :birthday => Date.today - ( 66 * 365 )
  end
  u = User.default_mock
  u.fname # => 'John'