Let’s get committed

Right, I know I said I’d do this a long time ago, but I just got round to checking up on some of my Rails patches with the hopes of persuading one or two of you that they might be worth supporting and getting committed to the core. This post concerns a couple of patches that, a couple of days ago, I updated to make sure they will apply against the current head version of Rails.

The first is one which totally saved my life a while ago while building DesalData. I had to allow users to graph data of water plants going back decades, in real time in their browsers. On a cheap shared server with one database. I figured that the best way to do this was to ask MySQL for all the required SUMs and MAXes in one query, but Rails only lets you make one calculation per query using ActiveRecord::Base.calculate. So, I set about patching it to allow multiple calculations at once, and ended up with client code that looked like this:

Person.calculate(:how_many => [:count, '*'],
    :total_age => [:sum, :age])
#=> {:how_many => 12, :total_age => 387}

Person.calculate({:how_many => [:count, '*'],
    :total_age => [:sum, :age]},
    :conditions => ['age < ?', 30])
#=> {:how_many => 7, :total_age => 94}

(These taken from my Rails ticket, not the app itself!) Needless to say, what with complaints from all sides about Rails performing badly and not being ‘enterprise-ready’ (whatever that means), I figured this would be a useful addition. So far a couple of people seem to agree with me, but I need a couple more votes of support to verify the patch and get it committed. I’ve tested it with MySQL 5 and SQLite 3, so if you feel like testing it yourself with some other DB and making sure it works, head over to the ticket and show me some love.

A related (and overlapping) ticket involves the addition of a :distinct_records option to ActiveRecord::Base.find. (See the ticket.) I’ll quote from the ticket rather than trying to explain it all again:

Let’s say you want to find the sum of the prices of a bunch of products in your database, and the criteria used for selecting products involve using :include to bring in associated tables. Those LEFT OUTER JOIN statements may result in the base record (Product) being duplicated for every association found. e.g. if product number 1 has three comments associated with it, then Product.sum(:price, :include => :comments, :conditions => ...) will include product number 1 in three rows of the SQL result set. I only want its price added to the sum once, but I can’t use the :distinct option because the prices I’m adding up aren’t necessarily unique.

This really caused me a huge headache with filtering data correctly, and these two patches combined are the result of days and days of banging my head against the desk trying to get my app to work properly. I’d be thrilled if you’d go and support this patch.

That is all, for now. I’d also be chuffed if the nested has_many :through patch gets committed, so go vote for it too.

If you’ve enjoyed this article, you might enjoy my recently published book JavaScript Testing Recipes. It’s full of simple techniques for writing modular, maintainable JavaScript apps in the browser and on the server.