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