0

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?

user929062
  • 807
  • 4
  • 12
  • 33

2 Answers2

1

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

Nick Kugaevsky
  • 2,935
  • 1
  • 18
  • 22
  • Yes, good screencast and useful plugin. Anyhow, for now I go with to_params since it is sufficient for my purposes. – user929062 Sep 10 '12 at 09:00
1

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
DNJohnson
  • 776
  • 5
  • 11
  • Thanks. This is easy, but leads to the url www.example.com/tags/yellow. Can I get rid of the "/tags/" part of the url? Or even better substitute "/tags" with e.g. "/images" or any other name I chose? So, the ideal url would be www.example.com/images/yellow. – user929062 Sep 09 '12 at 12:08
  • I just noticed that slight difference in your request. I've updated my answer to reflect why this can't be done. You also wouldn't be able to replace '/tags' with '/images' because that would again create a conflict within Rails and it wouldn't know which Resource to route to (Images or Tags). – DNJohnson Sep 09 '12 at 12:18
  • 1
    On the other hand, you could use a completely different keyword (unused by other resources) by adding the following to your routes config: match '/different/:id' => 'tags#show' – DNJohnson Sep 09 '12 at 12:21