Rails and midgets on unicycles

So let’s say you have a custom primary key for a table - a hash_id. It’s only ever populated externally, not by your rails application, so you figure you don’t really need to specify the custom primary key in the model, since it’s only ever read-only.

class Subscriber < ActiveRecord::Base
  belongs_to :midget
  set_primary_key :hash_id
end

Well, think again.

First of all, you’ll still need it if you ever add any has_one or has_many associations with this model.

But even if you only have a belongs_to association, there’s an insidious bug that’s waiting to bite you in the ass. If you ever select the records from this table through an association :include

@circuses = Circus.find(:all, :include => {:midget => :unicycles })

rails will cache the unicycles in the resulting hash by primary key. And if you don’t tell it that they have a custom primary key, they will all be cached to a single record, with id of 0.

So, you’ll end up with the whole troupe having to ride the same unicycle. The insidiousness lies in the fact that if you select the association directly, it works as expected, because no caching is involved:

Midget.find_by_name('Alberto').unicycles

will get you the expected results, so you might not realize anything is wrong until much later.

The moral of the story is, if you change one of the assumptions rails relies on, make sure to explicitly specify the change, because you don’t know what else in rails relies on that assumption.

rails exception monitoring

Exceptional and Hoptoad two exception monitoring services.

I’ve been using Rick Olson’s exception_logger plugin, quite useful and has the advantage of being self-hosted.

If your site is getting hammered by bots scanning for php file vulnerabilities, just add the following before your apache mongrel cluster rewrite rule:

RewriteCond %{REQUEST_URI} !\.php$
EZBoard Migrate

My first github release. Woo.