Dan Rosenstark
Dan Rosenstark

Reputation: 69757

Many-to-Many Association To Same Model with ActiveRecord?

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

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:

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?

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

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

Upvotes: 2

Views: 433

Answers (2)

Dan Rosenstark
Dan Rosenstark

Reputation: 69757

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.

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.

Upvotes: 0

Thiago Arrais
Thiago Arrais

Reputation: 34180

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

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.

Upvotes: 2

Related Questions