model.rb
3.91 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
module Searchkick
module Model
def searchkick(options = {})
class_eval do
cattr_reader :searchkick_options, :searchkick_env, :searchkick_klass, :searchkick_index
class_variable_set :@@searchkick_options, options.dup
class_variable_set :@@searchkick_env, ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
class_variable_set :@@searchkick_klass, self
class_variable_set :@@searchkick_callbacks, options[:callbacks] != false
# set index name
# TODO support proc
index_name = options[:index_name] || [options[:index_prefix], model_name.plural, searchkick_env].compact.join("_")
class_variable_set :@@searchkick_index, Searchkick::Index.new(index_name)
extend Searchkick::Search
extend Searchkick::Reindex
include Searchkick::Similar
if respond_to?(:after_commit)
after_commit :reindex, if: proc{ self.class.search_callbacks? }
else
after_save :reindex, if: proc{ self.class.search_callbacks? }
after_destroy :reindex, if: proc{ self.class.search_callbacks? }
end
def self.enable_search_callbacks
class_variable_set :@@searchkick_callbacks, true
end
def self.disable_search_callbacks
class_variable_set :@@searchkick_callbacks, false
end
def self.search_callbacks?
class_variable_get(:@@searchkick_callbacks) && Searchkick.callbacks?
end
def should_index?
true
end
def reindex
index = self.class.searchkick_index
if destroyed? or !should_index?
index.remove self
else
index.store self
end
end
def search_data
respond_to?(:to_hash) ? to_hash : serializable_hash
end
def as_indexed_json
source = search_data
# stringify fields
source = source.inject({}){|memo,(k,v)| memo[k.to_s] = v; memo}
# Mongoid 4 hack
if defined?(BSON::ObjectId) and source["_id"].is_a?(BSON::ObjectId)
source["_id"] = source["_id"].to_s
end
options = self.class.searchkick_options
# conversions
conversions_field = options[:conversions]
if conversions_field and source[conversions_field]
source[conversions_field] = source[conversions_field].map{|k, v| {query: k, count: v} }
end
# hack to prevent generator field doesn't exist error
(options[:suggest] || []).map(&:to_s).each do |field|
source[field] = nil if !source[field]
end
# locations
(options[:locations] || []).map(&:to_s).each do |field|
if source[field]
if source[field].first.is_a?(Array) # array of arrays
source[field] = source[field].map{|a| a.map(&:to_f).reverse }
else
source[field] = source[field].map(&:to_f).reverse
end
end
end
# change all BigDecimal values to floats due to
# https://github.com/rails/rails/issues/6033
# possible loss of precision :/
cast_big_decimal =
proc do |obj|
case obj
when BigDecimal
obj.to_f
when Hash
obj.each do |k, v|
obj[k] = cast_big_decimal.call(v)
end
when Enumerable
obj.map! do |v|
cast_big_decimal.call(v)
end
else
obj
end
end
cast_big_decimal.call(source)
# p search_data
source.as_json
end
# TODO remove
def self.document_type
model_name.to_s.underscore
end
def document_type
self.class.document_type
end
end
end
end
end