Class inheritance

9 views
Skip to first unread message

Peter Bengtson

unread,
Oct 31, 2009, 8:53:15 AM10/31/09
to CouchRest
I need to implement a Ruby persistence layer on top of CouchDB. The
infrastructure provided by CouchRest seems to be excellent. My
application, however, has some special, though not very unusual,
requirements. Thus I'd like to pick the brains of the CouchRest
community as to the feasibility of extending CouchRest. Maybe what I'm
looking for has already been implemented elsewhere, who knows.

It needs to support class inheritance, and it must be possible to pull
an object from the DB without knowing its class in advance. The views
must also support mapping over instances belonging to subclasses.

The following idiom is very natural to anyone coming from
ActiveRecord:

foo = Foo.get(some_id)

However, CouchRest already stores the class of the document as the
value of the property "couchrest-class". This means that the above
Ruby statement contains one rather substantial redundancy: "Foo.get"
will construct a Foo object and nothing else. (However, CouchRest
doesn't check that the "couchrest-class" property matches the class
explicitly given in the object itself: in fact, it is quite possible
to construct a Bar instance instead without anything untoward
happening.)

What I need is a way of pulling an object from CouchDB which invokes
the constructor of the class given by the "couchrest-class" object,
rather like the following:

foo = ExtendedDocument.get(some_id)

However, this always returns an ExtendedDocument instance because
CouchRest::Mixins::DocumentQueries.get uses "new" (on line 58 of
document_queries.rb) to construct the in-memory instance.

If instead of new, line 58 read:

doc['couchrest-class'].constantize.send(:new, doc)

Then this would always return an object of the class specified by the
object *itself*, rather than of an explicitly supplied class directly
stated in the loading code as in ActiveRecord.

Would this be a change compatible with the current code base, or would
it be better to add a new class, such as "General" to do this?

I'm also wondering whether views could be easily modified to take
subclasses into account during mapping operations. For instance,
something like the following:

class Human < SomeBasicCouchDBClass; end
class Woman < Human; end
class Man < Human; end

Assume we create 3 Women and 2 Men, but no Humans. As the code stands
today, evaluating "Human.all.length" returns 0, since the view code
checks for an exact class match. If would be fairly easy to add a new
method to check for subclass matches, e.g. "all_deep" or similar which
would invoke a new view created for the purpose.

Any thoughts on best CouchRest practices?

Matt Aimonetti

unread,
Nov 5, 2009, 2:16:10 PM11/5/09
to couc...@googlegroups.com
That sounds good to me, I'm just wondering if there would be any performance hit to retrieve the constant and dispatch the initialization using #send.

- Matt
Reply all
Reply to author
Forward
0 new messages