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

Я установил acts-as-taggable-on драгоценный камень в моей модели, как это:

 acts_as_taggable_on :deshanatags

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

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

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

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

Я просто пытаюсь добавить входные данные токена Jquery ( http://loopj.com/jquery-tokeninput/) в мое приложение.

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

3 ответа

Решение

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

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

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

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

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

where("(context = 'deshanatags') AND (tag_id IS NOT NULL)")

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

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

Если вы на ruby ​​1.9+

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

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

Быстрый и легкий ИМО

С использованием 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, который вы можете использовать

редактировать:

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

В более поздних версиях вы можете использовать:

ActsAsTaggableOn::Tag.for_context(:deshanatags)

Я попал сюда из Google, но потом нашел ответ в вики.

Из вики

Из кода

Другие вопросы по тегам