A Rails plugin which brings easy-to-use set-like functionality to ActiveRecord models.
This is based on SimpleEnum.
Installation
Add this line to your application's Gemfile:
gem 'simple_set'
And then execute:
$ bundle
Or install it yourself as:
$ gem install simple_set
Usage
Add this to a model:
class User < ActiveRecord::Base
as_set :roles, [:accounting, :management]
end
Then create the required roles_cd
column using migrations:
class AddRolesToUsers < ActiveRecord::Migration
def change
add_column :users, :roles_cd, :integer
end
end
Now, it's possible to manage roles with maximum ease:
bob = User.new
bob.roles = [:accounting]
bob.accounting? #=> true
bob.management? #=> false
bob.roles #=> [:accounting]
bob.roles_cd #=> 1
Gotchas
-
Acceptable values can be provided as an
Array
or as aHash
, the following lines are equivalent:as_set :spoken_languages, [:english, :french, :german, :japanese] as_set :spoken_languages, {english: 1, french: 2, german: 4, japanese: 8}
Reordering the array will change each element's value which is likely unwanted. Either only append new elements to the
Array
notation or use theHash
notation. -
Although the
Hash
notation is less intuitive than theArray
notation, it allows some neat tricks:class Pixel as_set :rgb, { red: 1, green: 2, blue: 4, yellow: 3, magenta: 5, cyan: 6, white: 7, } end x = Pixel.create(rgb: [:red, :blue]) x.red? #=> true x.green? #=> false x.blue? #=> true x.yellow? #=> false x.magenta? #=> true x.cyan? #=> false x.white? #=> false x.green = true x.white? #=> true
-
If the shortcut methods (like
<symbol>?
,<symbol>=
orKlass.<symbol>
) conflict with something in your class, an error will be raised. You can avoid this situation by defining a prefix:class Lp < ActiveRecord::Base # Without :prefix, the :new media condition bellow would generate a # Lp::new method that returns 1 and overrides the constructor. This is # likely unwanted and a :prefix must be set to avoid this situation: as_set :media_conditions, [:new, :sealed, :very_good, :good, :fair, :poor], prefix: true end Lp.media_condition_new #=> 1 Lp.new #=> #<Lp:0x00000803c22b98>
When
:prefix
is set totrue
, shortcut methods are prefixed by the singularized name of the attribute.The
:prefix
option not only takes a boolean value as an argument, but instead can also be supplied a custom prefix (i.e. any string or symbol), so withprefix: 'foo'
all shortcut methods would look like:foo_<symbol>...
-
Sometimes it might be useful to disable the generation of the shortcut methods (
<symbol>?
,<symbol>=
andKlass.<symbol>
), to do so just add the optionslim: true
:class User as_set :spoken_languages, [:english, :french, :german, :japanese], slim: true end bob = User.create(spoken_languages: [:english, :french] bob.spoken_languages #=> [:english, :french] bob.french? #=> throws NoMethodError: undefined method `french?' bob.french = false #=> throws NoMethodError: undefined method `french=' User.french #=> throws NoMethodError: undefined method `french'
-
Easy Rails integration:
Given a
User
is declared as:class User < ActiveRecord::Base as_set :roles, [:management, :accounting, :human_resources] end
Adjust strong parameters to allow roles assignment:
params.require(:user).permit(:roles => [])
And then render a collection of checkboxes:
= form_for @user do |f| = f.collection_check_boxes(:roles, User.roles, :to_sym, :to_sym) do |b| = b.check_box = b.label do = t("application.roles.#{b.text}")
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request