The moment I say ..
class Person extends CouchRecord[Person] {
//..
}
my domain model becomes tied to the persistence concerns.
When I started scouchdb, my very first thought was to make it non-invasive. The Scala objects must be pure and must remain pure and completely oblivious of the underlying persistence model. In the age of polyglot persistence there is every possibility that you may need to persist a domain model across multiple storage engines. I may be using a JPA backed relational store as the enterprise online database, which gets synchronized with some offline processing that comes from a CouchDB backend. I need the domain model persistence in both my Oracle and my CouchDB engines. The ActiveRecord pattern is difficult to scale to such requirements.
Here's what I implemented in scouchdb ..
// Scala abstraction : pure
case class ItemPrice(store: String, item: String, price: Number)
// specification of the db server running
val couch = Couch("127.0.0.1")
val item_db = Db("item_db")
// create the database
couch(item_db create)
// create the Scala object : a pure domain object
val s = ItemPrice("Best Buy", "mac book pro", 3000)
// create a document for the database with an id
val doc = Doc(item_db, "best_buy")
// add
couch(doc add s)
// query by id to get the id and revision of the document
val id_rev = couch(item_db by_id "best_buy")
// query by id to get back the object
// returns a tuple3 of (id, rev, object)
val sh = couch(item_db by_id("best_buy", classOf[ItemPrice]))
// got back the original object
sh._3.item should equal(s.item)
sh._3.price should equal(s.price)
It's a full cycle session of interaction with the CouchDB persistence engine without any intrusion into the domain abstraction. I am free to use ItemPrice domain abstraction for a relational storage as well.
CouchDB offers a model of persistence where the objects that we store should be close to the granularity of domain abstractions. I should be able to store the entire Aggregate Root of my model components directly as JSON. ActiveRecord model offers a lower level of abstraction and makes you think more in terms of persistence of the individual entities. The thought process is so relational that you ultimately end up with a relational model both in terms of persistence and domain. With CouchDB you need to think in terms of documents and views and NOT in terms of relations and tables. I blogged on this same subject some time back.
The philosophy that I adopted in scouchdb was to decouple the domain entities from the persistence layer. You hand over a pure Scala object to the driver, it will extract a JSON model from it and write it to CouchDB. I use sjson for this serialization. sjson works totally based on reflection and can transparently serialize and deserialize Scala objects that you hand over to it. From this point of view, the three aspects of managing domain abstractions, JSON serialization and persistence into CouchDB are totally orthogonal. I think this is difficult to get with an ActiveRecord based model.