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