4

I have the following models in my rails application

class User < ApplicationRecord 
end
class Group < ApplicationRecord 
end
class Role < ApplicationRecord 
end

Every Group has_many User with different Role. For example Group-1 have User - A with Role - Admin and Group-1 have User - B with Role - Member and Group-2 have User - A with Role - Member. Like wise each Group have multiple Users and every User have multiple Role.

Please guide What kind of association should I use?

Karthik Muthu
  • 135
  • 2
  • 13

3 Answers3

1

Assuming that a user belongs to only one group and has only one role.

Associations in model:

class Group < ApplicationRecord 
  has_many :users
end

class User < ApplicationRecord 
  belongs_to :group
  belongs_to :role
end

class Role < ApplicationRecord 
  has_many :users
end

Columns that should be added to the models:

user:

group_id:integer:index
role_id:integer:index

EDIT 1:

Updating the associations based on the comments.

class Group < ApplicationRecord 
  has_many :users
  has_many :roles
end

class User < ApplicationRecord 
  belongs_to :group
end

class Role < ApplicationRecord 
  belongs_to :group
end

Columns that should be added to the models:

user:

group_id:integer:index

role:

group_id:integer:index

To find the group and roles of a user you can use:

user = User.last
user.group # Returns group of the user
user.group.roles # Returns roles of the user
webster
  • 3,902
  • 6
  • 37
  • 59
  • Thanks for your effort but I have made some mistake in my question. The Group has many User and User has many Roles based on the Groups. Please let me know if I were not clear. – Karthik Muthu Jan 29 '18 at 09:08
1

Incase, If user belongs to many groups and role belongs to many users, I hope the following associations works fine...

class Group < ApplicationRecord 
  has_many :group_users
  has_many :users, through: :group_users

  has_many :group_user_roles
  has_many :roles, through: :group_user_roles
end

class User < ApplicationRecord 
  has_many :group_users
  has_many :groups, through: :group_users

  has_many :group_user_roles
  has_many :roles, through: :group_user_roles
end

class GroupUser < ApplicationRecord
    belongs_to :group
    belongs_to :user
end

class Role < ApplicationRecord
end

class GroupUserRole < ApplicationRecord
  belongs_to :user
  belongs_to :group
  belongs_to :role
end

You need to create one more table(GroupUserRole) to associate multiple users with multiple groups for multiple roles.

Narasimha Reddy - Geeker
  • 3,510
  • 2
  • 18
  • 23
  • So here do I need to create two table as GroupUser and GroupUserRole? – Karthik Muthu Jan 29 '18 at 12:38
  • if a user can be member of any number of groups - and having different roles for each groups - then yes you should create two different tables to create has_many through association. – Narasimha Reddy - Geeker Jan 29 '18 at 12:45
  • I am getting confuse what is the use of creating a model GroupUser table?. – Karthik Muthu Jan 30 '18 at 10:40
  • if user can involve in as many groups he wants, and a group can have as many user it needs. it this you required both side has_many association which is possible only with has_many through: only. read more about it here http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association – Narasimha Reddy - Geeker Jan 30 '18 at 10:43
1

You can also create a Tri-related table having a record for every membership of a user and saving that user's role as well.

class Trirelation
  belongs_to :group
  belongs_to :user
  belongs_to :role
end

class User
  has_many :trirelations
  has_many :groups, through: :trirelations
end

class Group
  has_many :trirelations
  has_many :users, through: :trirelations
end

class Role
  has_many :trirelations
end

In case you need to query whether a given user is an admin of a group,

@role = Trirelation.find_by(user_id: 1, group_id: 21).role.name
Naman Wadhwa
  • 150
  • 1
  • 8
  • It is working perfectly but can you pls make sure is it correct way to query? Thanks in advance. – Karthik Muthu Jan 30 '18 at 11:14
  • You can also use `User.find(1).trirelations.find_by(group_id: 21).role.name` However, you can also implement the roles by adding it as an enum column of Trirelation model instead of creating it as a different model altogether. – Naman Wadhwa Jan 30 '18 at 11:30