Rails 复杂的模型关联,用户和团队之间的共享文档

Rails Complex Model Association, Shared Document Between Users and Teams

我脑子里有一个复杂的模型关联,想知道如何实现它。这就是我想要完成的。

我对必须设置的关联有点困惑。这是我到目前为止的代码,其中没有包含团队方面:

class User < ApplicationRecord
  has_many :participations
  has_many :documents, through: :participations
end

class Document < ApplicationRecord
  has_many :participations
  has_many :users, through: :participations
end

class Participation < ApplicationRecord
  belongs_to :user
  belongs_to :document
  enum role: [ :admin, :editor, :viewer ]
end

我建议以与现有模型类似的方式引入 Team 和 TeamMembership 模型。同时将参与的 belongs_to 关联从 user 更改为多态 participant.

class Team < ApplicationRecord
  has_many :team_memberships
  has_many :users, through: :team_memberships
  has_many :participations, as: :participant
end

class TeamMembership < ApplicationRecord
  belongs_to :team
  belongs_to :user
end

class User < ApplicationRecord
  has_many :team_memberships
  has_many :teams, through: :team_memberships
  has_many :participations, as: :participant
end

class Participation < ApplicationRecord
  belongs_to :participant, polymorphic: true
  belongs_to :document
  enum role: [ :admin, :editor, :viewer ]
end

class Document < ApplicationRecord
  has_many :participations

  # if desired create a users method to conveniently get a list of users with access to the document
  def users
    @users ||= participations.flat_map do |participation|
      case participation.partipant
      when User
        [participation.participant]
      when Team
        participation.participant.users
      end
    end
  end
end

我只会添加 has_many :through 关联,因为您发现 benefit/need 拥有它们。除非您有特定的用例,否则这将降低维护它们的复杂性。在 User 具有团队关联的情况下,很明显您可能希望获得用户所属的团队,因为 TeamMembership 对象中没有您可能需要的特定信息决心,真好has_many:through to have.

编辑:添加了 Document 模型。

由于您已经有了一个 participation 模型,您可以将其用作用户和团队之间的连接模型。由于一个 user 可以属于多个团队,而一个文档可以有多个团队,因此您可以使用 has_many through 团队和文档之间的关系。我们将其称为 DocumentTeam 模型。

class User < ApplicationRecord
  has_many :participations
  has_many :documents, through: :participations
  has_many :teams, through: :participations
end

class Participation < ApplicationRecord
  belongs_to :document
  belongs_to :user
  belongs_to :team, optional: true
  enum role: [ :admin, :editor, :viewer ]
end

class Team < ApplicationRecord
  has_many :participations
  has_many :users, through: :participations
  has_many :document_teams
  has_many :document, through: :document_teams
end

class Document < ApplicationRecord
  has_many :participations
  has_many :users, through: :participations
  has_many :document_teams
  has_many :teams, through: :document_teams
end

class DocumentTeam < ApplicationRecord
  belongs_to :document
  belongs_to :team
end