sequel-bit-fields
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
Usage
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 ]
end
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
MyModel.finished(true).all
# let's find all unfinished instances
MyModel.finished(false).all
# let's find all the started and the finished instances
MyModel.started.finished.all
# if you need to overwrite the table name:
MyModel.where(MyModel.finished_sql(true, :table => '_my_tmp_model')).all
Get the declared columns
MyModel.bit_fields
=begin
{ :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."
} ] }
=end
MyModel.bit_fields( :status_bits )
=begin
[ {
:name => :started,
:description => "Description for 'started' not available."
}, {
:name => :finished,
:description => "Description for 'finished' not available."
}, {
:name => :reviewed,
:description => "Description for 'reviewed' not available."
} ]
=end
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
Sequel::Plugins::BitFields.bit_fields_for_models
=begin
{ '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."
} ] }
}
=end
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 ]
end
model = DirtyModel.create
model.bit_changed?(:finished) # false
model.finished = !model.finished
model.bit_changed?(:finished) # true
Scoping
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
end
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
Options
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."
}]
end
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]
end
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
add_column :status_bits, :Bignum, :null => false, :default => 0
end
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
end
end
end
Installation
# 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!
License
Hereby released under MIT license.
Authors/Contributors
- BlackLane GmbH
- Sascha Depold (Twitter | Github)
- jethroo
- Markus 'iblue' Fenske
- Jon Pitts