Begin main content

Ruby on Rails, Postgres & other musings

Just had a rambling (as always) conversation with my friend Rusty that bears documenting. This is an outline which hopefully I will find time to exapand on.

It always starts off innocently

Bamboo ScaffoldingIt started, innocently enough, with a discussion about the way that Ruby on Rails does database persistance of Ruby objects. It's simple and clean, but one thing that had bothered us both was the way that ActiveRecord required a table to contain columns for every property of every subclass of a root class. It uses a type column to store what class a particlar serialized object is. This kinda sucks. It just doesn't seem right. While reading the ActiveRecord API docs, I noticed an offsite link about single table inhertance. This document starts with the statement "Relational databases don't support inheritance".

A good inheritance and a good relationship

Many relational databases do, however, support inhertiance - albeit in differing non-standard ways. Why, we thought, should an implementation be limited across all databases just because it wants to support MySQL and DB2. One nice solution that occurs to me is to use table inhertance in Postgresql. A child table inherits all the columns of it's parent but can also implement new columns of it's own. A table scan of the parent finds all the rows in the child, but introspection on the relevant tables will show the appropriate columns. It is also much more efficient if you have a lot of children with a lot of properties, since the parent table isn't clogged with all those empty columns. By better mapping reality (which is after all what OO is supposed to do), everything works better with implicit constraints on allowed properties etc.

As Rusty pointed out, it would make scaffolding pages much nicer too since the db table introspection would only show the relevant fields. Without investigating too hard, it would seem quite simple to implement this by sub-classing some parts of ActiveRecord, thus not breaking any existing code or db support. Careful note would probably need to be made of the Find method.

You don't want limitations in your scaffolding

Our thoughts then turned to the limitations of using the Ruby webserver WEBrick and the way that Apache rewrite rules are used to make the various controller url formats work. The thing that attracts me to WEBrick is one of the reasons I love AOLserver - that the webserver functionality is under the full control of an interpreted language which means you can literally do what you like. Want to implement a request processor right in the webserver? Go ahead! I contrasted this with the hoops of writing an advanced request processor in a traditional scripted web environment like PHP or Perl's mason or Template::Toolkit. mod_perl gives you much more ability to do what you want, but eventually you start asking the question "What is it that Apache is doing for me?" and the answer seems to be "not a whole lot". Which is particularly grating when it sometimes makes your life hard.

3 habits of highly effective servers

Sure performance could be an issue, but that leads to our next point of discussion - the division of labour between the web application server and the database server. We talked about implementing a Ruby/ActiveRecord object server that would connect to the database and dish up objects on request, sent over the network in some serialized form. I assume Ruby has an equivalent of Perl's Storable, I just don't know what it is.

And that about sums up our conversation until it was time to go and do some real work.

As I said, I hope to get time to write up something more formal and try to kick of some discussion. Of course it's highly likely these are not original thoughts. Someone probably already has a patent on them ;)

03:48 PM, 19 Feb 2005 by Mark Aufflick Permalink | Short Link

RE: Ruby on Rails, Postgres & other musings

We certainly aren't the first people to think about these things... :)

There seems to be serious discussion going on in the rails lists (see this thread) about ways to free ActiveRecord from the STI object relational mapping style, with an option for the much cleaner (to my mind at least) class table inheritance. Then again, perhaps I'm just more comfortable with that from the years I've spent working with OpenACS objects.

by russm . on 02/22/05

I should RTFML

ML = Mailing list.

Of course I am professionally engaged for OO perl/sql development, so my interest in Rails is somewhat academic - which is why I haven't really kept up with the discussions. Doesn't stop me working out how to fix the world though ;)

That thread has a lot of really good discussion, and any reasonable person can see that there are a number of ways to deal with the OO inhertitance/Relational algebra disconnect. Some are definately bad imo (like the current single table method), but saying which one is best is not clearly possible.

Maybe it's time to look at object databases ... but there is real power in relational algebra that I think we would lose.

A few bullet points:

  • I also, like russm, like the cascading table design (similar to OpenACS) - and it can be implemented without using database-specific inheritance features.
  • I think the idea that someone mentioned of forcing child tables to implement the same columns as the parent is *really* the wrong way to do it (a few joins never hurt anyone...)
  • I really like the post about chained saves - eg. in perl, any subclassed save method must call $self->SUPER::save(). A benefit of doing it explicitly is that you can make changes to the object before the parent save if you wish.
  • You may want to have some mechanism for reducing the number of messages you pass to the db server with these sort of methods - ie. in the db class you could store up sql commands until all the chained saves have taken place before making a db request.

by Mark Aufflick on 02/22/05

Add comment