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 SUM
s and MAX
es 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. ThoseLEFT 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, thenProduct.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.