views:

32

answers:

1

Hello, I have a Category, a Subcategory and a Product model.

I have:

Category has_many Subcategories
Subcategory has_many Products
Subcategory belongs_to Category
Product belongs_to Subcategory

Is there a way to have something like

Category has_many Projects through Subcategories

?

The 'normal' rails way wouldn't work because "subcategory" doesn't belongs to product so product does not have a subcategory_id field. Instead, I need the query to be something like

SELECT * FROM products WHERE id IN category.subcategory_ids

Is there a way to do that?

Thanks,

Nicolás Hock Isaza

+3  A: 

If you do this the 'normal' Ruby on Rails way, the database you described would look something like this. If your database isn't structured like this, I suggest reading more about how associations are done for in Ruby on Rails because this is the right way (and you should be using t.references :category in your migration since it was designed to make it easy to not mess your references up).

+----------------+  +----------------+ +----------------+
| categories     |  | subcategories  | | products       |
+----------------+  +----------------+ +----------------+
| id             |  | id             | | id             |
| ...            |  | category_id    | | subcategory_id |
|                |  | ...            | | ...            |
+----------------+  +----------------+ +----------------+

With this as your database structure, the has_many :products, :through => subcategories works for the Category model.

Category.rb
class Category < ActiveRecord::Base
  has_many :subcategories
  has_many :products, :through => :subcategories
end
Subcategory.rb
class Subcategory < ActiveRecord::Base
  belongs_to :category
  has_many :products
end
Product.rb
class Product < ActiveRecord::Base
  belongs_to :subcategory
  has_one :category, :through => :subcategory  # don't need this, but it does work
end
ruby script\console
>> c = Category.create
=> #<Category id: 1, ...>
>> c.subcategories.create
=> #<Subcategory id: 1, category_id: 1, ...>
>> p = s.products.create
=> #<Product id: 1, subcategory_id: 1, ...>
>> c.products
=> [#<Product id: 1, subcategory_id: 1, ...>]
>> p.category         # if you have the has_one assocation
=> #<Category id: 1, ...>
Samuel
Ok. I had that exact thing (without the has_one) and it didn't work. I guess it should have been a typo because I wrote everything again as soon as I saw your answer and it's working now. Thanks :-)
Hock