SimpleSet 
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
Arrayor 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
the Hash notation.
- Although the
Hashnotation is less intuitive than theArraynotation, 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 to true, 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
with prefix: '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