Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
510 views
in Technique[技术] by (71.8m points)

ruby on rails - How to use jquery-Tokeninput and Acts-as-taggable-on

This is how you use autocomplete with jQuery Tokeninput and ActsAsTaggableOn.

In my situation i am using a nested form but it shouldnt matter. Everything below is code that works.

Code

Product Model:

attr_accessible :tag_list # i am using the regular :tag_list
acts_as_taggable_on :tags # Tagging products

Products Controller:

  #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

Routes:

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

Form:

<%= p.text_field :tag_list,
                 :id => "product_tags",
                 "data-pre" => @product.tags.map(&:attributes).to_json %>

Issue 1(SOLVED)


Must have the line:

format.json { render :json => @tags.collect{|t| {:id => t.name, :name => t.name }}}

Note - You can use @tags.map here as well and you dont have to change the form either.

Below are the 2 issues on why you needed to do this:

I have the following Tag: {"id":1,"name":"Food"}. When I save a Product, tagged "Food", it should save as ID: 1 when it searches and finds the name "Food". Currently, it saves a new Tag with a new ID that references the "Food" ID, i.e. {"id":19,"name":"1"}. Instead, it should be finding the ID, showing the name, and doing a find_or_create_by so it doesn't create a new Tag.


Issue 2(SOLVED)


When I go to products/show to see the tags by doing <%= @product.tag_list %>. The name appears as "Tags: 1", when it really should be "Tags: Food".

How can I fix these issues?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You should define a route in your routes.rb which should handle products/tags path. You can define it like:

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

Thus should give you a tags_path helper which should evaluate to /products/tags. This should get rid of the errors you mentioned in the question. Be sure to add this route before defining resources :product in your routes.rb

Now onto acts-as-taggable-on, I haven't used this gem, but you should look at method all_tag_counts documentation. Your ProductsController#tags method will need some changes on the following lines. I am not sure if its exactly what would be required, as I use Mongoid and can't test it out.

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...