SluggableFinder ================ Ismael Celis (http://www.estadobeta.com) This is a variation of acts_as_sluggable and acts_as_permalink. This plugin allows models to generate a unique "slug" (url-enabled name) from any regular atribute. Sluggable models can have a scope parameter so slugs are unique relative to a parent model. The plugin also adds an ActiveRecord::Base#find_sluggable method that looks into the "slug" field. If not found, it raises an ActiveRecord::RecordNotFound exception so you can use it just like find_by_id The plugin modifies to_param so it's transparent to link_to and url_for view helpers EXAMPLES ++++++++++++++++++++ In your models (app/models) +++++++++++++++++++++++++ class Category < ActiveRecord::Base has_many :posts sluggable_finder :title #slugifies the :title field into the :slug field end class Post < ActiveRecord::Base belongs_to :category has_many :comments sluggable_finder :title, :scope => :category_id #Post slugs are unique to the parent category end class Comment < ActiveRecord::Base belongs_to :post sluggable_finder :get_slug, :to => :permalink #creates slug from custom attribute and stores it in "permalink" field def get_slug #we define the custom attribute "#{post.id}-#{Time.now}" end end # Provide a list or reserved slugs you don't want available as permalinks # sluggable_finder :title, :reserved_slugs => ['admin','settings','users'] ++++++++++++++++++++ In your routes (config/routes.rb)++++++++++++++++++++ map.post 'posts/:post_slug' Or just the usual map.post 'posts/:id' ..because now Post.to_param returns the sluggable field anyway ++++++++++++++++++++ In your controllers (app/controllers)++++++++++++++++ You can do Model.find(slug) just how you would with a single numerical ID. It will also raise a RecordNotFound exception so you can handle that in your custom rescue_action_in_public action (more on that on http://www.estadobeta.com/2007/05/06/activerecordrecordnotfound/#comment-17669). The idea is that you keep your controller actions clean and handle Not Found errors elsewhere. You can still use Model.find the regular way. class PostsController < ApplicationController def show @post = Post.find( params[:post_slug] ) #raises ActiveRecord::RecordNotFound if not found end end INSTALLATION Download it to your Rails app as usual. .script/plugin install http://code.estadobeta.com/plugins/sluggable_finder Generate the migration to add the "slug" field to you model ("slug" is the default. You can use other field names). .script/generate migration AddSlugToBlogs class AddSlugToBlogs < ActiveRecord::Migration def self.up add_column :blogs, :slug, :string end def self.down remove_column :blogs, :slug end end #migrate it rake db:migrate # Use it as in the EXAMPLES part above. # Questions to Ismael at http://www.estadobeta.com