I'm a bit concerned about that too, so I've been sticking every piece of
validation I can into the database layer as opposed to in ruby code.
To be fair, having referential integrity in the ruby side shouldn't slow
things down, although it does make your database more fragile; references
arent loaded unless you ask them to be. A regular index on a join column
would be just as fast as a foreign key index, possibly faster on
However, you lose a lot of the *integrity* part of that if you leave this
up to rails. The main reasons referential integrity and constraints exist
are to to defend your data layer from bugs in the application layer. Stuff
like preventing a customer that has an order pending from being deleted, or
making sure an invoice can not be saved with a total of less than one cent.
Sure, you can code all of this into the ruby side, but then if you're
working on something by hand (in script/console or doing raw SQL queries)
you can still mess things up pretty badly.
The way rails handles transactions does bug me a bit though. If I need to
do a complex sequence of changes in a database as one transaction, I will
probably do it as a stored procedure on the database side and just call out
to that. I'm already doing this for "side effects" in one of my
applications.... in several places, but here's one example: I have a table
for hostnames, and a table for domain names. Hosts belong to Domains. Hosts
have a "full_name" column that combines their name with the name of their
parent (eg; host "foo" in domain "bar.com" gets the full_name
"foo.bar.com"). Instead of coding this as a before_save action on the rails
side, I made it a "BEFORE INSERT OR UPDATE" trigger on the postgresql side.
I think leaving as much of the data massaging/validating up to the
database as possible is not just a bit faster, but also probably a lot
Rails needs to provide these features because not all database engines
support them (eg; SQLite)... but if something to do with the data model can
be done in the database, I think it should. That *doesn't* mean that you
should do something in the database layer JUST because you can. The database
should only been concerned with handling the data. I've seen stored
procedures that actually do things like send email, and that, well, scares