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?