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?
I had problems with editing the tags if for example the model failed to validate,
I changed
to
If the form failed to validate on first submission, it was creating tags as the ID's of the tags it had created on subsequent submissions.
Two notes: if you're getting the tags changed by numbers on the POST request, use:
And if you're trying to add non-existent tags, use (undocumented):
I don't know if this is the entirety of your error, but you are not hitting the proper URL with the tokenInput plugin.
This
should be
As I said, I don't know if this is the only problem you are having, but if you change this, does it work?
EDIT:
I have never used
ActsAsTaggableOn
. Does it create aTag
model for you to use?From the looks of it on github, if you wanted to query all tags, you might have to use its namespace as opposed to just
Tag
, meaningActsAsTaggableOn::Tag
. For example, you can see how they accessTag
s directly in some of the specs.You should define a route in your
routes.rb
which should handleproducts/tags
path. You can define it like: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 definingresources :product
in yourroutes.rb
Now onto acts-as-taggable-on, I haven't used this gem, but you should look at method
all_tag_counts
documentation. YourProductsController#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.little add-on:
If you want to create the tags on the fly, you could do this in your controller:
This will create the tag, whenever the space bar is hit.
You could then add this search setting in the jquery script:
It's a little dirty but it works for me.
There is a bug in Application.js code. There is an extra ) after "/products/tags.json". Remove the extra ). The code should be: