Как использовать jquery-Tokeninput и Acts-as-taggable-on - PullRequest
14 голосов
/ 13 июля 2011

Так вы можете использовать автозаполнение с 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, т.е. {"id":19,"name":"1"}. Вместо этого он должен найти идентификатор, показать имя и выполнить find_or_create_by, чтобы не создавать новый Tag.


Выпуск 2 (решено)


Когда я перехожу на products/show, чтобы увидеть теги, набрав <%= @product.tag_list %>. Название появляется как « Метки: 1 », когда оно действительно должно быть « Метки: Еда ».

Как я могу исправить эти проблемы?

Ответы [ 6 ]

4 голосов
/ 23 ноября 2011

небольшое дополнение:

Если вы хотите создавать теги на лету, вы можете сделать это в вашем контроллере:

 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:

noResultsText: 'No result, hit space to create a new tag',

Это немного грязно, но у меня работает.

4 голосов
/ 15 октября 2011

В коде 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
});
4 голосов
/ 18 июля 2011

Вы должны определить маршрут в вашем routes.rb, который должен обрабатывать products/tags путь. Вы можете определить это как:

get "products/tags" => "products#tags", :as => :tags

Таким образом, вы должны получить tags_path помощника, который должен оценить /products/tags. Это должно избавить от ошибок, которые вы упомянули в вопросе. Обязательно добавьте этот маршрут до определения resources :product в вашем routes.rb

Теперь на действует-как-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
1 голос
/ 20 октября 2013

Два примечания: если вы получаете теги, замененные числами в запросе POST, используйте:

tokenValue:        "name"

И если вы пытаетесь добавить несуществующие теги, используйте (недокументированное):

allowFreeTagging:  true
1 голос
/ 14 декабря 2011

У меня были проблемы с редактированием тегов, если, например, модель не прошла проверку,

Я изменил

<%= 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 %>

Если форма не прошла проверку при первой отправке, она создавала теги в качестве идентификаторов тегов, созданных при последующих отправках.

1 голос
/ 13 июля 2011

Я не знаю, является ли это всей вашей ошибкой, но вы не указали правильный URL с помощью плагина tokenInput.

Это

$("#product_tag_list").tokenInput("/products/tags.json"), {

должно быть

$("#product_tag_list").tokenInput("/products.json"), {

Как я уже сказал, я не знаю, является ли это единственной проблемой, с которой вы столкнулись, но если вы измените это, это сработает?

РЕДАКТИРОВАТЬ:

Я никогда не использовал ActsAsTaggableOn.Создает ли она модель Tag для использования?

Судя по всему на github , если вы хотите запросить все теги, вы можете иметьиспользовать его пространство имен, а не просто Tag, что означает ActsAsTaggableOn::Tag.Например, вы можете увидеть, как они обращаются к Tag s напрямую в некоторых из спецификаций .

...