views:

149

answers:

2

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
+1  A: 

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.

Thiago Arrais
+1 Thanks. That did not do it, but I'm beginning to look at the whole relationship again. When I used CategoryA it actually worked, it just never got the other side of the relationship. I'm going to run some more tests.
Yar
Sorry, your answer is right, but it's half the story. The other half is in my answer (below)... but yeah, very cool, thank you.
Yar
A: 

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.

Yar