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

时间:2015-05-27 16:01:44

标签: ruby-on-rails activerecord has-and-belongs-to-many

我有两张桌子:

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将此关系中的两个模型关联起来两次?我需要多个并且属于许多表吗?也许是一个拥有并属于许多"通过"。这看起来像什么?

答案:

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

2 个答案:

答案 0 :(得分:0)

您无法使用belongs_to

定义多对多的关系

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

修改

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

你不能使用一个has_and_belongs_to_many表来实现这个目标,我会去找一个has_many:through关系。如果您只有两个组类别,请在连接表中为该类别设置一个标记。

尚未测试,但类似的东西应该起作用

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关系,您需要定义多个连接表。

答案 1 :(得分:0)

假设您已经知道如何处理数据模型中的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推荐的方式)。

我希望有所帮助!