Giter Site home page Giter Site logo

bitmask_attributes's Introduction

BitmaskAttributes

Transparent manipulation of bitmask attributes for ActiveRecord, based on the bitmask-attribute gem, which has been dormant since 2009. This updated gem work with Rails 3 and up (including Rails 3.1).

Installation

The best way to install is with RubyGems:

$ [sudo] gem install bitmask_attributes

Or better still, just add it to your Gemfile:

gem 'bitmask_attributes'

Example

Simply declare an existing integer column as a bitmask with its possible values.

class User < ActiveRecord::Base
  bitmask :roles, :as => [:writer, :publisher, :editor, :proofreader]
end

You can then modify the column using the declared values without resorting to manual bitmasks.

user = User.create(:name => "Bruce", :roles => [:publisher, :editor])
user.roles
# => [:publisher, :editor]
user.roles << :writer
user.roles
# => [:publisher, :editor, :writer]

It’s easy to find out if a record has a given value:

user.roles?(:editor)
# => true

You can check for multiple values (uses an ‘and` boolean):

user.roles?(:editor, :publisher)
# => true
user.roles?(:editor, :proofreader)
# => false

Or, just check if any values are present:

user.roles?
# => true

You can get the list of values for any given attribute:

User.values_for_roles
# => [:writer, :publisher, :editor, :proofreader]

Named Scopes

A couple useful named scopes are also generated when you use ‘bitmask`:

User.with_roles
# => (all users with roles)
User.with_roles(:editor)
# => (all editors)
User.with_roles(:editor, :writer)
# => (all users who are BOTH editors and writers)
User.with_any_roles(:editor, :writer)
# => (all users who are editors OR writers)
User.with_exact_roles(:writer)
# => (all users who are ONLY writers)
User.with_exact_roles(:writer, :editor)
# => (all users who are BOTH editors and writers and nothing else)

Find records without any bitmask set:

User.without_roles
# => (all users without a role)
User.no_roles
# => (all users without a role)

Find records without specific attributes:

User.without_roles(:editor)
# => (all users who are not editors)

User.without_roles(:writer, :editor)
# => (all users who are NEITHER writers nor editors)

Note that “without_” supports one or more attribute arguments, and the “no_” method does not support arguments. And “with_exact_” without arguments is alias for “no_”

Adding Methods

You can add your own methods to the bitmasked attributes (similar to named scopes):

bitmask :other_attribute, :as => [:value1, :value2] do
  def worked?
    true
  end
end

user = User.first
user.other_attribute.worked?
# => true

Handling null values

By default, bitmasks support the potential for the underlying integer value to be null. However, if you have created a field that is guaranteed never to be null, you can simplify the SQL query conditions by declaring “:null => false” in the definition:

bitmask :never_null_attributes,:as => [:value1, :value2], :null => false

Allowing for a “zero” value

It is common to use web forms to set bitmask bits using checkboxes. If the various bits each are represented by a checkbox and the user unchecks them all, the resulting “params” posted to the controller will be missing. When this happens, a controller will need to ensure that a “params” hash entry has an empty array or a call to “update_attributes” will not change the attribute. For example:

In model...
    class SomeModel < ActiveRecord::Base
        bitmask :some_attribute, :as => [:value1, :value2]
    end

In view...
    <input type="checkbox" name="some_model[some_attribute][]" value="value1"/>
    <input type="checkbox" name="some_model[some_attribute][]" value="value2"/>

In controller...
    def update
        @some_model = SomeModel.find(params[:id])
        params[:some_model][:some_attribute] ||= []
        @some_model.update_attributes(params)
    end

As an alternative, you may provide a special symbol representing “zero”:

In model...
    class SomeModel < ActiveRecord::Base
        bitmask :some_attribute, :as => [:value1, :value2], :zero_value => :none
    end

In view...
    <input type="checkbox" name="some_model[some_attribute][]" value="value1"/>
    <input type="checkbox" name="some_model[some_attribute][]" value="value2"/>
    <input type="hidden"   name="some_model[some_attribute][]" value="none"/>

In controller...
    def update
        @some_model = SomeModel.find(params[:id])
        @some_model.update_attributes(params)
    end

This technique can be particularly useful for both forms and web services where setting the attribute in question may be optionally included or not such that the controller setting of an empty array in the first example would not be correct.

Warning: Modifying possible values

IMPORTANT: Once you have data using a bitmask, don’t change the order of the values, remove any values, or insert any new values in the ‘:as` array anywhere except at the end. You won’t like the results.

Contributing

  1. Fork it.

  2. Create a branch (‘git checkout -b new-feature`)

  3. Make your changes

  4. Run the tests (‘bundle install` then `bundle exec rake`)

  5. Commit your changes (‘git commit -am “Created new feature”`)

  6. Push to the branch (‘git push origin new-feature`)

  7. Create a pull request from your branch.

  8. Promote it. Get others to drop in and +1 it.

Credits

Thanks to Bruce Williams and the following contributors of the bitmask-attribute plugin:

Copyright © 2007-2009 Bruce Williams & 2011 Joel Moss. See LICENSE for details.

bitmask_attributes's People

Contributors

joelmoss avatar spemmons avatar bjallen avatar teeparham avatar helsus avatar mjonuschat avatar psharpnumerex avatar ahamid avatar adrian-gomez avatar aduffeck avatar braddunbar avatar chak avatar somebody32 avatar mat813 avatar mattsjohnston avatar sborrazas avatar

Stargazers

 avatar

Watchers

 avatar James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.