Everyday Rails

Clean, search-friendly URLs for your Rails applications

By Aaron Sumner, 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.

What do you think? Follow along on on Mastodon, Facebook, or Bluesky to let me know what you think and catch my latest posts. Better yet, subscribe to my newsletter for updates from Everyday Rails, book picks, and other thoughts and ideas that didn't quite fit here.
Buy Me A Coffee

Test with confidence!

If you liked my series on practical advice for adding reliable tests to your Rails apps, check out the expanded ebook version. Lots of additional, exclusive content and a complete sample Rails application.

Newsletter

Ruby on Rails news and tips, and other ideas and surprises from Aaron at Everyday Rails. Delivered to your inbox on no particular set schedule.