The Pug Automatic

Canonizing pseudo-slugs in Rails

Written September 13, 2009. Tagged Ruby, Ruby on Rails.

It's common to use pseudo-slugs in Ruby on Rails apps. You do something like

class Item < ActiveRecord::Base

def to_param
[id, slug].join("-")


The Rails URL helpers will now use this parameter in URLs instead of just the id. Controller actions can usually be left unchanged since ActiveRecord::Base#find will run to_i on the parameter string, lopping off the slug.

These pseudo-slugs let people mess with you, though. They could pass your URL to someone else as and it will work fine. It may even be indexed by search engines that way.

This is easy to overlook, but the solution is fairly obvious and simple:

class ItemsController < ActionController:Base

def show
@item = Item.find(params[:id])

canonical = @item.to_param
if canonical != params[:id]
redirect_to(:overwrite_params => { :id => canonical }, :status => :moved_permanently) and return


Using :overwrite_params will ensure any additional parameters are unchanged.

If you need this for more than just the show action, you might move it to a separate method, perhaps used as a before_filter.