skip to Main Content

I have a model ‘Item’. It all works fine, however am not completely satisfied with its show path. I want to use certain parameters from items table to construct a more SEO friendly url. So here is my question..

How can I change my Show action url
from
‘mysite.com/items/1’
to
‘mysite.com/items/item-name/item-city/item-id’ where item-name, item-city, and item-id are dynamic for each specific item.

Is it possible to achieve this without a gem? if yes, how? If no, which gem would you suggest to achieve this in simplest way?

Thanks

2

Answers


  1. You can do something relatively simple and stays true to Rails by adding a to_param method to your model like so:

    def to_param
      "#{id}-#{name}-#{city.name}"
    end
    

    What this does is every time you use a method like the item_path, it will use the @item.to_param method (this is what it does now, and returns :id). Generating the normal route, but replacing the :id param with the SEO friendly one.

    And, on the other end, when you go to find(params[:id]) in the controller in your show, edit, delete, or update actions, it will to a to_i on it and turn it back into an id. This is what it does now, but to_i on an int is still an int.

    Your urls will look something like

    /items/56-boston-itemname
    

    The other benefit to this, if you happen to change the item name or the city name, it will change all the urls appropriately, but old urls that were sent in email will still work.

    Login or Signup to reply.
  2. One approach to this problem is to use route globbing:

    http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments

    You should be able to do something like this:

    get 'items/*names/:id', to: 'items#show', as: :item_names_path
    

    And put whatever you want in *names. This would take a little experimentation to get it right. I might add a method to item to create the names array.

    def names
      [city.name, name].uniq.compact
    end
    

    Then I believe you would call item_names_path(@item.names, @item)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search