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

Posted by Chris Blackburn Mon, 23 Apr 2007 05:00:00 GMT

We needed a convenient way to store a series of values in a single field. A bitfield would not do because it would only allow a value of 1 or 0 for each field, and we wanted to be able to store at least 3 values for each field.

So I found Gabriel Gironda’s acts_as_bitfield plugin and made a few tweaks. ActsAsBytefield is the result. It allows storage of 256 values in each field, or 255 discrete values ranging from 0-255 (unsigned char or byte) for each value in a MySQL varchar(255) field.

NOTE: Gabriel’s site has been down for some time. My own repository has also been down but is now back up. Sorry for the inconvenience.

Values greater than 255, or less than 0 wrap around. For example, setting a bytefield column to -1 will actually set it to 255, and setting it to -2 will actually set it to 254, etc.

Installation

./script/plugin install acts_as_bytefield

OR
./script/plugin install https://svn.cbciweb.com/svn/plugins/acts_as_bytefield

Documentation (RDoc)

rake rdoc

Testing

The tests require rspec

rake test

Usage

  • Create a string column in your table - varchar(255)
  • Add this directive to your model:
 acts_as_bytefield :bytefield_column_name, :fields => [:field_name_one, :field_name_two]

You will then be able to use the model in the following manner, for example:

 class SomeModel < ActiveRecord::Base
   acts_as_bytefield :bfield, :fields => [:test, :production]
 end

 obj = SomeModel.new(:test => 1)

 obj.test          #=> 1
 obj.test?         #=> 1
 obj.production?   #=> 0

 obj.test = 0
 obj.production = 65
 obj.save

 obj.test?         #=> 0
 obj.production?   #=> 65

 # The field that's storing the value:
 obj.bfield        #=> "\000A"