app/models/concerns/searchable.rb
module Searchable
extend ActiveSupport::Concern
included do
include Elasticsearch::Model
after_commit on: [:create] do
if Rails.env.test?
self.class.reindexed << self.id
else
delay.reindex
end
end
after_commit on: [:update] do
if Rails.env.test?
self.class.reindexed << self.id
else
delay.reindex
end
end
after_commit on: [:destroy] do
if Rails.env.test?
self.class.removed_from_index << self.id
else
delay.remove_from_index
end
end
def reindex
__elasticsearch__.index_document
end
def remove_from_index
__elasticsearch__.destroy_document
end
def self.reindexed
@@reindexed ||= []
end
def self.removed_from_index
@@removed_from_index ||= []
end
def self.clear_index_tracking
@@reindexed = []
@@removed_from_index = []
end
def self.rebuild_index
stager = index_stager
indexer(stager).run
stager.alias_stage_to_tmp_index && stager.promote
__elasticsearch__.refresh_index!
end
# ransack/meta_search (for activeadmin) and elasticsearch both try and inject a class search() method,
# so we declare our own and Try To Do the Right Thing
def self.search(*args, &block)
if args.first.is_a?(Elasticsearch::DSL::Search) || args.first.is_a?(String)
return self.__elasticsearch__.search(*args, &block)
else
return ransack(*args, &block)
end
end
private
def self.index_stager
Elasticsearch::Rails::HA::IndexStager.new(self.to_s)
end
def self.indexer(stager)
Elasticsearch::Rails::HA::ParallelIndexer.new(
klass: self.to_s,
idx_name: stager.tmp_index_name,
nprocs: ENV.fetch("NPROCS", 1),
batch_size: ENV.fetch("BATCH", 100),
force: true,
verbose: ENV.fetch("ES_DEBUG", false)
)
end
end
end