Adds group and membership functionality to Rails models.
The following ORMs are supported: Mongoid 3.1 & 4.0, ActiveRecord 3.2 & 4.x
The following Rubies are supported:
- MRI Ruby 1.9.3, 2.0.x, 2.1.x
- JRuby (1.9 mode)
Add this line to your application's Gemfile:
gem 'groupify'
And then execute:
$ bundle
Or install it yourself as:
$ gem install groupify
Add a migration similar to the following:
class CreateGroups < ActiveRecord::Migration
def change
create_table :groups do |t|
t.string :type # Only needed if using single table inheritence
end
create_table :group_memberships do |t|
t.string :member_type # Needed to make polymorphic members work
t.integer :member_id # The member that belongs to this group
t.integer :group_id # The group to which the member belongs
t.string :group_name # Links a member to a named group (if using named groups)
end
add_index :group_memberships, [:member_id, :member_type]
add_index :group_memberships, :group_id
add_index :group_memberships, :group_name
end
end
In your group model:
class Group < ActiveRecord::Base
acts_as_group :members => [:users, :assignments], :default_members => :users
end
In your member models (i.e. User
):
class User < ActiveRecord::Base
acts_as_group_member
acts_as_named_group_member
end
class Assignment < ActiveRecord::Base
acts_as_group_member
end
You will also need to define a GroupMembership
model to join groups to members:
class GroupMembership < ActiveRecord::Base
acts_as_group_membership
end
In your group model:
class Group
include Mongoid::Document
acts_as_group :members => [:users], :default_members => :users
end
In your member models (i.e. User
):
class User
include Mongoid::Document
acts_as_group_member
acts_as_named_group_member
end
Create groups and add members:
group = Group.new
user = User.new
user.groups << group
# or
group.add user
user.in_group?(group)
# => true
# Add multiple members at once
group.add(user, widget, task)
Add to named groups:
user.named_groups << :admin
user.in_named_group?(:admin)
# => true
Check if two members share any of the same groups:
user1.shares_any_group?(user2)
user2.shares_any_named_group?(user1)
Query for groups & members:
User.in_group(group) # Find all users in this group
User.in_named_group(:admin) # Find all users in this named group
Group.with_member(user) # Find all groups with this user
User.shares_any_group(user) # Find all users that share any groups with this user
User.shares_any_named_group(user) # Find all users that share any named groups with this user
Merge one group into another:
# Moves the members of source into destination, and destroys source
destination_group.merge!(source_group)
Check the specs for more details.
Groupify was originally created to help implement user authorization, although it can be used generically for much more than that. Here is how to do it.
class Ability
include CanCan::Ability
def initialize(user)
…
# Implements group authorization
# Users can only manage assignment which belong to the same group
can [:manage], Assignment, Assignment.shares_any_group(user) do |assignment|
assignment.shares_any_group?(user)
end
end
end
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request