Skip to content

Instantly share code, notes, and snippets.

@jdwyah
Created May 3, 2010 14:37
Show Gist options
  • Save jdwyah/388151 to your computer and use it in GitHub Desktop.
Save jdwyah/388151 to your computer and use it in GitHub Desktop.
# our multi_group http://rails.lighthouseapp.com/projects/8994/tickets/120-patch-activerecord-calculations-only-accept-one-grouping-field#
# isn't updated for 2.2 yet. In the meantime, this poor man's version gives you the same results with some delimitter tom foolery.
#
# note: be careful to ensure that your group_by do not use the delimitter
# usage:
# self.multi_count(:id, :distinct => true, :group => [:symptom_id, :treatment_id])
# [[["138", "1018"], 187], [["138", "427"], 373], [["6", "1018"], 197], [["6", "427"], 393]]
class ActiveRecord::Base
def self.multi_count(field, opts = {})
fq_field_name = "#{table_name}.#{field}"
count_statement = opts[:distinct] ? "count (distinct #{fq_field_name})" : "count(#{fq_field_name})"
sql_opts = {}
select_cols = []
if opts[:group]
Array(opts[:group]).each do |group_term|
select_cols << group_term
end
group_str = (2..opts[:group].length+1).to_a.join(',')
end
if opts[:order]
order_opts = Array(opts[:order])
order_opts.each do |order_term|
select_cols << order_term
end
sql_opts[:order] = if opts[:group]
select_cols.length/2+2..select_cols.length+1
else
2..select_cols.length+1
end.to_a.join(',') + ' NULLS LAST'
end
sql_opts[:group] = (2..select_cols.length+1).to_a.join(',')
select_statement = "#{count_statement}, #{select_cols.join(',')}"
#build a sql query
sql = construct_finder_sql(sql_opts.merge(:select => select_statement))
connection.select_rows(sql).inject(ActiveSupport::OrderedHash.new) do |memo, row|
key = row.slice(1,opts[:group].length)
memo[key.length > 1 ? key : key.first] = row[0].to_i
memo
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment