如何使用jquery-Tokeninput和Acts-as-taggable-on

时间:2011-07-13 04:34:10

标签: ruby-on-rails ruby ruby-on-rails-3 autocomplete acts-as-taggable-on

这是您使用jQuery TokeninputActsAsTaggableOn自动填充功能的方法。

在我的情况下,我使用的是嵌套表格但不重要。以下所有内容都是有效的代码。

代码

产品型号:

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,也无需更改表单。

以下是您需要执行此操作的两个问题:

我有以下Tag{"id":1,"name":"Food"}。当我保存标记为Product的{​​{1}}时,它应在搜索时保存为"Food"并找到名称ID: 1。目前,它会使用引用"Food" ID的新ID(即Tag)保存新的"Food"。相反,它应该是找到ID,显示名称,然后执行{"id":19,"name":"1"},这样就不会创建新的find_or_create_by


第2期(已解决)


当我通过Tag转到products/show看标签时。该名称显示为“标签:1 ”,当它真的应该是“标签:食物”时。

如何解决这些问题?

6 个答案:

答案 0 :(得分:4)

您应该在routes.rb中定义一条应该处理products/tags路径的路线。您可以将其定义为:

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

因此应该给你一个tags_path帮助器,它应该评估为/products/tags。这应该摆脱你在问题中提到的错误。在resources :product

中定义routes.rb之前,请务必添加此路线

现在进入acts-as-taggable-on,我没有使用过这个gem,但你应该看一下方法all_tag_counts documentation。您的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 :(得分:4)

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
});

答案 2 :(得分:4)

小插件:

如果您想动态创建标签,可以在控制器中执行此操作:

 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',

它有点脏,但对我有用。

答案 3 :(得分:1)

我不知道这是否是您的错误的全部内容,但您没有使用tokenInput插件访问正确的URL。

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

应该是

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

正如我所说,我不知道这是否是您遇到的唯一问题,但如果您更改此问题,是否有效?

编辑:

我从未使用ActsAsTaggableOn。它是否为您创建Tag模型?

github上的外观来看,如果您想查询所有标记,则可能必须使用其命名空间而不仅仅是Tag,这意味着{{ 1}}。例如,您可以看到他们如何直接访问某些the specs中的ActsAsTaggableOn::Tag

答案 4 :(得分:1)

如果模型无法验证,我在编辑标签方面遇到了问题,

我改变了

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

如果表单在首次提交时未能验证,则表示正在创建标签,作为其在后续提交时创建的标签的ID。

答案 5 :(得分:1)

两个注意事项:如果您在POST请求中使用数字更改了标签,请使用:

tokenValue:        "name"

如果您尝试添加不存在的标签,请使用(未记录的):

allowFreeTagging:  true