Routes and link generation

Hi, I'm setting up some routes for an online shop. I want to the urls to look like:

/category/department/product

The problem I'm having is how to generate the urls needed. Do I have to specify the category and department for each link? The problem is that a product can be in more than one category so I won't know what to pass.

I currently have this in routes.rb:

map.with_options :controller => 'catalog' do |catalog|   catalog.product ':category/:department/:id', :action => 'show' end

And this as my link:

<%= link_to 'A special banana', product_url(:category => 'fruit', :department => 'bananas', :id => 444) %>

Do I need to override to_param for the product? If so, how?

Thanks for any advice.

Cheers, Jord

Not sure if I was clear enough. What I don't understand is how to figure out which category and department a product is so that I can generate the links.

Am I making too much work for myself by have the routes setup like I want? Is it possible to have routes like this or would it be better to go for something like:

/product/1

I think a route like /category/department/product is a lot more readable and can already do this if a product only appears in one category, but I'm not sure how to go about it when a product is in more than one category.

What do you think?

If you’ve set up your route like so

map.product “/:category/:department/:product”, :controller => […]

then you should be able to generate the url like this

product_url(:category => category, :department => :department). If you’re looking to avoid the numeric representations of category and department, then make sure to redefine to_params in your models for each.

class Category […] def to_params name # Or whatever attribute you want… end end

Is that what you’re looking for?

RSL

Thanks for the reply Russell, but that's what I have already.

The problem was with generating a route to a product that exists in more than one department. Sya I was generating a route to a product from the home page, I wouldn't know which category to put for the url. Anyway, I've decided that it's probably more effect than it's worth. So, I've decided to go for /product/123-product-name for my product urls and stick with /category/department for category display.

Thanks anyway :slight_smile:

Cheers, Jord

I don’t understand why

product_url(:category => category, :department => department)

wouldn’t assign category based solely on the fact that you manually told it which category to use. I’ve never had the multiple category setup but I can’t imagine that Rails wouldn’t respond to setting a param manually.

RSL

I don't understand why

product_url(:category => category, :department => department)

wouldn't assign category based solely on the fact that you manually told it which category to use. I've never had the multiple category setup but I can't imagine that Rails wouldn't respond to setting a param manually.

It will, but say that I have a product which appears in both category A and B, how will I know which category, either A or B, to pass to product_url? It works ok if you are within the category when generating the route because you can grab the category from params[:category], but if you're not in the category, for example, on the home page, you won't know which category to pass to the product_url because there are two categories associated with the product.

Does that make sense? :slight_smile:

Cheers, Jord

Jordan,

Jamis wrote about some of these issues recently:

http://weblog.jamisbuck.org/2007/2/5/nesting-resources

~ j.

Jamis wrote about some of these issues recently:

Buckblog: Nesting resources

Thanks, I'll take a look :slight_smile:

Cheers, Jord

Yeah. That does make sense. I guess if it weren’t coming from a category-specific archive/page/whatever, what I’d do is pass it product.categories.first. I just tested [in irb] this kind of setup and it works nicely.

product_url(:category => @category || product.categories.first || nil, :department => :whatever}

if @category is set, then it uses it, else the first product.category, and if product.categories.empty? then it uses nil.

RSL