This is a plugin for Sequel which allows the creation of bitfields. With bitfields you can define flags / booleans / bits /whatsoever for you model.
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 ]
endAnd 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 # => 3And 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')).allMyModel.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."
} ]
=endMyModel.bit_field_indexes_for( :status_bits )
# => { :started => 1, :finished => 2, :reviewed => 4 }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 }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."
} ] }
}
=endPlease 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) # trueAs 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
endThis 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? # trueVersion 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."
}]
endYou 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]
endLet'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? # falseIf 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
endIf 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# gem approach
gem install sequel-bit_fields
# bundler approach
# add this to your Gemfile
gem 'sequel-bit_fields'
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.
- BlackLane GmbH
- Sascha Depold (Twitter | Github)
- jethroo
- Markus 'iblue' Fenske
- Jon Pitts
