Skip to content

A sequel plugin that allows the use of integer columns to represent a big number of flags.

License

Notifications You must be signed in to change notification settings

blacklane/sequel-bit_fields

 
 

Repository files navigation

sequel-bit-fields

Build Status

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

The original gem resides at https://github.com/sdepold/sequel-bit_fields, but seems unmaintained. This fork contains general code clean up and support for Sequel 5.

Installation

Requirements:

  • Ruby 2.2 or newer

This library has not been published to RubyGems yet. You can fetch it by specifying the git repo. Specific versions can be retrieved by using git tags:

gem "sequel-bit_fields", git: "https://github.com/blacklane/sequel-bit_fields.git", tag: "v1.4.0"

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
  Bignum :status_bits, :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

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!

Development

After checking out the repo, run:

$ gem install bundler
$ bundle install

to install dependencies. Then, run bundle exec rake to run the tests.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in sequel-bit_fields.gemspec, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/blacklane/sequel-bit_fields.

License

Hereby released under MIT license.

Authors/Contributors

About

A sequel plugin that allows the use of integer columns to represent a big number of flags.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Ruby 100.0%