Thomas Kuhlmann
Thomas Kuhlmann

Reputation: 325

Right association between three models

I am struggling to find the easiest solution for associating three models:

  1. User
  2. Organization
  3. Role

User and Organization is a HABTM association - one user can have multiple organizations and vice versa.

One user can also have multiple roles, but just one per organization.

Right now I have this in my model:

user.rb

class User < ActiveRecord::Base
  has_many :roles, through: :organizations
  has_and_belongs_to_many :organizations, :join_table => :organizations_users
end

organization.rb

class Organization < ActiveRecord::Base
  has_and_belongs_to_many :users, :join_table => :organizations_users
  has_many :roles
end

role.rb

class Role < ActiveRecord::Base
  has_many :users, through: :organizations
  belongs_to :organizations
end

Does that make sense?

Upvotes: 0

Views: 199

Answers (1)

Peter Alfvin
Peter Alfvin

Reputation: 29389

Here are my though:

  • Given that you're using the has_and_belongs_to_many and given Rails' defaults, your specification of the join_table is redundant
  • Your has_many :roles, through: :organizations will only work if you have both a role and a user field in the organizations tables, as Rails will expect to do a SQL select of that table looking for those fields.

Since you want users to have up to one one role per organization, then I would think the most straightforward thing would be to add a role field to the organizations_users model, as follows:

user.rb

class User < ActiveRecord::Base
  has_many :roles, through: :organizations_users
  has_many :organizations, :through => :organizations_users
  has_many :organizations_users
end

organization.rb

class Organization < ActiveRecord::Base
  has_many :users, :through => :organizations_users
  has_many :roles, :through => :organizations_users
  has_many :organizations_users
end

organization_user.rb

class OrganizationUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :organization
  belongs_to :role
end

role.rb

class Role < ActiveRecord::Base
end

The above assumes that you have some reason to want Role to continue to be an ActiveModel as opposed to just a string field in the organizations_users table.

Upvotes: 1

Related Questions