views:

292

answers:

3

I am trying to set up a Many-to-Many association between 2 objects. I have gone through several tutorials and have been able to correctly set up the model. My problem is that I am having having trouble setting up the correct routes so I can view the full relationship... something like only displaying the products from a specific category (/categories/1/products/)

This is how I generated the model:

script/generate scaffold category name:string
script/generate scaffold product name:string
script/generate scaffold categorization category_id:integer product_id:integer

Here is the schema:

ActiveRecord::Schema.define(:version => 20100205210519) do

  create_table "categories", :force => true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "categorizations", :force => true do |t|
    t.integer  "category_id"
    t.integer  "product_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "products", :force => true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
end

Here is the 3 model objects:

class Category < ActiveRecord::Base
    has_many :categorizations
    has_many :products, :through => :categorizations
end

class Product < ActiveRecord::Base
    has_many :categorizations
    has_many :categories, :through => :categorizations
end

class Categorization < ActiveRecord::Base
    belongs_to :product
    belongs_to :category
end

Pretty simple and everything seems to be working fine because I can add a product to a category through the console:

@category.categorizations << Categorization.new(:product_id => 1)

I'm sure I need to update the routes.rb file but I don't really know the correct way to do it. This is what I put in the routes file:

map.resources :categories, :has_many => :products

When I try to view products on a category "/categories/7/products/" it just lists all of the products! Does this mean my route is set up correctly and I just need to write a custom action on the products controller (instead of it going to index)? What am I doing wrong here... am I close or way off?!?

Thanks

+2  A: 

What you want to do is use nested resources. The general format looks like this:

map.resources :users do |users|
  users.resources :posts
end

Read more about it here.

Jimmy Cuadra
Great link for the documentation. After going through the page it seems like my route is setup correctly. I believe the route I have is equivalent to the one you wrote... according to the rails routing guide: http://guides.rubyonrails.org/routing.html#nested-resources
Ryan Ferretti
Just for completeness, the route that Ryan is using (map.resources :categories, :has_many => :products) also defines a nested resource, its just using a different format.
Eduardo Scoz
+3  A: 

You're probably not using the data from the route to filter your list of products.

In your index method of the product_controller, you need to do something like:

Category.find(params[:category_id]).products
Eduardo Scoz
That was it... the route was set up correctly, I just wasn't handling the index action on the products page correctly. It was just returning the default "Product.all"
Ryan Ferretti
A: 

As proposed in this question, you could try adding the request parameter :category_id to your find query.

Always look at the output of rake routes.

LWille