GMA
GMA

Reputation: 6096

Rails: ignoring duplicates in an nested association

I have models User, Team, Document. There's a many-to-many relationship between Users and Teams, and a many-to-many relationship between Teams and Documents, using join tables called TeamMembership and TeamDocument respectively.

The relationships in my models look like this:

class Document < ActiveRecord::Base
  has_many :team_documents, dependent: :destroy
  has_many :teams, through: :team_documents
end

class User < ActiveRecord::Base
  has_many :team_memberships, dependent: :destroy, foreign_key: :member_id
  has_many :teams, through: :team_memberships
  has_many :documents, through: :teams
end

class TeamDocument < ActiveRecord::Base
  belongs_to :team
  belongs_to :document
end

class TeamMembership < ActiveRecord::Base
  belongs_to :team
  belongs_to :member, class_name: "User"
end

class Team < ActiveRecord::Base
  has_many :team_documents, dependent: :destroy
  has_many :documents, through: :team_documents
  has_many :team_memberships, dependent: :destroy
  has_many :members, through: :team_memberships
end

The idea is that users can belong to many teams, a document can be associated with many teams, and users will only have access to documents that "belong" to at least one team that the user is a member of.

Here's the question: I can use User#documents to retrieve a list of all the documents that this user is allowed to view. But this will return duplicates if a document is viewable by more than one team which the user is a member of. How can I avoid this?

I know I can remove the duplicates after the fact with @user.documents.uniq, but as I will never want to include the duplicates in any case, is there a way I can just make #documents not include duplicates every time?

Upvotes: 0

Views: 217

Answers (2)

kik
kik

Reputation: 7937

I don't have nested has_many :through like yours to test it, but I suspect using uniq option on your user association would help :

class User < ActiveRecord::Base
  has_many :documents, through: :teams, uniq: true
end

Upvotes: 1

BroiSatse
BroiSatse

Reputation: 44675

You can add a default_scope on Document model:

class Document < ActiveRecord::Base

default_scope group: { documents: :id }

Upvotes: 0

Related Questions