Bitmasker

Bitmasker allows you to store many boolean values as one integer field in the database.

Synopsis

  class User < ActiveRecord::Base
    has_bitmask_attributes :notifications do |config|
      config.attribute :send_weekly_newsletter,    0b0001
      config.attribute :send_monthly_newsletter,   0b0010, true
    end
  end

Code Climate Build Status

Examples

  # in migration
  t.integer :notifications_mask

  # in app/models/user.rb
  class User < ActiveRecord::Base
    has_bitmask_attributes :notifications do |config|
      config.attribute :send_weekly_newsletter,    0b0001
      config.attribute :send_monthly_newsletter,   0b0010, true
      config.attribute :send_daily_update,         0b0100
      config.accessible
      # config.field_name :notifications_mask # <- default functionality
    end
  end

This will define the following methods:

  • User#notifications -- returns a BitmaskAttributes object representing all values
  • User#send_weekly_newsletter? -- predicate
  • User#send_weekly_newsletter -- works just like the predicate, makes it easy to use actionview form helpers
  • User#send_weekly_newsletter=(value) -- just give it a boolean value (also takes "0" and "1" or "t" and "f" just like activerecord does for boolean fields)
  • User#send_monthly_newsletter?
  • User#send_monthly_newsletter
  • User#send_monthly_newsletter=(value)

the call to config.accessible calls attr_accessible :send_weekly_newsletter, :send_monthly_newsletter in your model.

Scopes

Bitmasker also sets up a few useful scopes:

  • User#with_notifications
  • User#without_notifications
  • User#with_any_notifications

Scopes Examples

# Users that want weekly newsletter
User.with_notifications(:send_weekly_newsletter)

# Users that want monthly AND weekly newsletters
User.with_notifications(:send_monthly_newsletter, :send_weekly_newsletter)

# Users that want monthly OR weekly newsletters
User.with_any_notifications(:send_monthly_newsletter, :send_weekly_newsletter)

View Example

  # in your view
  <% form_for @user do |f| %>
    Monthly Newsletter: <%= f.check_box :send_monthly_newsletter? %>
    or
    Monthly Newsletter
    Yes: <%= f.radio_button :send_monthly_newsletter, 'true' %>
    No: <%= f.radio_button :send_monthly_newsletter, 'false' %>
  <% end %>

Config Options

config.attribute(name, mask, default = false)

Sets up a binary attribute. Defines three functions: name, name?, and name=(true|false)

  • name a symbol, Bitmasker will define
  • mask example: 0b0000001, must be a power of 2
  • default set to true if you want the attribute to default to true

config.accessible if you are using attr_accessible in your model and you want to mass-assign your bitmask attributes, you will want to call this

config.field_name(name)

  • name name of the field name in the database where all this info is stored, should be an integer

Updating from has_bitmask_attributes

If you used the method_format feature from has_bitmask_attributes, you will need to change your configuration as method_format has been removed.

Before

  # in app/models/user.rb
  class User < ActiveRecord::Base
    has_bitmask_attributes :notifications do |config|
      config.attribute :weekly_newsletter,    0b0001
      config.attribute :monthly_newsletter,   0b0010, true
      config.method_format 'send_%s'
    end
  end

After

  # in app/models/user.rb
  class User < ActiveRecord::Base
    has_bitmask_attributes :notifications do |config|
      config.attribute :send_weekly_newsletter,    0b0001
      config.attribute :send_monthly_newsletter,   0b0010, true
    end
  end

Copyright (c) 2012 Amiel Martin, released under the MIT license