How to create user freindly routes for tagging
I have a model Image:
class Image < ActiveRecord::Base attr_accessible :description, :name, :size, :image, :tag_ids has_many :taggings, :dependent => :destroy has_many :tags, :through => :taggings end
Then I have my Tag model:
class Tag < ActiveRecord::Base attr_accessible :name has_many :taggings, :dependent => :destroy has_many :images, :through => :taggings end
My routes.rb is currently:
resources :images do get 'confirm_destroy', :on => :member end resources :tags
Now let's say I created a few tags "blue", "red" and "yellow" for the images. On some page I want to show a list of tags and then link them to e.g. www.example.com/yellow where all the images tagged as yellow shall be shown. The view (haml) for this tag list is currently:
- @tags.each do |tag| = link_to(tag.name, tag)
But it generates a link to www.example.com/tags/2 (with 2 being the tag_id).
How can I create the correct resources in order to link to www.example.com/yellow instead of www.example.com/tags/2. Will the view with "link_to" be the same in this case?
You won't be able to create a route to www.example.com/yellow because this doesn't reference a specific resource, and subsequently could create conflicts. Imagine if you had a tag called 'images', Rails wouldn't know if the url to www.example.com/images referred to a specific tag, or the images resource.
The best we can do is create a resource which uses the name as the identifier in the URL, such that www.example.com/tags/yellow would show the tag with 'yellow' as its name attribute.
To do this, you need to define the following to_param method in the model for Tag.
class Tag < ActiveRecord::Base attr_accessible :name has_many :taggings, :dependent => :destroy has_many :images, :through => :taggings def to_param name end end
This will tell Rails to use the name attribute for routing instead of the default id. Your link_to won't need to be updated, however, your Tag controller will need to now find the Tag by name as opposed to ID, like so:
class TagsController < ApplicationController def show @tag = Tag.find_by_name(params[:id]) end ... end
You can do this with to_param method in your model or with friendly_id gem. Ryan Bates has perfect screencast about this http://railscasts.com/episodes/314-pretty-urls-with-friendlyid