Ruby on Rails – Customized URLs for User Profile (show) Pages in Rails 3.1

Ruby on Rails – Customized URLs for User Profile (show) Pages in Rails 3.1

Just this July, I decided it was time to graduate from PHP to Ruby. I had to see what all the hype was about. Rails was everywhere. Getting started with the Ruby on Rails tutorial by Michael Hartl couldn’t be easier. Thirteen chapters later, and I’m working on my new startup’s website, http://thegeno.me.

While I have my complaints about Ruby (this will definitely be a future post!), the Rails framework makes many things just work. It’s like magic. Despite the ease in accomplishing common, regular tasks, achieving more custom effects often requires a bit of…tinkering. The Rails community is pretty big, but Googling and reading a few StackOverflow posts doesn’t provide a quick answer to every question like PHP. Here’s one of the first items I spent some time figuring out and hunting down – changing the URL for the show view of a model.

The Problem with URLs in Rails

By default, each item entered into your application’s database is assigned a unique id (the primary key). Rails will use this to identify a particular object from your database. Moreover, the default link for showing this item is identified by this id. For example, in your Users model, you might have a user with the email ‘user@example.com’, whose id is ’2′, and username is ‘widgetman.’ By default, this user’s ‘show’ page is found under the url: http://yourapplication.com/users/2.

While it’s great that Rails generates all of this very easily for us, we might want better permalinks for a more personal feel or better SEO. Assuming that usernames are unique in this example, we would want to make it so that the user’s profile would be routed to the url: http://yourapplication.com/users/widgetman. Doing this is not as straightforward as you’d think.

Step 1: Add a Lowercase Permalink to Your User Model

By default, I allow my users to register with usernames that have no spaces but may include both upper and lowercase letters. Since I want my permalinks to be all lowercase letters, I’m going to add a new column calls ‘permalink.’

$ rails generate migration AddPermalinkToUsers permalink:string
$ bundle exec rake db:migrate

Once the migration is complete, let’s open our User Model file to add the necessary code to create the permalink upon user registration:

../app/models/user.rb

.
.
before_save :create_permalink
.
.

This will execute the function (we are about to write) to create the permalink during our user registration process.

../app/models/user.rb

.
.
private
     def create_permalink
          self.permalink = username.downcase
     end
.
.

Now by default, when a user registers for the site, the data they enter for ‘username’ (or whatever field you want to use for the permalink) will be saved in all lowercase in the permalink column.

Step 2: Update Your ‘to_param’ in Your User Model

By default, to_param, the function that defines the column in your model’s table that is passed as the :id whenever a request to the associated controller is made, is set as the primary key in your table. By specifying a to_param we can help to control which column in your model is used for the permalink (note: this must be a unique value or bad things will happen!).

../app/models/user.rb

.
.
def to_param
     permalink
end
.
.

Now, the permalink column from our user model will be used to generate links for individual records. We’re almost there.

Step 3: Update Your Controller to find Your Records According to the New Default Parameter

Now that we changed the default parameter from :id to :permalink. Normally, our user controller would look something like this for the show action:

../app/controllers/users_controller.rb

.
.
def show
     @user = User.find(param[:id])
     @title = @user.name
end
.
.

By default, Rails will pass the id from the User table as the param[:id] upon requesting the show action. However, we have just updated our user model to pass the permalink from the User table as the parameter that is returned in param[:id]. Once we realize that User.find(param[:id]) is a shortcut for User.find_by_id(param[:id]) the change we need to make might become more apparent:

../app/controllers/users_controller.rb

.
.
def show
     @user = User.find_by_permalink(param[:id])
     @title = @user.name
end
.
.

This will make sure that the proper @user is retrieved from your table based on the permalink that was requested. Keep in mind that all instances where you defined @user as @user = User.find(param[:id]) need to be changed to @user = User.find_by_permalink(param[:id]).

This is how I was able to change the permalink structure of my user (and other models). Always make sure that you're using a unique column for defining your permalinks! I hope to write more posts as I learn more Rails.

