Как использовать jquery-Tokeninput и Acts-as-taggable-on
Так вы используете автозаполнение с jQuery Tokeninput и ActsAsTaggableOn.
В моей ситуации я использую вложенную форму, но это не имеет значения. Все ниже - это код, который работает.
код
Модель продукта:
attr_accessible :tag_list # i am using the regular :tag_list
acts_as_taggable_on :tags # Tagging products
Контроллер продуктов:
#1. Define the tags path
#2. Searches ActsAsTaggable::Tag Model look for :name in the created table.
#3. it finds the tags.json path and whats on my form.
#4. it is detecting the attribute which is :name for your tags.
def tags
@tags = ActsAsTaggableOn::Tag.where("tags.name LIKE ?", "%#{params[:q]}%")
respond_to do |format|
format.json { render :json => @tags.map{|t| {:id => t.name, :name => t.name }}}
end
end
Маршруты
# It has to find the tags.json or in my case /products/tags.json
get "products/tags" => "products#tags", :as => :tags
application.js:
$(function() {
$("#product_tags").tokenInput("/products/tags.json", {
prePopulate: $("#product_tags").data("pre"),
preventDuplicates: true,
noResultsText: "No results, needs to be created.",
animateDropdown: false
});
});
форма:
<%= p.text_field :tag_list,
:id => "product_tags",
"data-pre" => @product.tags.map(&:attributes).to_json %>
Проблема 1 (РЕШЕННАЯ)
Должна иметь строку:
format.json { render :json => @tags.collect{|t| {:id => t.name, :name => t.name }}}
Примечание. Здесь вы можете использовать @tags.map
, и вам также не нужно менять форму.
Ниже приведены 2 вопроса о том, почему вам нужно было сделать это:
У меня есть следующий Tag
: {"id":1,"name":"Food"}
. Когда я сохраняю Product
, помеченный тегом "Food"
, он должен сохранять как ID: 1
при поиске и поиске имени "Food"
. В настоящее время он сохраняет новый Tag
с новым идентификатором, который ссылается на идентификатор "Food"
, т.е. {"id":19,"name":"1"}
. Вместо этого нужно найти идентификатор, показать имя и сделать find_or_create_by
, чтобы он не создавал новый Tag
.
Проблема 2 (РЕШЕННАЯ)
Когда я перейду к products/show
, чтобы увидеть теги, выполнив <%= @product.tag_list %>
. Имя появляется как " Тэги: 1", когда это действительно должно быть " Tags: Food".
Как я могу исправить эти проблемы?
Ответы
Ответ 1
Вы должны определить маршрут в routes.rb
, который должен обрабатывать путь products/tags
. Вы можете определить его как:
get "products/tags" => "products#tags", :as => :tags
Таким образом, вам следует предоставить помощник tags_path
, который должен оцениваться как /products/tags
. Это должно избавиться от ошибок, которые вы упомянули в вопросе. Не забудьте добавить этот маршрут до определения resources :product
в routes.rb
Теперь на acts-as-taggable-on я не использовал этот камень, но вы должны посмотреть на метод all_tag_counts
. В вашем методе ProductsController#tags
понадобятся некоторые изменения в следующих строках. Я не уверен, что это именно то, что потребуется, поскольку я использую Mongoid и не могу проверить его.
def tags
@tags = Product.all_tag_counts.(:conditions => ["#{ActsAsTaggableOn::Tag.table_name}.name LIKE ?", "%#{params[:q]}%"])
respond_to do |format|
format.json { render :json => @tags.collect{|t| {:id => t.name, :name => t.name } }
end
end
Ответ 2
В коде Application.js есть ошибка. Существует дополнительный) после "/products/tags.json". Удалите лишние). Код должен быть:
$("#product_tags").tokenInput("/products/tags.json", {
prePopulate: $("#product_tags").data("pre"),
preventDuplicates: true,
noResultsText: "No results, needs to be created.",
animateDropdown: false
});
Ответ 3
небольшое дополнение:
Если вы хотите создавать теги "на лету", вы можете сделать это в своем контроллере:
def tags
query = params[:q]
if query[-1,1] == " "
query = query.gsub(" ", "")
Tag.find_or_create_by_name(query)
end
#Do the search in memory for better performance
@tags = ActsAsTaggableOn::Tag.all
@tags = @tags.select { |v| v.name =~ /#{query}/i }
respond_to do |format|
format.json{ render :json => @tags.map(&:attributes) }
end
end
Это создаст тэг, всякий раз, когда нажимается пробел.
Затем вы можете добавить этот параметр поиска в jquery script:
noResultsText: 'No result, hit space to create a new tag',
Это немного грязно, но это работает для меня.
Ответ 4
Я не знаю, является ли это всей вашей ошибкой, но вы не нажимаете правильный URL-адрес с помощью плагина tokenInput.
Это
$("#product_tag_list").tokenInput("/products/tags.json"), {
должен быть
$("#product_tag_list").tokenInput("/products.json"), {
Как я уже сказал, я не знаю, является ли это единственной проблемой, с которой вы сталкиваетесь, но если вы измените это, это сработает?
EDIT:
Я никогда не использовал ActsAsTaggableOn
. Создает ли он модель Tag
для вас?
Из взглядов на github, если вы хотите запросить все теги, вам, возможно, придется использовать свое пространство имен в отличие от просто Tag
, что означает ActsAsTaggableOn::Tag
. Например, вы можете увидеть, как они обращаются к Tag
непосредственно в некоторых спецификациях.
Ответ 5
У меня были проблемы с редактированием тегов, если, например, модель не смогла проверить,
Я изменил
<%= p.text_field :tag_list,
:id => "product_tags",
"data-pre" => @product.tags.map(&:attributes).to_json %>
к
<%= p.text_field :tag_list,
:id => "product_tags",
"data-pre" => @product.tag_list.map {|tag| {:id => tag, :name => tag } }.to_json %>
Если форма не прошла проверку при первом представлении, она создавала теги как идентификатор тегов, которые она создала при последующих представлениях.
Ответ 6
Две заметки: если вы получаете теги, измененные номерами в запросе POST, используйте:
tokenValue: "name"
И если вы пытаетесь добавить несуществующие теги, используйте (недокументированные):
allowFreeTagging: true