Skip to content
This repository


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Easy-to-use and powerful slugging for Rails 3

tree: 39bf93eb4e

Fetching latest commit…

Cannot retrieve the latest commit at this time


Slugalicious — Easy and powerful URL slugging for Rails 3

(no monkey-patching required)

Author Tim Morgan
Version 1.2.1 (Mar 2, 2012)
License Released under the MIT license.


URLs for your ActiveRecord objects. It’s built for Rails 3 and is cordoned off
in a monkey patching-free zone.

use-cases for slugging. Slugs are stored in a separate table, meaning you don’t
keeping the old URLs around for redirecting purposes.

less pretty but guaranteed-unique backup slug generation strategy.

Slugalicious works with the Stringex Ruby library, meaning you get meaningful
Stringex is:



Important Note: Slugalicious is written for Rails 3.0 and Ruby 1.9 only.

Firstly, add the gem to your Rails project’s Gemfile:

gem 'slugalicious'


rails generate slugalicious

Then run the migration to set up your database.



class User < ActiveRecord::Base
  include Slugalicious

from a slug:

user = User.find_from_slug(params[:id])

Multiple slug generators

default String#to_url, provided by the Stringex gem.)

but then add in the first name if two people share a last name, we’d call
slugged like so:


it guaranteed unique. Let’s use the example generators shown above. If we create
a user with the name “Sancho Sample”, he will get the slug “sample”. Create
“sancho-sample;2”. The semicolon is the default ID separator (and it can be

Scoped slugs

“hammer” slug.

:scope option on the slugged method. Let’s say you wanted to limit the scope
of a @Product@’s slug to its associated Department; that way you could have a
product named “keyboard” in both the Computer Supplies and the Music Supplies

class Product < ActiveRecord::Base
  include Slugalicious
  belongs_to :department
  slugged :name, scope: :department_url_component


  def department_url_component + "/"

Now, your computer keyboard’s slug will be “computer-supplies/keyboard” and your
piano keyboard’s slug will be “music-supplies/keyboard”. There’s an important
slash at the end, as shown in the example above.

When you call to_param on your piano keyboard, instead of just “keyboard”, you
will get “music-supplies/keyboard”. Likewise, you can use the



def find_product
  @product = Product.find_from_slug_path(params[:path])

This is why it’s very convenient to have your :scope method/proc not only
preceding the slug.

Altering and expiring slugs


that produces an existing slug [active or inactive]).



active slug, as a way of both updating search engines’ indexes and ensuring that
find_product method shown above to be like so:

def find_product
  @product = Product.find_from_slug_path(params[:path])
    redirect_to product_url(@product), status: :moved_permanently
    return false
  return true

to the new URL.

The problem is that even though the old slug is inactive, it’s still “taken.” If
you create a product called “Keyboard”, but then rename it to “Piano”, the
product will claim both the “keyboard” and “piano” slugs. If you had renamed it
to make room for a different product called “Keyboard” (like a computer
keyboard), you’d find its slug is “keyboard;2” or similar.

instance. An example:

Something went wrong with that request. Please try again.