model.rb
5.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
module Searchkick
module Model
def searchkick(**options)
unknown_keywords = options.keys - [:_all, :_type, :batch_size, :callbacks, :conversions, :default_fields,
:filterable, :geo_shape, :highlight, :ignore_above, :index_name, :index_prefix, :inheritance, :language,
:locations, :mappings, :match, :merge_mappings, :routing, :searchable, :settings, :similarity,
:special_characters, :stem_conversions, :suggest, :synonyms, :text_end,
:text_middle, :text_start, :unscoped_reindex_job, :word, :wordnet, :word_end, :word_middle, :word_start]
raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any?
raise "Only call searchkick once per model" if respond_to?(:searchkick_index)
Searchkick.models << self
options[:_type] ||= -> { searchkick_index.klass_document_type(self, true) } if options[:inheritance]
class_eval do
cattr_reader :searchkick_options, :searchkick_klass
callbacks = options.key?(:callbacks) ? options[:callbacks] : true
class_variable_set :@@searchkick_options, options.dup
class_variable_set :@@searchkick_klass, self
class_variable_set :@@searchkick_callbacks, callbacks
class_variable_set :@@searchkick_index, options[:index_name] ||
(options[:index_prefix].respond_to?(:call) && proc { [options[:index_prefix].call, model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_") }) ||
[options.key?(:index_prefix) ? options[:index_prefix] : Searchkick.index_prefix, model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_")
class << self
def searchkick_search(term = "*", **options, &block)
Searchkick.search(term, {model: self}.merge(options), &block)
end
alias_method Searchkick.search_method_name, :searchkick_search if Searchkick.search_method_name
def searchkick_index
index = class_variable_get :@@searchkick_index
index = index.call if index.respond_to? :call
Searchkick::Index.new(index, searchkick_options)
end
alias_method :search_index, :searchkick_index unless method_defined?(:search_index)
def enable_search_callbacks
class_variable_set :@@searchkick_callbacks, true
end
def disable_search_callbacks
class_variable_set :@@searchkick_callbacks, false
end
def search_callbacks?
class_variable_get(:@@searchkick_callbacks) && Searchkick.callbacks?
end
def searchkick_reindex(method_name = nil, full: false, **options)
scoped = (respond_to?(:current_scope) && respond_to?(:default_scoped) && current_scope && current_scope.to_sql != default_scoped.to_sql) ||
(respond_to?(:queryable) && queryable != unscoped.with_default_scope)
refresh = options.fetch(:refresh, !scoped)
if method_name
# update
searchkick_index.import_scope(searchkick_klass, method_name: method_name)
searchkick_index.refresh if refresh
true
elsif scoped && !full
# reindex association
searchkick_index.import_scope(searchkick_klass)
searchkick_index.refresh if refresh
true
else
# full reindex
searchkick_index.reindex_scope(searchkick_klass, options)
end
end
alias_method :reindex, :searchkick_reindex unless method_defined?(:reindex)
def searchkick_index_options
searchkick_index.index_options
end
end
if respond_to?(:after_commit)
after_commit :reindex, if: -> { self.class.search_callbacks? }
elsif respond_to?(:after_save)
after_save :reindex, if: -> { self.class.search_callbacks? }
after_destroy :reindex, if: -> { self.class.search_callbacks? }
end
def reindex(method_name = nil, refresh: false, async: false, mode: nil)
klass_options = self.class.searchkick_index.options
if mode.nil?
mode =
if async
:async
elsif Searchkick.callbacks_value
Searchkick.callbacks_value
elsif klass_options.key?(:callbacks)
klass_options[:callbacks]
end
end
case mode
when :queue
if method_name
raise Searchkick::Error, "Partial reindex not supported with queue option"
else
self.class.searchkick_index.reindex_queue.push(id.to_s)
end
when :async
if method_name
# TODO support Mongoid and NoBrainer and non-id primary keys
Searchkick::BulkReindexJob.perform_later(
class_name: self.class.name,
record_ids: [id.to_s],
method_name: method_name ? method_name.to_s : nil
)
else
self.class.searchkick_index.reindex_record_async(self)
end
else
if method_name
self.class.searchkick_index.update_record(self, method_name)
else
self.class.searchkick_index.reindex_record(self)
end
self.class.searchkick_index.refresh if refresh
end
end unless method_defined?(:reindex)
def similar(options = {})
self.class.searchkick_index.similar_record(self, options)
end unless method_defined?(:similar)
def search_data
respond_to?(:to_hash) ? to_hash : serializable_hash
end unless method_defined?(:search_data)
def should_index?
true
end unless method_defined?(:should_index?)
if defined?(Cequel) && self < Cequel::Record && !method_defined?(:destroyed?)
def destroyed?
transient?
end
end
end
end
end
end