n Booleans = 1 Integer, saves columns and migrations.
Ruby
Pull request Compare This branch is 1 commit ahead, 84 commits behind grosser:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
benchmark
lib
spec
README.markdown
Rakefile
VERSION
bitfields.gemspec

README.markdown

Save migrations and columns by storing multiple booleans in a single integer.
e.g. true-false-false = 1, false-true-false = 2, true-false-true = 5 (1,2,4,8,..)

class User < ActiveRecord::Base
  include Bitfields
  bitfield :my_bits, 1 => :seller, 2 => :insane, 4 => :stupid
end

user = User.new(:seller => true, :insane => true)
user.seller == true
user.stupid? == false
user.my_bits == 3
  • records changes user.chamges == {:seller => [false, true]}
  • adds scopes User.seller.stupid.first (deactivate with bitfield ..., :scopes => false)
  • builds sql User.bitfield_sql(:insane => true, :stupid => false) == '(users.my_bits & 3) = 1'
  • builds index-using sql with bitfield ... ,:query_mode => :in_list and User.bitfield_sql(:insane => true, :stupid => false) == 'users.my_bits IN (2, 3)' (2 and 1+2), often slower than :bit_operator sql especially for high number of bits
  • builds update sql User.set_bitfield_sql(:insane => true, :stupid => false) == 'my_bits = (my_bits | 6) - 4'
  • faster sql than any other bitfield lib through combination of multiple bits into a single sql statement
  • gives access to bits User.bitfields[:my_bits][:stupid] == 4

Install

As Gem: sudo gem install bitfields
Or as Rails plugin: rails plugin install git://github.com/grosser/bitfields.git

Migration

ALWAYS set a default, bitfield queries will not work for NULL t.integer :my_bits, :default => 0, :null => false OR add_column :users, :my_bits, :integer, :default => 0, :null => false

Examples

Update all users User.seller.not_stupid.update_all(User.set_bitfield_sql(:seller => true, :insane => true))

Delete the shop when a user is no longer a seller before_save :delete_shop, :if => lambda{|u| u.changes['seller'] == [true, false]}

TIPS

  • Never do: "#{bitfield_sql(...)} AND #{bitfield_sql(...)}", merge both into one hash
  • bit_operator is faster in most cases, use :query_mode => :in_list sparingly
  • standard mysql integer is 4 byte -> 32 bitfields

performance

TODO

  • convenient named scope User.with_bitfields(:xxx=>true, :yy=>false)

Author

Michael Grosser
grosser.michael@gmail.com
Hereby placed under public domain, do what you want, just do not hold me accountable...