Even better looking URLs with permalink_fu
Extracted from Mephisto is the handy plugin called permalink_fu. This plugin allows you to use ID-less permalinks, much like that in this blog.
I wrote earlier about how to use to_param for nicer URLs, but these are even better. The plugin automatically turns a field in your model into something that could be a permalink, by stripping out all non english and non alphanumeric letters. It then saves this in a field in your database for future use.
So, onto the HowTo:
First, install the plugin in your rails app.
./script/plugin install http://svn.techno-weenie.net/projects/plugins/permalink_fu/ |
Now you need to add a field to your database to store the permalink.
./script/generate migration add_permalink_to_article |
In the migration we add the field called permalink.
add_column :designers, :permalink, :string |
1 2 3 4 5 6 7 8 9 10 11 |
class Article < ActiveRecord::Base # title is the field name you want to convert to a permalink has_permalink :title # you can also specifiy a different permalink field in your database by giving a second paramater # has_permalink :title, :my_permalink_field # we now add the to_param method which Rails's routing uses def to_param permalink end end |
The permalink field is only populated after the record is validated, so if you have a bunch of records already in your database you can get the permalink field to populate with
Article.find(:all).each(&:save) |
@article = Article.find_by_permalink(params[:id]) |
However that doesn’t seem to pass the smell test using :id rather than :permalink, but will work fine. To use :permalink you will have to change your routing code and your view code :
1 2 3 4 5 6 |
# in your route file map.connect 'article/:permalink', :controller => 'article', :action => 'view' # in your views when linking link_to "View #{article.title}", {:controller => 'designer', :action => 'view', :permalink => article.permalink} # then in your controller you can use @article = Article.find_by_permalink(params[:permalink]) |
Thats all! I’m always on the lookout for SEO related Rails topics to talk about so drop me a line @ questions at this domain .com.
Like this article? Subscribe to the SEO on Rails feed.
Comments
-
Hi, Eadz, Great tutorial, thanks for sharing. I have a question of deleting an article. The "article" has a many-to-many relation to the "category": @article = Article.find_by_permalink(params[:id]) if @article @article.destroy end I got the error message like: `destroy_without_habtm_shim_for_categories' Can you please tell me where it goes wrong? Thank you, Alex
-
Hello, I found the above plugin useful. But what if you have two articles by the same title. Would it be better to put an id in the permalink or test if the permalink exists then put a suffix. thanks,
-
Hi! Alex - this seems to be a known rails bug - http://dev.rubyonrails.org/ticket/4386 search_guru - originaly in this article I had a validates_uniqueness_of :permalink, but becasue of the way permalink_fu works - it hooks into the before_validation callback - this uniqueness validation didn't work. But I think the idea would be to enforce unique titles and permalinks in the model ( which requires some hacking to permalink_fu ). Failing that, you could check to see if it exists and then as you suggest ad a suffix like '2'
-
Great tutorial... Rock over London, Rock on Chicago.
-
Designer is a new controller? Give me one example of URL for this. I need help. Thanks
-
wouldn't it be possible to do like this instead of "has_permalink": class Category < ActiveRecord::Base def before_validation self.permalink = PermalinkFu.escape(self.title) end end and then use: validates_uniqueness_of :permalink
