rails 中两个表之间的两个或多个多对多关系

Two or more Many to Many relationships between two tables in rails

我有两个表:

UsersGroups

一个用户has_many组和一个组,has_many一个用户:

u = User.last
u.groups
g = Group.last
g.users

假设我出于某种奇怪的原因想要第二个不同组的列表。再次,一个用户有多个组(在本例中称为 other_group),一个组有很多用户。

u = User.last
u.other_groups
g = Group.last
g.other_users

如何使用 Active Record 两次关联此关系中的两个模型?我需要多个 has 和 belongs to many tables 吗?也许 a 拥有并属于许多 "through"。这看起来像什么?


答案:

class Matter < ActiveRecord::Base
  has_many :matters_lawfirms
  has_many :matters_other_lawfirms
  has_many :lawfirms, class_name: 'Lawfirm', through: :matters_lawfirms,  :source => :lawfirm
  has_many :other_lawfirms, class_name: 'Lawfirm', through: :matters_other_lawfirms,  :source => :lawfirm
end

class Lawfirm < ActiveRecord::Base
  has_many :matters_lawfirms
  has_many :matters_other_lawfirms
  has_many :matters, class_name: 'Matter', through: :matters_lawfirms,  :source => :matter
  has_many :other_matters, class_name: 'Matter', through: :matters_other_lawfirms,  :source => :matter
end

class MattersLawfirm < ActiveRecord::Base
  belongs_to :matter
  belongs_to :lawfirm
end

class MattersOtherLawfirm < ActiveRecord::Base
  belongs_to :matter
  belongs_to :lawfirm
end

迁移:

class AddMatterOtherLawfirms < ActiveRecord::Migration
  def change
    create_table :matters_other_lawfirms, :id => false do |t|
      t.references :matter, :lawfirm
    end

    add_index :matters_other_lawfirms, [:matter_id, :lawfirm_id],
      name: "matters_other_lawfirms_index",
      unique: true
  end
end



class AddMatterLawfirmsHabtmt < ActiveRecord::Migration
  def change
    create_table :matters_lawfirms, :id => false do |t|
      t.references :matter, :lawfirm
    end

    add_index :matters_lawfirms, [:matter_id, :lawfirm_id],
      name: "matters_lawfirms_index",
      unique: true
  end
end

您根本无法使用 belong_to

定义多对多关系

您应该实施 has_and_belongs_to_manyhas_many :through 关系,而不是 has_many - belongs_to 关系。

编辑

好的,我想我现在明白了,

您无法使用单个 has_and_belongs_to_many table 实现此目的,我会选择 has_many :through 关系。如果您只有两个组类别,请在您的加入中为该类别设置一个标志 table。

尚未测试,但类似的东西应该可以工作

class GroupMembership #.. with category field or something
  belongs_to :group
  belongs_to :user

class User
  has_many :group_memberships
  has_many :local_groups, -> { where group_memberships: { category: 'local' } }, :through => :group_memberships, :source => :group
  has_many :outside_groups, -> { where group_memberships: { category: 'outside' } }, :through => :group_memberships, :source => :group

class Group
  has_many :group_memberships
  has_many :local_users, -> { where group_memberships: { category: 'local' } }, :through => :group_memberships, :source => :user
  has_many :outside_users, -> { where group_memberships: { category: 'outside' } }, :through => :group_memberships, :source => :user

对于 HABTM 关系,您需要定义多个连接 table。

假设您已经知道如何处理数据模型中的 has_many 关系(Alper 似乎要写到这一点),在两个表之间容纳多个关系非常容易(我现在正在做一些事情这涉及将用户明确地链接到他们正在从事的项目以及他们拥有的项目。我相信这与您要实现的目标非常相似)。代码看起来像这样:

用户模型

has_many :regular_groups, class_name: 'Group', through: :user_regular_groups
has_many :other_groups, class_name: 'Group', through: :user_other_groups

群模型

has_many :regular_users, class_name: 'User', through: :user_regular_groups
has_many :other_users, class_name: 'User', through: :user_other_groups

显然,在这种情况下,我们使用了两个不同的关联表(user_regular_groups 和 user_other_groups),但是您可以使用一个范围来完成类似的事情(沿着 Alper 的思路)推荐)。

希望对您有所帮助!