views:

68

answers:

1

I have a fairly simple model; Users have_many products. I would like to be able to view a list of all products as well as a list of the products associated with a given user. My routes are set up like this:

/products
/products/:id
/users
/users/:id
/users/:id/products

The catch here is that I'd like to display the product list differently in the product#index view and the user/products#index view.

Is there a 'correct' way to do this? My current solution is to define products as a nested resource inside users, and then to check for params[:user_id] - if its found I render a template called 'index_from_user', otherwise I just render the typical 'index' template.

This is a situation I'm running into a lot - if there's a preferred way to do it I'd love to know...

+1  A: 

You can declare two "products" routes - one under users, and one independent of users eg:

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

They will both look for "ProductsController#index" but the second will have the "user_id" pre-populated from the route (note: "user_id" not just "id")

So you can test for that in the index method, and display different items depending on whether it is present.

You will need to add a before_filter to the ProductController to actually instantiate the user model before you can use it eg:

before_filter :get_user # put any exceptions here

def index
  @products = @user.present? ? @user.products : Product.all
end

# all the other actions here...


# somewhere near the bottom...
private

def get_user
  @user = User.find(params[:user_id])
end

If you really want to display completely different views, you can just do it explicitly in the index action eg:

def index
  @products = @user.present? ? @user.products : Product.all
  if @user.present?
     return render(:action => :user_view) # or whatever...
  end
  # will render the default template...
end
Taryn East