A sequel plugin that allows the use of integer columns to represent a big number of flags.
Latest commit 84f5463 Mar 16, 2015 @sdepold Bump to version: v1.3.0



This is a plugin for Sequel which allows the creation of bitfields. With bitfields you can define flags / booleans / bits /whatsoever for you model.

Build status

Build Status


Let's define a model:

class MyModel < Sequel::Model
  # generic:
  plugin :bit_fields, :the_respective_column, [ :the, :different, :flags, :or, :bits ]

  # real world:
  plugin :bit_fields, :status_bits, [ :started, :finished, :reviewed ]

And now we can play around with an instance of it:

model = MyModel.create

model.started?        # => false
model.started = true
model.started?        # => true
model.status_bits     # => 1

model.finished?       # => false
model.finished = true
model.finished?       # => true
model.status_bits     # => 3

And we might want to find instances:

# let's find all the finished instances

# let's find all unfinished instances

# let's find all the started and the finished instances

# if you need to overwrite the table name:
MyModel.where(MyModel.finished_sql(true, :table => '_my_tmp_model')).all

Get the declared columns

{ :status_bits => [ {
  :name => :started,
  :description => "Description for 'started' not available."
}, {
  :name        => :finished,
  :description => "Description for 'finished' not available."
}, {
  :name        => :reviewed,
  :description => "Description for 'reviewed' not available."
} ] }

MyModel.bit_fields( :status_bits )
[ {
  :name => :started,
  :description => "Description for 'started' not available."
}, {
  :name        => :finished,
  :description => "Description for 'finished' not available."
}, {
  :name        => :reviewed,
  :description => "Description for 'reviewed' not available."
} ]

Get the indexes of the columns

MyModel.bit_field_indexes_for( :status_bits )
# => { :started => 1, :finished => 2, :reviewed => 4 }

Get the values of the declared columns:

model = MyModel.new
model.finished => true
model.bit_field_values_for( :status_bits )
# => {:started => false, :finished => true, :reviewed => false}

# or with a specific value only:
model.bit_field_values_for( :status_bits, true )
# => { :finished => true }

Get all bit fields of all models, which use the plugin

{ 'MyModel' => { :status_bits => [ {
    :name => :started,
    :description => "Description for 'started' not available."
  }, {
    :name        => :finished,
    :description => "Description for 'finished' not available."
  }, {
    :name        => :reviewed,
    :description => "Description for 'reviewed' not available."
  } ] }

Check if a bit has been changed

Please note that you will need to add the dirty plugin to your model, too.

class DirtyModel < Sequel::Model
  plugin :dirty
  plugin :bit_fields, :status_bits, [ :started, :finished, :reviewed ]

model = DirtyModel.create
model.bit_changed?(:finished) # false
model.finished = !model.finished
model.bit_changed?(:finished) # true


As you might find yourself in the situation, where you would like to define multiple bit fields with the same name, you will notice, that the straightforward attempt will overwrite the methods of the previously defined bit fields. In order to fix this, you can pass a scope options:

class User < Sequel::Model
  plugin :bit_fields, :website_permission_bits,     [ :admin ], :scope => :website
  plugin :bit_fields, :iphone_app_permission_bits,  [ :admin ], :scope => :iphone
  plugin :bit_fields, :android_app_permission_bits, [ :admin ], :scope => :android

This will change the name of the bit fields:

User.new.website_admin?                         # false
User.new.iphone_admin?                          # false
User.new(:android_admin => true).android_admin? # true


Version 1.0.0 introduced the possibility to describe fields. Here is how it looks like:

class User < Sequel::Model
  plugin :bit_fields, :some_bits, [{
    :name        => :checked,
    :description => "This bit fields states that the model has been checked by someone."

Assigning symbols to columns and multiple bit_field assignment

You may want to set a bit_field via the column name and pass it a symbol. Or you may find it useful to turn on multiple bit_fields at the same time.

Values that are not passed will be set to false. This behavior is useful if you want to set specific bit_fields and not have to set every bit_field.

Given the model:

class MyModel < Sequel::Model
  plugin :bit_fields, :roles, [:author,:contributor,:reader]

Let's create a user that is a reader and contributor:

user = MyModel.new
user.roles = [:contributor,:reader]

user.contributor? # true
user.reader?      # true
user.author?      # false

user.roles = :author

user.author?      # true
user.reader?      # false
user.contributor? # false

The table

If you are creating a new model from scratch:

DB = Sequel.sqlite

DB.create_table(:my_models) do
  primary_key :id, :auto_increment => true

  # let's use Bignum as it has more space :)
  # set the default to 0 and disallow null values
  Bignum :status_bits, :null => false, :default => 0

The migration

If you want to extend an existing model:

Sequel.migration do
  change do
    alter_table :users do
      add_column :permission_bits, Bignum, :default => 0, :null => false


# gem approach
gem install sequel-bit_fields

# bundler approach
# add this to your Gemfile
gem 'sequel-bit_fields'

Side notes

You should always declare the column with a default value of 0. Also NULL should be disabled / not allowed. Otherwise the plugin will fail hard!


Hereby released under MIT license.