Search code examples
ruby-on-rails-3.2jquery-tokeninput

Using jQuery Tokeninput with a self-referential association in Rails 3


I'm trying to set up a search-as-you-type form with Tokeninput, with help from Ryan Bates' Railscast. Unfortunately, I'm having trouble figuring it out with a self-referential association.

In my models:

class Skill < ActiveRecord::Base
  attr_accessible :skill_relationship_attributes, :prereq_tokens
  attr_reader :prereq_tokens

  has_many :skill_relationships
  has_many :prereqs, :through => :skill_relationships
  has_many :inverse_skill_relationships, :class_name => 'SkillRelationship', :foreign_key => "prereq_id"
  has_many :inverse_prereqs, :through => :inverse_skill_relationships, :source => :skill

  accepts_nested_attributes_for :skill_relationships, :allow_destroy => true

  def prereq_tokens=(ids)
    self.prereq_ids = ids.split(",")
  end
end

class SkillRelationship < ActiveRecord::Base
  attr_accessible :skill_id, :prereq_id, :skill_attributes, :prereq_attributes

  belongs_to :skill
  belongs_to :prereq, :class_name => 'Skill'
end

And I feebly put together a form:

<%= form_for skill do |f| %> 
  <%= f.label :prereq_tokens, "Prerequisites" %><br/>
  <%= f.text_field :prereq_tokens, data: {load: Skill.all} %>       
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

I do get a nicely styled text field, but it doesn't find anything when it searches and I'm not really sure where to go from here. Any ideas?


Solution

  • I figured this one out! First, I removed "data: {load: Skill.all}" from the form, because I wanted it to work through thinking_sphinx rather than my entire database. Then - and here was the key - I specified propertyToSearch and queryParam in my coffeescript:

    jQuery ->
      $('#skill_prereq_tokens').tokenInput '/skills.json'
        theme: 'facebook'
        propertyToSearch: 'title' // :title is the attribute in my Skill model that I want to show up in the list
        queryParam: 'search' // :search is the parameter that gets passed to thinking_sphinx
    

    And voila! It turned out to be more a thinking_sphinx issue than anything to do with my self-referential associations.

    It's important to note that specifying the title attribute with propertyToSearch only determines which attribute gets to represent each skill and does not prevent thinking_sphinx from using other attributes from its index.

    It doesn't work exactly like a Facebook input field though, since thinking_sphinx by default only does whole-word search. In other words, if I'm looking for a skill called "Boxing" and I type in "box" or even "boxin", I'll get nothing. Only when I finally type in the full word boxing "boxing" will the skill be returned in the list. It's possible to configure thinking_sphinx to index prefixes, so that it'll return results from partial words, like Facebook does - but if you're indexing a large database, you probably don't want to do that, because your index will blow up crazy fast. That's probably a significant part of the reason why Facebook caps everyone at 5000 friends, apart from the fact that no one has 5000 friends.