forked from toptal/chewy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chewy.rb
194 lines (171 loc) · 5.92 KB
/
chewy.rb
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
require 'active_support'
require 'active_support/log_subscriber'
require 'active_support/deprecation'
require 'active_support/core_ext'
require 'active_support/concern'
require 'active_support/json'
require 'i18n/core_ext/hash'
require 'chewy/backports/deep_dup' unless Object.respond_to?(:deep_dup)
require 'singleton'
require 'elasticsearch'
require 'chewy/version'
require 'chewy/errors'
require 'chewy/config'
require 'chewy/repository'
require 'chewy/runtime'
require 'chewy/log_subscriber'
require 'chewy/strategy'
require 'chewy/index'
require 'chewy/type'
require 'chewy/fields/base'
require 'chewy/fields/root'
begin
require 'kaminari'
require 'chewy/query/pagination/kaminari'
rescue LoadError
end
begin
require 'will_paginate'
require 'will_paginate/collection'
require 'chewy/query/pagination/will_paginate'
rescue LoadError
end
require 'chewy/railtie' if defined?(::Rails)
ActiveSupport.on_load(:active_record) do
extend Chewy::Type::Observe::ActiveRecordMethods
begin
require 'will_paginate/active_record'
rescue LoadError
end
end
ActiveSupport.on_load(:mongoid) do
module Mongoid::Document::ClassMethods
include Chewy::Type::Observe::MongoidMethods
end
begin
require 'will_paginate/mongoid'
require 'chewy/query/pagination/will_paginate'
rescue LoadError
end
end
module Chewy
class << self
# Derives type from string `index#type` representation:
#
# Chewy.derive_type('users#user') # => UsersIndex::User
#
# If index has only one type - it is possible to derive it without specification:
#
# Chewy.derive_type('users') # => UsersIndex::User
#
# If index has more then one type - it raises Chewy::UnderivableType.
#
def derive_type name
return name if name.is_a?(Class) && name < Chewy::Type
index_name, type_name = name.split('#', 2)
class_name = "#{index_name.camelize}Index"
index = class_name.safe_constantize
raise Chewy::UnderivableType.new("Can not find index named `#{class_name}`") unless index && index < Chewy::Index
type = if type_name.present?
index.type_hash[type_name] or raise Chewy::UnderivableType.new("Index `#{class_name}` doesn`t have type named `#{type_name}`")
elsif index.types.one?
index.types.first
else
raise Chewy::UnderivableType.new("Index `#{class_name}` has more than one type, please specify type via `#{index_name}#type_name`")
end
end
# Creates Chewy::Type ancestor defining index and adapter methods.
#
def create_type index, target, options = {}, &block
type = Class.new(Chewy::Type)
adapter = if defined?(::ActiveRecord::Base) && ((target.is_a?(Class) && target < ::ActiveRecord::Base) || target.is_a?(::ActiveRecord::Relation))
Chewy::Type::Adapter::ActiveRecord.new(target, options)
elsif defined?(::Mongoid::Document) && ((target.is_a?(Class) && target.ancestors.include?(::Mongoid::Document)) || target.is_a?(::Mongoid::Criteria))
Chewy::Type::Adapter::Mongoid.new(target, options)
else
Chewy::Type::Adapter::Object.new(target, options)
end
index.const_set(adapter.name, type)
type.send(:define_singleton_method, :index) { index }
type.send(:define_singleton_method, :adapter) { adapter }
type.class_eval &block if block
type
end
# Main elasticsearch-ruby client instance
#
def client
Thread.current[:chewy_client] ||= ::Elasticsearch::Client.new configuration
end
# Sends wait_for_status request to ElasticSearch with status
# defined in configuration.
#
# Does nothing in case of config `wait_for_status` is undefined.
#
def wait_for_status
client.cluster.health wait_for_status: Chewy.configuration[:wait_for_status] if Chewy.configuration[:wait_for_status].present?
end
# Deletes all corresponding indexes with current prefix from ElasticSearch.
# Be careful, if current prefix is blank, this will destroy all the indexes.
#
def massacre
Chewy.client.indices.delete(index: [Chewy.configuration[:prefix], '*'].delete_if(&:blank?).join(?_))
Chewy.wait_for_status
end
alias_method :delete_all, :massacre
# Strategies are designed to allow nesting, so it is possible
# to redefine it for nested contexts.
#
# Chewy.strategy(:atomic) do
# city1.do_update!
# Chewy.strategy(:urgent) do
# city2.do_update!
# city3.do_update!
# # there will be 2 update index requests for city2 and city3
# end
# city4..do_update!
# # city1 and city4 will be grouped in one index update request
# end
#
# It is possible to nest strategies without blocks:
#
# Chewy.strategy(:urgent)
# city1.do_update! # index updated
# Chewy.strategy(:bypass)
# city2.do_update! # update bypassed
# Chewy.strategy.pop
# city3.do_update! # index updated again
#
def strategy name = nil, &block
Thread.current[:chewy_strategy] ||= Chewy::Strategy.new
if name
if block
Thread.current[:chewy_strategy].wrap name, &block
else
Thread.current[:chewy_strategy].push name
end
else
Thread.current[:chewy_strategy]
end
end
def urgent_update= value
ActiveSupport::Deprecation.warn('`Chewy.urgent_update = value` is deprecated and will be removed soon, use `Chewy.strategy(:urgent)` block instead')
if value
strategy(:urgent)
else
strategy.pop
end
end
def atomic &block
ActiveSupport::Deprecation.warn('`Chewy.atomic` block is deprecated and will be removed soon, use `Chewy.strategy(:atomic)` block instead')
strategy(:atomic, &block)
end
def config
Chewy::Config.instance
end
delegate *Chewy::Config.delegated, to: :config
def repository
Chewy::Repository.instance
end
delegate *Chewy::Repository.delegated, to: :repository
end
end