I am using ElasticSearch and Tire for search in my app across all models.
- I would like to refactor autocomplete method because it looks to complex for me.
- Am I using a good pattern for searching across model?
Model
class Link < ActiveRecord::Base
include Tire::Model::Search
include Tire::Model::Callbacks
tire.mapping do
indexes :id, :type => 'string', :index => :not_analyzed
indexes :title, analyzer: 'snowball', boost: 100
end
def to_indexed_json
to_json(
only: [:id, :title]
)
end
...
end
Controller
class SearchController < ApplicationController
def new
search = SearchesCatalog.new(params[:term])
render json: search.autocomplete.to_json
end
end
Lib
class SearchesCatalog
attr_reader :options
def initialize(options = {})
@options = HashWithIndifferentAccess.new(options)
@resources = [ :questions, :answers, :links, :events, past_events, :reviews ]
end
def results
term = options[:term]
Tire.search @resources do
query { string "#{term}" }
end.results
end
def autocomplete
array = []
results.each do |result|
case result.type
when "past_event"
array << { title: result.content, label: "#{result.content} <span class='search-type'>PastEvent</span>", value: "/past_events/#{result.id}" }
when "event"
array << { title: result.title, label: "#{result.title} <span class='search-type'>Event</span>", value: "/events/#{result.id}" }
when "topic"
array << { title: result.name, label: "#{result.name} <span class='search-type'>Topic</span>", value: "/#{result.app_id}/t/#{result.id}" }
when "link"
array << { title: result.title, label: "#{result.title} <span class='search-type'>Link</span>", value: "/links/#{result.id}" }
when "question"
array << { title: result.content, label: "#{result.content[0..100]} <span class='search-type'>Question</span>" }
when "answer"
array << { title: result.content, label: "#{result.content[0..100]} <span class='search-type'>Answer</span>" }
end
array
end
end
Javascript
// set up the search bar
$("#question_search").autocomplete({
source:$('#question_search').data('source'),
html: true,
minlength: 1,
appendto: "#search_results",
select: function( event, ui ) {
window.location=ui.item.value;
return false;
},
focus: function( event, ui ) {
$("#question_search").val(ui.item.title);
return false;
},
open: function( event, ui ) {
$('#search_results')
.find('a:first').addclass('first').end()
.find('a:last').addclass('last');
}
});