This example refers to two classes of Ruby objects: regions and airports. Airports belong to regions, and regions can have many airports. The goal is to provide autocompletion of airport names and region names. We'll use Solr's facets and jQuery UI's autocomplete widget.

Setup

The setup below prepares Solr to perform a faceted search for Region objects using region names and their related Airport objects.

searchable do
  text :region_name
  integer :airport_ids, :multiple => true, :references => Airport do
    airport_coordinates.map(&:id)
  end
  string :pretty_region_names
end

Head over to jquery-ui and download what you need. Put the javascript files where .js files belong, put CSS files where .css files belong, etc.

Wherever your searchbar exists in a view, wrap it in a div with a class of "ui-widget". I use HAML:

.ui-widget 
  = form_tag find_location_path do 
    = text_field_tag :keywords, params[:keywords], placeholder: 'Choose Destination' 
    = submit_tag "Plan", class: 'submit'  

Here we should test the jquery-ui autocomplete widget by including the following javascript in the view from above:

$(document).ready(function(){ 
  $( "#keywords" ).autocomplete({ 
    source: ["apple", "art", "bees", "butter", "charlie", "cool", "delta", "dirac", "elephant", "egg beater", "foo", "foobar"], 
    minLength: 2 
  }); 
}); 

Now we should have autocomplete working, but the suggestions are pretty useless. Let's fix that by replacing the source with a remote function:

$(document).ready(function(){
  $( "#keywords" ).autocomplete({
    source: get_airports,
    minLength: 2
  });
});

function get_airports(request, response){
  var params = {keywords: request.term};
  $.get("/queries/json_completion", params, function(data){
    response(data);
  }, "json");
}

We're almost there, we just need to add a controller action and a route to connect that ajax request to our controller action. The route:

match '/queries/json_completion', to: 'queries#json_completion', as: 'json_completion'

And in the queries_controller:

def json_completion
  search = Sunspot.search(Region) do
    keywords(params["keywords"])
    facet :pretty_region_names
    facet :airport_ids
  end
  bucket = []
  bucket << search.facet(:pretty_region_names).rows.first(5).map{|x| x.value }
  bucket << "---------------------------------"
  bucket << search.facet(:airport_ids).rows.first(5).map{ |x| x.instance.airport_name }
  render :json => bucket.flatten
end

That's it! Good luck & have fun!

Tad Hosford is a recent addition to the isotope|eleven development team. He graduated from the UAB Electrical and Computer Engineering department in 2009. He says software development is a perfect fit for him because it offers endless opportunities to create and to find new solutions to interesting problems.