多态在Rails中有很多关系

时间:2016-03-07 01:14:14

标签: ruby-on-rails activerecord

我正在尝试与ActiveRecord建立多态的has-many-through关系。这是最终目标:

  • 用户可以属于许多组织和许多团队
  • 组织拥有众多用户和许多团队
  • 团队拥有众多用户且属于某个组织

我正在尝试使用has-many-through而不是has-and-belongs-to-many,因为我需要将一些信息与关系(如组织或团队中的用户角色)相关联,所以我做了联接表会员

我该如何实现?

3 个答案:

答案 0 :(得分:2)

我会像这样设计架构: enter image description here

  • Organization有很多Team
  • Team有很多TeamMember
  • User有很多TeamMember
  • TeamMember属于UserTeam

模型将是:

<强> organization.rb

class Organization < ActiveRecord::Base
  has_many :teams
  has_many :team_members, through: :teams
  has_many :users, through: :team_members
end

<强> team.rb

class Team < ActiveRecord::Base
  belongs_to :organization # fk: organization_id
  has_many :team_members
  has_many :users, through: :team_members
end

<强> user.rb

class User < ActiveRecord::Base
  has_many :team_members
  has_many :teams, through: :team_members
  has_many :organizations, though: :teams
end

<强> team_member.rb

class TeamMember < ActiveRecord::Base
  belongs_to :team      # fk: team_id
  belongs_to :user      # fk: user_id
  attr_accessible :role # role in team
end

因此,请与您的要求进行比较:

  

用户可以属于许多组织和许多团队

=&GT;好

  

组织拥有众多用户和许多团队

=&GT;好

  

团队拥有许多用户并属于某个组织

=&GT;好

顺便说一下,我们这里不使用任何多态,而TeamMember代表你早期想法中的Membership

答案 1 :(得分:1)

对于多态关联,

class User
  has_many :memberships
end

class Team
  belongs_to :organization
  has_many :memberships, :as => :membershipable #you decide the name
end

class Organization
  has_many :memberships, :as => :membershipable
  has_many :teams
end

class Membership
  belongs_to :user
  belongs_to :membershipable, polymorphic: true
end

请注意,UserTeamOrganization间接关联,并且每次通话都必须经过Membership

答案 2 :(得分:0)

在我的项目中,我使用Relationship类(在我名为ActsAsRelatingTo的gem中)作为连接模型。它看起来像这样:

# == Schema Information
#
# Table name: acts_as_relating_to_relationships
#
#  id                  :integer          not null, primary key
#  owner_id            :integer
#  owner_type          :string
#  in_relation_to_id   :integer
#  in_relation_to_type :string
#  created_at          :datetime         not null
#  updated_at          :datetime         not null
#

module ActsAsRelatingTo
  class Relationship < ActiveRecord::Base

      validates :owner_id,                  presence: true
      validates :owner_type,                presence: true
      validates :in_relation_to_id,         presence: true
      validates :in_relation_to_type,       presence: true

      belongs_to  :owner,                   polymorphic: true
      belongs_to  :in_relation_to,          polymorphic: true

  end
end

所以,在你的User模型中,你会说:

  class User < ActiveRecord::Base

    has_many :owned_relationships,
      as: :owner,
      class_name: "ActsAsRelatingTo::Relationship",
      dependent: :destroy

    has_many :organizations_i_relate_to, 
      through: :owned_relationships, 
      source: :in_relation_to, 
      source_type: "Organization"

    ...

  end

我相信您可以将source_type参数关闭,因为可以从Organization推断出已加入的类(:organizations)。通常,我会加入无法从关系名称推断出类名的模型,在这种情况下,我包含source_type参数。

有了这个,你可以说user.organizations_i_relate_to。你可以为任何一组类之间的关系做同样的设置。

您也可以在Organization课程中说:

class Organization < ActiveRecord::Base

    has_many :referencing_relationships,
      as: :in_relation_to,
      class_name: "ActsAsRelatingTo::Relationship",
      dependent: :destroy

    has_many :users_that_relate_to_me, 
      through: :referencing_relationships, 
      source: :owner, 
      source_type: "User"

这样你就可以说organization.users_that_relate_to_me

我厌倦了必须完成所有设置,所以在我的gem中我创建了一个acts_as_relating_to方法,所以我可以做类似的事情:

class User < ActiveRecord::Base
  acts_as_relating_to :organizations, :teams
  ...
end

class Organization < ActiveRecord::Base
  acts_as_relating_to :users, :organizations
  ...
end

class Team < ActiveRecord::Base
  acts_as_relating_to :organizations, :users
  ...
end

并且为我自动设置所有多态关联和方法&#34;。

很抱歉答案很长。希望你能找到有用的东西。