Clean, search-friendly URLs for your Rails applications

December 07, 2010

Slugs or permalinks are a common feature of blogging applications—instead of accessing data on your site with URLs like http://mygreatrubybookstore.com/books/349 you can point users (and search engines) to pretty URLs like http://mygreatrubybookstore.com/books/pragmatic-ruby. And slugs aren’t just for blog applications! I use these techniques liberally in my applications to add a little polish and usability. Group names, user profiles, and other models are fair game. This is an easy feature to implement, whether you’re using one of several available Ruby gems. You can even roll your own if you’d like. Read on to get started.

FriendlyId

I have the most experience with FriendlyId. It’s easy to install and configure, is under active development, includes thorough documentation, and overall has a good balance of features to simplicity. In addition to creating nice URLs, FriendlyId also handles reserved words like new and edit (you can add your own, too); non-unique slugs; caching; and scoped slugs (which I haven’t had a need for yet).

Let’s say you’ve got an existing Book model, and you want to add FriendlyId to it. Install the gem to get started, then run the generator and, optionally, a migration to generate a cached version of the slug string to speed up queries:

  $ rails generate friendly_id
  $ rails generate migration AddSlugToBook cached_slug:string
  $ rake db:migrate

And finally configure your model to have a friendly ID:

  # app/models/book.rb

  class Book < ActiveRecord::Base
    has_friendly_id :title, :use_slug => true
  
    # rest of the model
  end

If you’re adding FriendlyId to a model that already has some records stored in the database, and are using the cached slug option, you’ll need to run the following rake task to create slugs for existing data:

  $ rake friendly_id:redo_slugs MODEL=YourModelHere

Restart your application server and you’re ready to go.

ActsAsUrl

ActsAsUrl, part of the Stringex collection of extensions to Ruby’s String class, may be more beneficial to you if you need better Unicode support (as in, you want to translate common Unicode characters into more search-friendly terms). Check the README for some of the slick translations ActsAsUrl can do. You’ll have to do a little more work&dash;once you’ve indicated your model’s attribute for acts_as_url, you’ll need to override to_param. This isn’t too hard, but it’s also not as turnkey as FriendlyId. If you need that translation support, though, ActsAsUrl should be worth the extra effort.

Babosa

You might also take a look at Babosa, a FriendlyId derivative that lets you do things like convert strings to Ruby methods. I actually could have used that for a project I currently maintain at work.

I’m including the venerable permalink_fu because it was an early and popular solution to this problem. I used this plugin in some of my own early-ish Rails projects. It doesn’t appear to be in current development, though, and lacks some of the features of more current projects like FriendlyId and ActsAsUrl.

DIY

Finally, I should acknowledge that yes, you can easily do this yourself in your model, by creating a method for the slug (probably using Rails’ parameterize method) and overriding to_param to do lookups based on the slug instead of the id column. The benefit of a gem like one of these I’ve listed, though, is that you can apply slugs to as many different models in your application as you’d like, with minimum code duplication, and be able to focus on features more unique to your own project.

Rails testing made simple

Learn to test Rails apps the way I learned, building up tests step-by-step, in Everyday Rails Testing with RSpec. Expanded to include exclusive content and a complete sample Rails application. Learn more »

Also available on Amazon.com.

blog comments powered by Disqus