与ActiveRecord的多对多关联到同一模型?

时间:2022-06-21 20:16:31

I'm following this tutorial which is working splendidly for has_many :through relationships. I've got normal things like category_product working.

我正在按照本教程为has_many工作:通过人际关系。我有类似product_product工作的正常事情。

However, I am not able to conceptualize this situation (nor get it to work): I have a Category that has related Categories. Since every category can have N categories... first off, is this actually a many-to-many situation (I'm pretty positive that it is)? Secondly, what would this look like? My migration looks like this:

但是,我无法概念化这种情况(也无法使其工作):我有一个具有相关类别的类别。因为每个类别都可以有N个类别......首先,这实际上是多对多的情况(我是非常积极的)?其次,这会是什么样的?我的迁移看起来像这样:

create_table :categories do |t|
  t.string :name
  t.timestamps
end

create_table :related_categories, :id => false do |t|
  t.integer :category_a_id
  t.integer :category_b_id
end

and my model's guts are

而我的模特的胆量是

has_many :related_categories, :foreign_key=>"category_a_id"
has_many :categories, :through => :related_categories, :source=>:category_a

This is obviously not right, though it's getting there (i.e., it's 100% broken). How can I do this?

这显然是不对的,虽然它已经到了那里(即它已经100%被打破)。我怎样才能做到这一点?

Edit: I forgot this, but only here on SO (meaning it's not the answer):

编辑:我忘了这个,但只在这里SO(意思是它不是答案):

class RelatedCategory < ActiveRecord::Base
  belongs_to :category_a, :class_name=>"Category"
  belongs_to :category_b, :class_name=>"Category"
end

2 个解决方案

#1


You should try :source => :category_b in your has_many declaration.

你应该在你的has_many声明中尝试:source =>:category_b。

You already used category_a_id as your foreign key to the related categories table. This basically tells ActiveRecord to match the category_a_id field on the related_categories table to the current Category object id when fetching all related_categories records related to it. The source parameter to this has_many :through declaration specifies which field should be considered for finding (or writing, for that matter) the related objects when filling the categories collection.

您已使用category_a_id作为相关类别表的外键。这基本上告诉ActiveRecord在获取与其相关的所有related_categories记录时,将related_categories表上的category_a_id字段与当前的Category对象id匹配。此参数的源参数has_many:through声明指定在填充类别集合时应考虑哪个字段用于查找(或写入)相关对象。

#2


Here's the answer, but it's not pretty.

这是答案,但它并不漂亮。

  has_many :related_categories, :foreign_key=>"category_a_id"
  has_many :related_categories2, :class_name=>"RelatedCategory", :foreign_key=>"category_b_id"
  has_many :categories, :through => :related_categories, :source=>:category_b
  has_many :categories_backwards, :through => :related_categories2, :source=>:category_a
  has_many :category_products

then you would have to do some goofy getter that combines the categories + categories_backwards, or something.

然后你必须做一些结合了类别+ categories_backwards或其他东西的傻瓜。

Edit [2 minutes later]: Wow, with the getter it almost seems perfect! Of course, the problem is that you have to push to categories and not whatever you get from the getter.

编辑[2分钟后]:哇,有吸气剂,它几乎看起来很完美!当然,问题在于你必须推送到类别,而不是从getter得到的任何东西。

#1


You should try :source => :category_b in your has_many declaration.

你应该在你的has_many声明中尝试:source =>:category_b。

You already used category_a_id as your foreign key to the related categories table. This basically tells ActiveRecord to match the category_a_id field on the related_categories table to the current Category object id when fetching all related_categories records related to it. The source parameter to this has_many :through declaration specifies which field should be considered for finding (or writing, for that matter) the related objects when filling the categories collection.

您已使用category_a_id作为相关类别表的外键。这基本上告诉ActiveRecord在获取与其相关的所有related_categories记录时,将related_categories表上的category_a_id字段与当前的Category对象id匹配。此参数的源参数has_many:through声明指定在填充类别集合时应考虑哪个字段用于查找(或写入)相关对象。

#2


Here's the answer, but it's not pretty.

这是答案,但它并不漂亮。

  has_many :related_categories, :foreign_key=>"category_a_id"
  has_many :related_categories2, :class_name=>"RelatedCategory", :foreign_key=>"category_b_id"
  has_many :categories, :through => :related_categories, :source=>:category_b
  has_many :categories_backwards, :through => :related_categories2, :source=>:category_a
  has_many :category_products

then you would have to do some goofy getter that combines the categories + categories_backwards, or something.

然后你必须做一些结合了类别+ categories_backwards或其他东西的傻瓜。

Edit [2 minutes later]: Wow, with the getter it almost seems perfect! Of course, the problem is that you have to push to categories and not whatever you get from the getter.

编辑[2分钟后]:哇,有吸气剂,它几乎看起来很完美!当然,问题在于你必须推送到类别,而不是从getter得到的任何东西。