How to use jquery tokeninput in Rails?
Asked Answered
J

2

6

I'm trying to add a tokeninput jquery field in a form in my app that allows users to post status updates. I want users to be able to attach works (a separate model) to the status update. I'm using the act_as_taggable_on gem and my query specifies the tags context "works". However, the field will not load any search results.

I actually have a second tokeninput field that allows users to attach tags to the status update, much like this website uses tags to attach to this issue ticket. It works fine! I'm trying to mirror that functionality to specify the context to search the works model and I'm struggling with the implementation.

Any ideas? Your time and assistance would be greatly appreciated! Here is the relevant code:

post model

attr_accessible :content, :tag_list, :work_list

acts_as_taggable_on :tags
acts_as_taggable_on :works

Post controller (updated)

def work_list
 query = params[:q]  
 @work_list = ActsAsTaggableOn::Tag.includes(:taggings).where("taggings.context = 'works'").where("tags.name ILIKE ?", "%#{params[:q].downcase.to_s}%").all
 @work_list = @work_list.select { |v| v.name =~ /#{query}/i }
  respond_to do |format|
    format.json { render :json => @work_list.map{|w| {:id => w.name, :name => w.name }}}
  end
end


def tags 
    query = params[:q]
    if query[-1,1] == " "
      query = query.gsub(" ", "")
      ActsAsTaggableOn::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{|t| {:id => t.name, :name => t.name }}}
    end
  end

form

<%= f.text_field :tag_list, :id => "post_work_list",  "data-pre" => @post.work_list.map(&:attributes).to_json %>

javascript

$ ->
  $("#post_tags").tokenInput "/posts/tags.json",
    prePopulate: $("#post_tags").data("pre")
    preventDuplicates: true
    noResultsText: "No results, press space key to create a new tag."
    animateDropdown: false

$ ->
  $("#post_work_list").tokenInput "/posts/work_list.json",
    prePopulate: $("#post_work_list").data("pre")
    preventDuplicates: true
    noResultsText: "No results"
    animateDropdown: false

routes

get "posts/tags" => "posts#tags", :as => :tags
get "posts/work_list" => "posts#work_list", :as => :work_list

Thanks!

EDIT: I cleaned up this question and the updated all of the code. I also started a conversation on enginhere.com which also has some other troubleshooting from other engineers:

http://bit.ly/179kiqH

Feel free to help by continuing the conversation on the above enginhere.com conversation and then posting the final, official answer here for the bounty!

Thanks again!

Jacquelynejacquelynn answered 16/8, 2013 at 11:22 Comment(0)
I
3

Amazing post answers to any questions by this topic!

http://bloginius.com/blog/2013/12/31/how-integrate-acts-as-taggable-on-with-jquery-token-input-with-rails-3/

Implode answered 9/1, 2014 at 8:16 Comment(1)
Note that link-only answers are discouraged, SO answers should be the end-point of a search for a solution (vs. yet another stopover of references, which tend to get stale over time). Please consider adding a stand-alone synopsis here, keeping the link as a reference.Nubianubian
I
2

If you are using acts_as_taggable_on gem it's easier way than in railscast.

Model (Post):

acts_as_taggable_on :works

View (form):

= f.text_field :work_list, "data-pre" => f.object.work_list.sort.collect {|t| {id: t, name: t } }.to_json

JS:

$ ->
  $("#post_work_list").tokenInput "/posts/works.json",
    preventDuplicates: true,
    animateDropdown: false
Implode answered 16/8, 2013 at 20:36 Comment(18)
Thanks for the reply! I couldn't get this to work but this got me thinking: why not just use the acts_as_taggable_on gem for works like I'm using for tags? I mirrored the code I'm using for tags but the works field still won't work. I'm getting closer though! The javascript loads but I get a 500 error when I type anything in the field. Updated question. Any ideas? Thanks!!!Jacquelynejacquelynn
What about error description in server log in console? Catch errors in #works method.Implode
Started GET "/posts/works.json?q=op" Processing by PostsController#works as JSON Parameters: {"q"=>"op"} NameError (uninitialized constant ActsAsTaggableOn::Work): Completed 500 Internal Server Error in 1ms app/controllers/posts_controller.rb:28:in `works'Jacquelynejacquelynn
Updated question so you can see the formatted error. Thanks again for the help so far!!Jacquelynejacquelynn
When you define "acts_as_taggable_on :works" it means that you will use ActsAsTaggableOn::Tag model with context "works". So try to change your query to ActsAsTaggableOn::Tag.includes(:taggings).where("taggings.context = 'works'").where("tags.name ILIKE ?", "%#{params[:q].downcase.to_s}%")Implode
Changed it to what you posted above and I think I'm getting closer. The javascript returned "No results" so it actually completed the search (no errors in the console). I think it's because I didn't create any works after I added Works to the acts_as_taggable_on. However, I then noticed that after I tried to create a new work I got a routing error: No route matches [POST] "/posts/works". How do I fix the routes.db so that I can create new works AND add new works as tags to a Post? Thanks!!!Jacquelynejacquelynn
Updated question. Creating new works and tagging works to a post seem to take the same route URL. How can I fix this? Thank you so much Ex. I'm getting close to finally getting this fixed!!Jacquelynejacquelynn
You should delete from Post model any associations for works and leave only acts_as_taggable_on :works. If you want to add new work-tags you can add options to your tokenInput definition "allowCustomEntry: true". Look here github.com/mbleigh/acts-as-taggable-on#usage good documentation for usage gem.Implode
Take tokenInput from here github.com/kusmierz/jquery-tokeninput to work what I wrote.Implode
I commented out the "has_many:works" from the Post model and I still had the same issue. I then tried to comment out get "posts/works" => "posts#works", :as => :works from routes but then the javascript shows a 500 error again. The error log shows Processing by PostsController#show as JSON Parameters: {"q"=>"test", "id"=>"works"} ActiveRecord::RecordNotFound (Couldn't find Post with id=works)Jacquelynejacquelynn
This leads me to think that I may need to tweak the query in the Post controller.Jacquelynejacquelynn
get "posts/works" => "posts#works", :as => :works - will return tags by query for you. New tags should be created in posts#update (path for form action).Implode
Updated question. I added a new route so that I can query tags and so it won't clash with creating new works. Can you help me with my form? I think that's the last thing I need to fix. Don't get any search results but it may be because I have an error in the form field. I don't get any javascript errors.Jacquelynejacquelynn
Yes, can I look closer your code? May be on github? Or drop it to me somehow. It's hard to help in comments.Implode
I updated the code in the question. Is there other code I can add on this page for you? It's a private repo so I can't give read only access. Are there other alternatives?Jacquelynejacquelynn
Another option is a Google Hangouts session so we can review it together. I can pay for your time.Jacquelynejacquelynn
[email protected] or skype: ivan_teplyakov. Not need to pay, it's interesting to me :)Implode
Add me to contact list to gtalk or skype. Lets contact when I will online. GMT+4Implode

© 2022 - 2024 — McMap. All rights reserved.