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:

http://weblog.jamisbuck.org/2007/2/5/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