Подтвердить что ты не робот

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

Я установил 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 (http://loopj.com/jquery-tokeninput/) в мое приложение

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

4b9b3361

Ответ 1

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

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)")

Ответ 2

Я лично считаю, что оба решения будут медленными, если у вас есть много тэгов для извлечения, поскольку есть много отдельных операторов 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

Ответ 3

Используя модель 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-объект, который вы можете использовать

изменить

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