Ismael Celis (http://www.estadobeta.com)
This is a variation of acts_as_slugable, acts_as_permalink and whiny_finders.
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
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
In your routes (config/routes.rb)
map.post ‘posts/:post_slug’
In your controllers (app/controllers)
You can do Model.find_sluggable( param ) just like Model.find( 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 in Spanish for now).
The idea is that you keep your controller actions clean and handle Not Found errors elsewhere.
class PostsController < ApplicationController
def show
@post = Post.find_sluggable( 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 itUse it as in the EXAMPLES part above.
Questions to Ismael at http://www.estadobeta.com