I have set up my application with the searchkick gem and am working on the autocomplete feature for my Presenters index. My problem is that I am searching on multiple fields (first_name and last_name), and while I can search for a presenter by both fields - for example, if I have Presenter 'Jennifer Hall', I can type either 'Jennifer' or 'Hall' and the name 'Jennifer Hall' will appear in the autocomplete drop down, but if I type 'Jennifer ' (once I add the space), the name disappears and there are no more suggestions. My question is how can I fix this?
My Code
I have followed this tutorial: Adding search and autocomplete to a Rails app with Elasticsearch
presenter.rb:
class Presenter < ActiveRecord::Base
searchkick autocomplete: ['first_name', 'last_name'],
suggest: ['first_name', 'last_name']
...
end
presenters_controller.rb:
class PresentersController < ApplicationController
def index
if params[:query].present?
@presenters = Presenter.search(params[:query],
fields: [:first_name, :last_name],
page: params[:page])
else
@presenters = Presenter.all.page params[:page]
end
end
def autocomplete
render json: Presenter.search(params[:query],
autocomplete: true,
fields: [:first_name, :last_name],
limit: 10).map { |presenter|
presenter.first_name + " " + presenter.last_name
}
end
...
end
I got the .map{ |presenter| etc. } idea from here:
how do i map multiple attributes in rails with searchkick gem
However, when I followed the solution exactly, I only got 'undefined' in my drop-down of suggested names. Changing it to presenter.first_name + " " + presenter.last_name made it so the full name appears in the drop-down.
routes.rb:
resources :presenters, :only => [:index, :show] do
collection do
get :autocomplete
end
index.html.haml:
.container
= form_tag presenters_path, method: :get do
- if params[:query].present?
.btn-search.btn-clearsearch
= link_to "clear", presenters_path
- else
.search
Search
= text_field_tag :query, params[:query],
id: "presenter_search",
autocomplete: "off"
= submit_tag "go", class: "btn-search"
I am using typeahead.js, so that works with:
application.html.haml:
= javascript_include_tag 'application'
= javascript_include_tag
"//cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.9.3/typeahead.min.js"
and
presenter.js.coffee:
$ ->
$('#presenter_search').typeahead
name: "presenter"
remote: "/presenters/autocomplete?query=%QUERY"
So, once again, my problem is that if I type the first name, all options matching that first name will appear in drop-down (both first and last name), but as soon as I type the space, the entire list of suggestions goes away. I have no way of searching, say, any first and last name 'Jennifer H'. I can guess that the problem is with the mapping in the controller/autocomplete action, but typing:
.map(&:first_name, &:last_name)
or
.map(&:first_name, :last_name)
generate errors, and
.map{ |presenter| presenter.slice(:first_name, :last_name) }
makes all suggestions in the drop-down read 'undefined.'
Any suggestions on how to solve this?
Hope this helps. Remember to reindex with rake searchkick:reindex CLASS=Model_name
// in model
def full_name
[first_name, last_name].join(' ')
end
searchkick text_middle: ['full_name'], autocomplete: ['full_name']
def search_data
{
full_name: full_name
}
end
// in controller
users = User.search params[:query], fields: [{"full_name" => :text_middle}]