user2327691
user2327691

Reputation: 53

Rails rename model name in url dynamically

In Rails, I have a model named item. Each item belongs_to category (another model), which has an attribute called name.

When seeking any item, I see the url as /item/:id

instead, I would like the url to show up as /'item.category.name'/:id

e.g. if the item belongs to category whose name is "footwear", then, I would like to see the url as /footwear/:id. And if there is another item that belongs to category whose name is "clothing", then I would like to see the URL as /clothing/:id

Is this possible?

Upvotes: 2

Views: 226

Answers (1)

Shyam Habarakada
Shyam Habarakada

Reputation: 15785

If you setup a route like

# config/routes.rb
RouteTest::Application.routes.draw do
  get ':category_name(/:id)', to: 'items#show', constraints: {id: /\d+/}
end

It will map to the show action in your ItemsController, and in there, you will have access to params[:category_name] and params[:id]. With this information, you should be able to get the data you want and render it.

Note that this route however will likely have the undesirable effect of masking any routes that follow. You could use rails advanced route constraints to further narrow down 'which values would be considered valid category_names' but this wouldn't be a very scalable or manageable approach.

For example, you could do something like

RouteTest::Application.routes.draw do
  get ':brand_name(/:id)', to: 'items#show', constraints: lambda { |request| BrandList.include?(request.params[:brand_name]) }

  # etc. ...

  get ':category_name(/:id)', to: 'items#show'
end

but this only really works well when the BrandList is a finite list that you could setup during application initialization.

A better, more scalable approach might be to design your URLs like

/brand/adidas
/brand/teva
/shoes/1
/shoes/2
/jackets/45

IOW, prefix known namespaces like brand with an appropriate human friendly URL prefix and use category based route as a catch-all at the bottom.

Hope this helps.

Upvotes: 2

Related Questions