SEO friendly URLs in RoR
Asked Answered
B

4

4

Let's say I have a relatively basic CRUD application for editing music albums. In the database I have:

id | album_name | artist  |  navigation

1    Lets Talk   Lagwagon    lets-talk

However, instead of albums/1 returning my Show page, I want the page to be accessible by the albums/lets-talk route.

So in my controller I have:

  def show
    @album = Album.find_by_navigation(params[:id])
  end

And in my index view I have:

<%= link_to 'Show', :controller => "albums", :action => "show", :id => album.navigation %>

This successfully performs its function, however, the Ruby API says my link_to method is old and archaic without listing an alternative, so I suspect I'm going about this the wrong way.

Basifixed answered 26/2, 2013 at 5:55 Comment(0)
P
6

Check out friendly_id gem. It is exactly what you need.

Pathogenic answered 26/2, 2013 at 7:16 Comment(1)
Sergey, This was precisely what I needed, thanks. @TylerDeWitt Thanks for the link, I somehow missed it when I was scouring RailsCasts for a solution last night.Basifixed
S
17

Define your to_param in the model:

class album
    def to_param
        "#{id}-#{album-name.parameterize}"
     end
end

Now you can use

<%= link_to album.album_name, album %>

to create the link to the seo path

Then in your controller:

Album.find(params[:id])

will call to_i -> so you get the Topic.find(2133) or whatever.

This will result in urls of the form: "/album/2-dark-side-of-the-moon" which although not exactly what was asked for has advantages - The id is used to find the album - which is unique, when the name might not be.

The parameterize method "Replaces special characters in a string so that it may be used as part of a ‘pretty’ URL" - http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize

Sandberg answered 26/2, 2013 at 6:1 Comment(4)
why the downvote? This is how this is done in the Rails Best Practices course at codeschool. Seems to work well on projects Iv'e done. Have i missed the point of the question?Sandberg
Wasn't downvoted by me, I just read it. While I'm not utilizing this particular solution this time, I appreciate the information. How is codeschool? Worth it?Basifixed
First, with "#{id}-#{album-name.parameterize}", your url will be /album/2-lets-talk, not /album/lets-talk. Second, with non-latin names when you use parametrize then the name in the link will be different from the name of the object, this case not match question. Thats why downvote.Phototherapy
OK. Thanks for the feedback. Iv'e updated my answer to indicate why you might not want to rely on the album name. It's a possible way to tackle this sort of problem. Just using the Name unaltered is not.Sandberg
P
6

Check out friendly_id gem. It is exactly what you need.

Pathogenic answered 26/2, 2013 at 7:16 Comment(1)
Sergey, This was precisely what I needed, thanks. @TylerDeWitt Thanks for the link, I somehow missed it when I was scouring RailsCasts for a solution last night.Basifixed
D
1

If you want to display URL in browser as app/albums/lets-talk but POST params as album_id => 1, for shopping cart addition etc.

In your album model:

# PRODUCT MODEL
 before_create do
   self.navigation = album_name.downcase.gsub(" ", "-")  
  end

def to_param
    [id, album_name.parameterize].join("-")
end

Now you can

@album = Album.find_by_navigation(params[:id])

and

album = Album.find(params[:album_id])
Demineralize answered 23/7, 2015 at 10:45 Comment(0)
P
0

It seems like you whant to override :id parameter to :name parameter. This case described in this article.

class User < ActiveRecord::Base
  def to_param  # overridden
    name
  end
end

user = User.find_by_name('Phusion')
link_to 'Show', user_path(user)  # => <a href="/users/Phusion">Show</a>
Phototherapy answered 26/2, 2013 at 6:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.