Создание URL-слагов для тегов с act_as_taggable_on - PullRequest
8 голосов
/ 13 февраля 2011

Я хотел бы создать URL-слагы для тегов, управляемых гемом act_as_taggable_on. Например, вместо URL, таких как http://myapp.com/tags/5,, я хотел бы иметь http://myapp.com/tags/my-tag (где «мой тег» - это уникальное имя тега).

В моделях, которые я создаю сам, я обычно делаю это, переопределяя метод to_param модели и создавая поле "slug" в модели, чтобы сохранить результат нового метода to_param. Я пытался сделать это с моделью тегов ActsAsTaggableOn, но она не работает.

В противном случае я могу переопределить вещи в классе tag.rb ActsAsTaggableOn следующим образом:

# Overwrite tag class
ActsAsTaggableOn::Tag.class_eval do
  def name
    n = read_attribute(:name).split
    n.each {|word| word.capitalize!}.join(" ")
  end      
end

Однако, если я попытаюсь переопределить метод to_param в этом же блоке с помощью определения метода, например:

def to_param
  name.parameterize
end

Rails по-прежнему генерирует и отвечает на маршруты с целочисленными идентификаторами, а не с параметризованным именем. На самом деле в консоли, если я попробую что-то вроде

ActsAsTaggableOn::Tag.find(1).to_param

Возвращается целочисленный идентификатор, а не результат переопределенного метода to_param.

Я бы предпочел не разветвлять гем и не настраивать его, если есть какой-то способ сделать это с помощью собственного кода приложения. Благодаря.

Ответы [ 5 ]

14 голосов
/ 14 мая 2012

@ vitork-код - хорошее начало, но он не работает для более новых версий friendly_id и acts_as_taggable. Вот обновленный инициализатор:

ActsAsTaggableOn::Tag.class_eval do
extend FriendlyId
friendly_id :name,
              :use => :slugged,
              :slug_column => :permalink,
              :reserved_words => ['show', 'edit', 'create', 'update', 'destroy']
end

Мой столбец базы данных называется Постоянная ссылка , вы можете использовать slugged , если хотите. Кстати, я использую следующее:

  • friendly_id (4.0.5)
  • действует как помеченный как (2.2.2)

Спасибо Виторку за начальный код!

13 голосов
/ 13 мая 2011

Я использую гем friendly_id (https://github.com/norman/friendly_id) для управления слагом. Мой метод создания слагов для моих тегов похож на ваш, но чуть проще.

Я только что создал инициализатор act_as_taggable_on.rb со следующим кодом:

# act_as_taggable_on.rb
ActsAsTaggableOn::Tag.class_eval do
  has_friendly_id :name,
                  :use_slug => true,
                  :approximate_ascii => true,
                  :reserved_words => ['show', 'edit', 'create', 'update', 'destroy']
end

А потом:

@user = User.new :name => "Jamie Forrest"
@user.tag_list = "This is awesome!, I'm a ruby programmer"
@user.save

И вуаля:

ActsAsTaggableOn::Tag.find('this-is-awesome')    #=> #<Tag id: 1, name: "This is awesome!">
ActsAsTaggableOn::Tag.find('im-a-ruby-programmer')    #=> #<Tag id: 2, name: "I'm a ruby programmer">

Надеюсь, эта помощь ...

9 голосов
/ 19 октября 2012

На самом деле ответ намного проще, и вам не нужно использовать friendly_id или любое другое ненужное расширение.

сonfig / Инициализаторы / act_as_taggable_on.rb

ActsAsTaggableOn::Tag.class_eval do
  before_save { |tag| tag.slug = name.parameterize if name_changed? }

  def to_param
    slug
  end
end

При необходимости добавьте столбец слагов, иначе пропустите обратный вызов before_save.

Тогда в представлении вместо итерации, как

article.tag_list.each do |tag|..

вы будете повторять вот так

article.tags.each

потому что tag_list дает вам только строки, тогда как с тегами у вас есть реальные экземпляры тегов. И хотя бы в контроллере

if params[:tag]
   tag = ActsAsTaggableOn::Tag.find_by_slug(params[:tag])
   @articles = Article.moderated.includes(:user).tagged_with(tag)
end
8 голосов
/ 13 апреля 2014

Чтобы это работало с последней версией (Rails 4.x, friendly_id 5.x), выполните следующие шаги:

Создание миграции для добавления пула в таблицу тегов

# rails generate migration add_slugs_to_tags
class AddSlugToTags < ActiveRecord::Migration
  def change
    add_column :tags, :slug, :string
    add_index :tags, :slug
  end
end

Вы можете переименовать столбец: slug - вы должны указать имя столбца в инициализаторе, если вы его измените. Не забудьте запустить миграцию rake db:migrate.

Создание инициализатора для ActsAsTaggableOn

# config/initializers/acts_as_taggable_on.rb
ActsAsTaggableOn::Tag.class_eval do
  extend FriendlyId

  friendly_id :name, use: :slugged
end

При поиске по тегам вы должны использовать ActsAsTaggableOn::Tag.friendly.find 'tag-name' или добавить :finders к friendly_id: используйте call для использования поиска непосредственно в модели. Подробнее читайте в friendly_id guides .

1 голос
/ 10 ноября 2016

Есть другой способ.

Создание контроллера для тегов с одним действием:

rails g controller tags index

В rout.rb изменить сгенерированный маршрут на:

get 'tags/:tag' => 'tags#index', as: :tag

В tags_controller.rb добавить этот код:

def index
    @tag = params[:tag]
    @entries = Entry.tagged_with(@tag)
end

где Entry - название модели.

Теперь вы можете получить все записи с хорошими URL, как example.com / tags / animals


Использование в представлениях:

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