Как создать удобные маршруты для тегов

У меня есть изображение модели:

class Image < ActiveRecord::Base
  attr_accessible :description, :name, :size, :image, :tag_ids

  has_many :taggings, :dependent => :destroy
  has_many :tags, :through => :taggings
end

Тогда у меня есть моя модель тега:

class Tag < ActiveRecord::Base
  attr_accessible :name
  has_many :taggings, :dependent => :destroy
  has_many :images, :through => :taggings

end

Мои маршруты.rb в настоящее время:

resources :images do
    get 'confirm_destroy', :on => :member
end
resources :tags

Теперь предположим, что я создал несколько тегов «синий», «красный» и «желтый» для изображений. На какой-то странице я хочу показать список тегов, а затем связать их, например. www.example.com/yellow, где будут показаны все изображения, помеченные желтым цветом. Представление (haml) для этого списка тегов в настоящее время:

- @tags.each do |tag|
  = link_to(tag.name, tag)

Но он генерирует ссылку на www.example.com/tags/2 (где 2 — это tag_id).

Как я могу создать правильные ресурсы, чтобы ссылаться на www.example.com/yellow вместо www.example.com/tags/2. Будет ли в этом случае вид с «link_to» таким же?


person user929062    schedule 09.09.2012    source источник


Ответы (2)


Вы не сможете создать маршрут к www.example.com/yellow, потому что он не ссылается на конкретный ресурс и впоследствии может привести к конфликтам. Представьте, если бы у вас был тег с именем «images», Rails не знал бы, относится ли URL-адрес www.example.com/images к определенному тегу или ресурсу изображений.

Лучшее, что мы можем сделать, это создать ресурс, который использует имя в качестве идентификатора в URL-адресе, чтобы www.example.com/tags/yellow отображал тег с 'желтым' в качестве атрибута имени. .

Для этого вам необходимо определить следующий метод to_param в модели для тега.

class Tag < ActiveRecord::Base
  attr_accessible :name
  has_many :taggings, :dependent => :destroy
  has_many :images, :through => :taggings

    def to_param
        name
    end
end

Это укажет Rails использовать атрибут name для маршрутизации вместо id по умолчанию. Ваш link_to не нужно будет обновлять, однако ваш контроллер тегов теперь должен будет найти тег по имени, а не по идентификатору, например:

class TagsController < ApplicationController

    def show
        @tag = Tag.find_by_name(params[:id])
    end

    ...

end
person DNJohnson    schedule 09.09.2012
comment
Спасибо. Это просто, но приводит к URL-адресу www.example.com/tags/yellow. Могу ли я избавиться от /tags/ части URL-адреса? Или, что еще лучше, замените /tags, например. /images или любое другое имя, которое я выбрал? Таким образом, идеальным URL будет www.example.com/images/yellow. - person user929062; 09.09.2012
comment
Я только что заметил небольшую разницу в вашем запросе. Я обновил свой ответ, чтобы отразить, почему это невозможно сделать. Вы также не сможете заменить '/tags' на '/images', потому что это снова создаст конфликт внутри Rails, и он не будет знать, к какому ресурсу маршрутизировать (изображения или теги). - person DNJohnson; 09.09.2012
comment
С другой стороны, вы можете использовать совершенно другое ключевое слово (не используемое другими ресурсами), добавив следующее в конфигурацию маршрутов: match '/ Different/:id' => 'tags#show' - person DNJohnson; 09.09.2012

Вы можете сделать это с помощью метода to_param в своей модели или с помощью драгоценного камня friendly_id. У Райана Бейтса есть отличный скринкаст об этом http://railscasts.com/episodes/314-pretty-urls-with-friendlyid

person Nick Kugaevsky    schedule 09.09.2012
comment
Да, хороший скринкаст и полезный плагин. В любом случае, пока я использую to_params, так как этого достаточно для моих целей. - person user929062; 10.09.2012