Как получить список всех тегов при использовании драгоценного камня «act-as-taggable-on» в Rails (а не в процентах)

17

Я установил acts-as-taggable-on gem в моей модели следующим образом:

 acts_as_taggable_on :deshanatags

Он использует контекст deshanatags . Теперь мне нужно получить список всех тегов (а не только те, которые были назначены для одного элемента. Мне нужно все) в этом контексте в следующем формате:

[
    {"id":"856","name":"House"},
    {"id":"1035","name":"Desperate Housewives"}
]

Как я могу это сделать?

Я старался следовать многим учебным пособиям, но попал в тупики, потому что большинство из них написано для Rails 3. Rails для некоторых изменений в модели, таких как удаление attr_accessor, затрудняет мне понимание этих обучающих программ. Поэтому, пожалуйста, помогите.

Просто я пытаюсь добавить вход в токен JQuery ( Ссылка ) к моему приложению

PS: Через таблицу тегов, есть ли способ получить список тегов, таких как вывод Tag.all, путем фильтрации контекста?

    
задан THpubs 28.03.2014 в 11:30
источник

3 ответа

35

Теги хранятся в таблице тегов, к которой вы получаете доступ из вашей программы, например,

ActsAsTaggableOn::Tag.all

Если вам нужна дополнительная информация об использовании тегов, есть также таблица

ActsAsTaggableOn::Tagging

, который содержит ссылки на то, где используется каждый тег, включая его контекст

Чтобы применить это к вашему примеру, вы можете использовать

ActsAsTaggableOn::Tagging.includes(:tag).where(context: 'deshanatags').map { |tagging| { 'id' => tagging.tag_id.to_s, 'name' => tagging.tag.name } }.uniq

Давайте объясним различные части этого утверждения:

  • «includes» гарантирует, что разные теги «загружены», другими словами, что вместо загрузки n + 1 записей в базе данных будет выполняться всего 2 запроса
  • 'where' ограничивает записи теми, у кого данный контекст
  • «map» преобразует результирующий массив записей в новый массив, содержащий хеши, о которых вы просили в своей проблеме, с идентификатором, сопоставленным с идентификатором тега, и именем, сопоставленным с именем тега
  • наконец, «uniq» гарантирует, что у вас нет двойников в вашем списке.

Чтобы справиться с дополнительной проблемой, будучи тегами без тега, вы можете расширить предложение where до

where("(context = 'deshanatags') AND (tag_id IS NOT NULL)")
    
ответ дан Danny 28.03.2014 в 11:45
источник
  • Есть ли способ получить только те, которые имеют контекст deshanatags? –  THpubs 28.03.2014 в 11:48
  • Через таблицу тегов, есть ли способ получить список тегов, таких как вывод Tag.all, путем фильтрации контекста? –  THpubs 29.03.2014 в 12:34
  • EAPubs - извините за поздний ответ. Некоторое время –  Danny 04.04.2014 в 17:58
  • Извините, у него также есть проблемы. В коде указано NoMethodError: undefined method name 'for nil: NilClass' –  THpubs 07.04.2014 в 17:23
  • Похоже, что ваша база данных «повреждена», с метками, не имеющими тега ... Я предлагаю очистить их, так как нет никакого смысла, чтобы они зависали ... Альтернатива в том, что вы явно игнорируете их в своем запрос, но это приводит к «уродливому коду» ... См. последнюю строку, добавленную в решение! –  Danny 07.04.2014 в 19:23
Показать остальные комментарии
4

Я лично считаю, что оба решения будут медленными, если у вас есть много тэгов для извлечения, поскольку есть много отдельных операторов select. Я бы сделал это следующим образом:

ActsAsTaggableOn::Tagging.includes(:tag).where(context: 'deshanatags').uniq.pluck(:id, :name)

Если вы на рубине 1.9 +

Таким образом, вы просто закончите:

SELECT DISTINCT "taggings"."id", name FROM "taggings" LEFT OUTER JOIN "tags" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."context" = 'deshanatags'

Быстрое и легкое imo

    
ответ дан Fabio Russo 12.08.2014 в 11:46
источник
2

Используя модель ActsAsTaggableOn::Tagging , вы можете получить список всех тегов и отфильтровать их в соответствии с контекстом, а затем отформатировать их следующим образом:

ActsAsTaggableOn::Tagging.all
.where(context: "deshanatags")
.map {|tagging| { "id" => "#{tagging.tag.id}", "name" => tagging.tag.name } }

where даст нам результат всех тегов для заданного контекста, который затем перебираем с использованием map , извлекаем связанный тег для каждого тега в нашем результате и получаем атрибуты id и name.

Обязательно привяжите методы напрямую (не к нескольким строкам), если вы не используете ruby ​​1.9 +

Затем вы можете вызвать .to_json на результат, чтобы получить правильно отформатированный json-объект, который вы можете использовать

изменить

Я обновил сообщение, чтобы уточнить, что делает каждый оператор, а также обновил формат нашего окончательного результата, чтобы использовать строки как ключи вместо символов

    
ответ дан fabianfetik 01.04.2014 в 10:21
источник
  • Не работает ... Записи, которые я получаю от ActsAsTaggableOn :: Tagging.all.where (context: "deshanatags"), все это похоже на # # ActsAsTaggableOn :: Tagging id: 35, tag_id: 23, taggable_id: 1, taggable_type: «Deshana», tagger_id: nil, tagger_type: nil, context: "deshanatags", created_at: "2014-04-03 05:44:08">] ' –  THpubs 03.04.2014 в 07:45
  • Да, это правильно. Вам понадобится также часть .map, чтобы получить требуемую информацию. –  fabianfetik 03.04.2014 в 10:12
  • Это дает мне эту ошибку: NoMethodError: undefined method id 'for nil: NilClass' –  THpubs 07.04.2014 в 17:24