views:

37

answers:

1

I have a need to design a system to track users memberships to groups with varying roles (currently three).

class Group < ActiveRecord::Base
 has_many :memberships
 has_many :users, :through => :memberships 
end

class Role < ActiveRecord::Base
 has_many :memberships
 has_many :users, :through => :memberships
end

class Membership < ActiveRecord::Base
 belongs_to :user
 belongs_to :role
 belongs_to :group
end

class User < ActiveRecord::Base
 has_many :memberships
 has_many :groups, :through => :memberships
end

Ideally what I want is to simply set

@group.users << @user 

and have the membership have the correct role. I can use :conditions to select data that has been manually inserted as such :

:conditions => ["memberships.role_id= ? ", Grouprole.find_by_name('user')]

But when creating the membership to the group the role_id is not being set.

Is there a way to do this as at present I have a somewhat repetitive piece of code for each user role in my Group model.

UPDATED

It should be noted what id ideally like to achieved is something similar to

@group.admins << @user
@group.moderators << @user

This would create the membership to the group and set the membership role (role_id ) appropriately.

A: 

You can always add triggers in your Membership model to handle assignments like this as they are created. For instance:

class Membership < ActiveRecord::Base
  before_save :assign_default_role

protected
  def assign_default_role
    self.role = Role.find_by_name('user')
  end
end

This is just an adaptation of your example.

tadman
Unfortunately given the variation in roles this wouldn't work. Ive updated my initial post to include some addition requirements .
David Lyod
You're going to have to add scoped conditions to those relationships so that the creation can inherit from the scope. Using dynamic labels for your roles, though, will cause trouble if they have to constantly be resolved. Defining fixed "role codes" would simplify this considerably. Using hash-style scopes is better for this: { :role_id => Role::USER_ROLE_CODE }
tadman