Posted by Chris Blackburn Fri, 06 Oct 2006 05:00:00 GMT

I have found myself needing to sort a hash collection often, by a value within the hashes. The last instance where I needed this was to sort an aggregated result set of multiple union queries. So sorting with an order by clause would not work across the unions.

The solution is below. I pass a sortclause into the method that would look like this companyname asc or company_name desc.

def stats(sort_clause)

    # queries, etc.
    ...

    find_by_sql(sql).each do |acct|
      aid = acct.id.to_i
      results[aid] = {} unless results[aid]
      month = acct.monthname
      case (month)
        when 'last'
          results[aid][:spend_last] = acct.spend.to_f
        when 'this'
          results[aid][:spend_this] = acct.spend.to_f
        when 'total'
          results[aid][:company_name] = acct.company_name
          results[aid][:balance]      = acct.bal.to_f
          results[aid][:campaigns]    = acct.campaign_count.to_i
          results[aid][:keywords]     = acct.keyword_count.to_i
      end
    end

    sort_col, order = sort_clause.split(' ')
    logger.debug("sort_clause: #{sort_clause}")
    results = results.sort_by{ |item|
      item[1][sort_col.intern]
    }
    if (order =~ /desc/i)
      results.reverse!
    end
    results
end