By default, Rails uses ID’s in URLs. For example, let’s say we have a list of categories stored in the categories table of the database. The “Super Cool” category is stored with categories#id = 5. To view that category our URL will look like:
http://yourAwesomeDomain.com/category/5
That works great, but it’s not very user friendly. It’s also not very good for SEO purposes. A better URL would use a human-readable and search-engine-decipherable slug instead of an ID. For example:
http://yourAwesomeDomain.com/category/super-cool
How do we get that? Easy!
First, add a column named “slug” to the categories table:
# dbmigrate20120402020611_create_categories.rb
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.string :name
t.string :slug
t.timestamps
end
end
end
Next, add these lines to your category model:
# appmodelscategory.rb
class Category < ActiveRecord::Base
before_create :generate_slug
attr_protected :slug
def generate_slug
self.slug = name.parameterize
end
def to_param
slug
end
end
Bam! You are done. Your rails helpers and other logic will now automagically use slugs instead ID’s. For example:
@my_new_cat = Category.create(:name => 'Super Cool') => #<Category id: 3, name: "Super Cool", slug: "super-cool", created_at: "2012-04-02 18:43:08", updated_at: "2012-04-02 18:43:08"> category_path(@my_new_cat) => /category/super-cool link_to(@my_new_cat.name, @my_new_cat) => <a href="/category/super-cool">Super Cool</a>
And in your controller, you can find the category by searching with the slug:
# appcontrollerscategory_controller.rb
class CategoryController < ApplicationController
def show
@category = Category.find_by_slug(params[:id])
end
end
Pretty cool, huh?