22 Comments

  1. buddhamagnet

    I think the method you mention above is to_param, not to_params. Great post, I went through a similar process generating friendly URLs for users by full name.

  2. You are 100% correct on that one…I’ve updated the post to the proper function.

    Thanks for reading!

  3. Hi Alex!

    Works like a charm. Thanks. But I have a problem.
    Sorry, I’m new in the rails world.

    I need get the ID to pass into my variable. I can’t do that because the ID param was converted into USERNAME in url.

    For exemple:
    @chef_list = Recipe.find(params[:chef_id])
    @recipes = @search.where({:status_id => 1, :chef_id => @chef_list }).order(“id desc”).page(params[:page]).per(9)

    So, I need to pass the “chef_id” to list recipes from a especific user.

    Works perfectly: /chefs/54/recipes/
    Doesn’t work: /chefs/sanson/recipes

    Sorry about my english, I Hope that you understand my problem.

    What should I do? Thank you again.

  4. Hi Sanson,

    I think I’m understanding. Make sure your models and routes are properly set up:

    Chef Model:

    has_many :recipes

    Recipe Model:

    belongs_to :chef

    Routes:

    resources :chefs do
    resources :recipes
    end

    Now the language in the controller:

    RecipesController

    def index //This will be http://application.com/chefs/sanson/recipes
    @chef = Chef.find_by_permalink(params[:chef_id])
    @recipes = @chef.recipes
    end

    def show #This will be http://application.com/chefs/sanson/recipes/42
    @chef = Chef.find_by_permalink(params[:chef_id])
    @recipe = Recipe.find(params[:id])
    end

    Not sure if this is exactly what you’re looking for, but hopefully it get’s you to where you want to be!

    Disclaimer: I wrote this sort of quickly, so please excuse any errors!

  5. Works perfectly now. Thank you again.

  6. This is a fantastic little tutorial on URLs that will definitely be more SEO-friendly. It’s also the kind of thing that helps one write a CMS :) Thanks for taking the time to write!

  7. Hi David,

    Glad you found this helpful. It was surprising to me that rails had to be cajoled into SEO friendly links.

    Thanks for reading!
    -Alex

  8. Thanks a lot!!

    This seems good, but how to have a profile link as facebook & twitter??

    please help..

  9. http://mensengagementrings.ca

    I beloved as much as you will receive performed proper here. The sketch is tasteful, your authored material stylish. nonetheless, you command get got an edginess over that you want be turning in the following. ill undoubtedly come more beforehand again as exactly the similar nearly a lot frequently within case you protect this increase.

  10. If your Garage Door has been fixed with the presence of poles then
    attach the wire with the poles. One of its advantages is that it is less expensive than the three other types
    of garage doors. If your garage door is old and worn out, a new one can do a lot to improve the look of your
    home.

  11. I wanted to thank you for this very good read!!
    I definitely enjoyed every little bit of it.
    I have you bookmarked to look at new things you post…

  12. It’s hard to find your blog in google. I found it on 14 spot,
    you should build quality backlinks , it will help you to get more visitors.
    I know how to help you, just type in google –
    k2 seo tips

  13. This is a natural occurrence and can be easily mistaken for acne.
    , the official medical journal of the American Society of
    Plastic Surgeons (ASPS). The above are just some of the most important skin care tips and
    best acne treatments to keep in mind if you have acne.

  14. It means that you get total discounts at the time of subscription. They offer so many extras
    that make starting up a new website so simple that even a complete novice could get a website up and
    running. What search results will offered up with unless you possess a website or perhaps a blog to market your business.

  15. I read a lot of interesting content here. Probably you spend
    a lot of time writing, i know how to save you a lot of work, there is an online tool that creates
    unique, google friendly posts in minutes, just search in google – laranitas free
    content source

  16. Hi i amm kavin, its my first occasion to commenting anyplace, when i
    read this piece oof writing i thought i could also
    make comment due tto tis briloliant paragraph.

  17. In fact, when seeking guaranteed personal loans, they are often the best loan provider to go to.
    Unsecured loans give you approval on the same
    day of your application and you get the money directly wired to your
    bank account. 1500 herewith the small repayment
    period of 2 weeks to 4 weeks.

  18. A fantastic charger is one that can maintain the battery safe.
    The electronic cigarette is making the new generation of smoking popular all over the world.
    Cigarette smoking is one habit that is really hard
    to deny and hard to eliminate for most people.

  19. Nice post. I was checking constantly this blog and I’m impressed!
    Extremely helpful info particularly the remaining section :
    ) I handle such information a lot. I used to be looking for this certain information for a very lengthy
    time. Thanks and good luck.

  20. Hello, I think ypur site mmight be having
    browser compatibility issues. When I look at your website iin Ie, it looks
    fine but when opening inn Internet Explorer, iit has
    some overlapping. I just wanted to give you
    a quick heads up! Oher then that, terrific blog!

  21. F*ckin’ awesome things here. I’m very glad to see your article.
    Thanks a lot and i’m looking forward to contact you.
    Will you kindly drop me a mail?

  22. Great information over again. Thanks;)

    Feel free to vsit my blog … gretzky hockey

Leave a Reply

Spam Protection by WP-SpamFree