has_many and has_many through?

Hi all,

I’ve tried searching for the answer to this and I can’t seem to find an answer, so I wonder If I’m going about this the right way?

I basically have 3 models, user, organization and membership. A user can create an organisation, and can also belong to organizations through memberships, so organizations owned by other users.

I would like to be able to get all organizations that a user has access to, regardless if they own it, or they have access via a membership.

Do I need to merge owned_organizations and organizations? Or is there a better way to do this?

class User < ActiveRecord::Base
  has_many :memberships
  has_many :owned_organizations, class_name: "Organization", foreign_key: :user_id
  has_many :organizations,-> { uniq }, through: :memberships, source: :user
end

class Membership < ActiveRecord::Base
  belongs_to :user
  belongs_to :organisation
end

class Organization < ActiveRecord::Base
  has_many :memberships
  has_many :members,-> { uniq }, through: :memberships, class_name: 'User', source: :user
end

I know how to write this in SQL, I just need the correct way to do this in Rails

SELECT organizations.*
FROM organizations 
LEFT JOIN memberships ON organizations."id" = memberships.organization_id
WHERE organizations.user_id = '123' OR memberships.user_id = '123'

Any advice would be great! Thanks

What if the membership had a field that indicated the membership was for an owner or admin? Then to get all members you only need to look at one place: memberships.

If you want to keep the current data model, how about ensuring owners are also members?

Hi Derek,

Thanks for the reply. After tons of searching around, I tried both methods (amongst others) yesterday and decided to to use the second method. Would you say that the first method was preferable to the second? I would like to do things the best way possible.

I guess the reason I preferred the second method was to keep the foreign key in the organisation table to the owning user.

I wouldn’t say it’s a slam dunk that one is better than the other. It really depends on the types of questions you intend to ask of the data.

The advantage of storing metadata on the membership is that it is now the sole place to look for details about a membership. It also scales well to groups having multiple owners or there being different types of memberships (owner, admin, moderator…). The cost of that approach is that you burden membership with some data that turns out to be not applicable for the vast majority of records.

I think the approach you chose is a fine one.