elasticsearch-model-queryable 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/CHANGELOG.md +26 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +695 -0
- data/Rakefile +59 -0
- data/elasticsearch-model.gemspec +57 -0
- data/examples/activerecord_article.rb +77 -0
- data/examples/activerecord_associations.rb +162 -0
- data/examples/couchbase_article.rb +66 -0
- data/examples/datamapper_article.rb +71 -0
- data/examples/mongoid_article.rb +68 -0
- data/examples/ohm_article.rb +70 -0
- data/examples/riak_article.rb +52 -0
- data/gemfiles/3.0.gemfile +12 -0
- data/gemfiles/4.0.gemfile +11 -0
- data/lib/elasticsearch/model/adapter.rb +145 -0
- data/lib/elasticsearch/model/adapters/active_record.rb +104 -0
- data/lib/elasticsearch/model/adapters/default.rb +50 -0
- data/lib/elasticsearch/model/adapters/mongoid.rb +92 -0
- data/lib/elasticsearch/model/callbacks.rb +35 -0
- data/lib/elasticsearch/model/client.rb +61 -0
- data/lib/elasticsearch/model/ext/active_record.rb +14 -0
- data/lib/elasticsearch/model/hash_wrapper.rb +15 -0
- data/lib/elasticsearch/model/importing.rb +144 -0
- data/lib/elasticsearch/model/indexing.rb +472 -0
- data/lib/elasticsearch/model/naming.rb +101 -0
- data/lib/elasticsearch/model/proxy.rb +127 -0
- data/lib/elasticsearch/model/response/base.rb +44 -0
- data/lib/elasticsearch/model/response/pagination.rb +173 -0
- data/lib/elasticsearch/model/response/records.rb +69 -0
- data/lib/elasticsearch/model/response/result.rb +63 -0
- data/lib/elasticsearch/model/response/results.rb +31 -0
- data/lib/elasticsearch/model/response.rb +71 -0
- data/lib/elasticsearch/model/searching.rb +107 -0
- data/lib/elasticsearch/model/serializing.rb +35 -0
- data/lib/elasticsearch/model/version.rb +5 -0
- data/lib/elasticsearch/model.rb +157 -0
- data/test/integration/active_record_associations_parent_child.rb +139 -0
- data/test/integration/active_record_associations_test.rb +307 -0
- data/test/integration/active_record_basic_test.rb +179 -0
- data/test/integration/active_record_custom_serialization_test.rb +62 -0
- data/test/integration/active_record_import_test.rb +100 -0
- data/test/integration/active_record_namespaced_model_test.rb +49 -0
- data/test/integration/active_record_pagination_test.rb +132 -0
- data/test/integration/mongoid_basic_test.rb +193 -0
- data/test/test_helper.rb +63 -0
- data/test/unit/adapter_active_record_test.rb +140 -0
- data/test/unit/adapter_default_test.rb +41 -0
- data/test/unit/adapter_mongoid_test.rb +102 -0
- data/test/unit/adapter_test.rb +69 -0
- data/test/unit/callbacks_test.rb +31 -0
- data/test/unit/client_test.rb +27 -0
- data/test/unit/importing_test.rb +176 -0
- data/test/unit/indexing_test.rb +478 -0
- data/test/unit/module_test.rb +57 -0
- data/test/unit/naming_test.rb +76 -0
- data/test/unit/proxy_test.rb +89 -0
- data/test/unit/response_base_test.rb +40 -0
- data/test/unit/response_pagination_kaminari_test.rb +189 -0
- data/test/unit/response_pagination_will_paginate_test.rb +208 -0
- data/test/unit/response_records_test.rb +91 -0
- data/test/unit/response_result_test.rb +90 -0
- data/test/unit/response_results_test.rb +31 -0
- data/test/unit/response_test.rb +67 -0
- data/test/unit/searching_search_request_test.rb +78 -0
- data/test/unit/searching_test.rb +41 -0
- data/test/unit/serializing_test.rb +17 -0
- metadata +466 -0
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::ImportingTest < Test::Unit::TestCase
|
4
|
+
context "Importing module" do
|
5
|
+
class ::DummyImportingModel
|
6
|
+
end
|
7
|
+
|
8
|
+
module ::DummyImportingAdapter
|
9
|
+
module ImportingMixin
|
10
|
+
def __find_in_batches(options={}, &block)
|
11
|
+
yield if block_given?
|
12
|
+
end
|
13
|
+
def __transform
|
14
|
+
lambda {|a|}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def importing_mixin
|
19
|
+
ImportingMixin
|
20
|
+
end; module_function :importing_mixin
|
21
|
+
end
|
22
|
+
|
23
|
+
should "include methods from the module and adapter" do
|
24
|
+
Elasticsearch::Model::Adapter.expects(:from_class)
|
25
|
+
.with(DummyImportingModel)
|
26
|
+
.returns(DummyImportingAdapter)
|
27
|
+
|
28
|
+
DummyImportingModel.__send__ :include, Elasticsearch::Model::Importing
|
29
|
+
|
30
|
+
assert_respond_to DummyImportingModel, :import
|
31
|
+
assert_respond_to DummyImportingModel, :__find_in_batches
|
32
|
+
end
|
33
|
+
|
34
|
+
should "call the client when importing" do
|
35
|
+
Elasticsearch::Model::Adapter.expects(:from_class)
|
36
|
+
.with(DummyImportingModel)
|
37
|
+
.returns(DummyImportingAdapter)
|
38
|
+
|
39
|
+
DummyImportingModel.__send__ :include, Elasticsearch::Model::Importing
|
40
|
+
|
41
|
+
client = mock('client')
|
42
|
+
client.expects(:bulk).returns({'items' => []})
|
43
|
+
|
44
|
+
DummyImportingModel.expects(:client).returns(client)
|
45
|
+
DummyImportingModel.expects(:index_name).returns('foo')
|
46
|
+
DummyImportingModel.expects(:document_type).returns('foo')
|
47
|
+
DummyImportingModel.stubs(:__batch_to_bulk)
|
48
|
+
assert_equal 0, DummyImportingModel.import
|
49
|
+
end
|
50
|
+
|
51
|
+
should "return the number of errors" do
|
52
|
+
Elasticsearch::Model::Adapter.expects(:from_class)
|
53
|
+
.with(DummyImportingModel)
|
54
|
+
.returns(DummyImportingAdapter)
|
55
|
+
|
56
|
+
DummyImportingModel.__send__ :include, Elasticsearch::Model::Importing
|
57
|
+
|
58
|
+
client = mock('client')
|
59
|
+
client.expects(:bulk).returns({'items' => [ {'index' => {}}, {'index' => {'error' => 'FAILED'}} ]})
|
60
|
+
|
61
|
+
DummyImportingModel.stubs(:client).returns(client)
|
62
|
+
DummyImportingModel.stubs(:index_name).returns('foo')
|
63
|
+
DummyImportingModel.stubs(:document_type).returns('foo')
|
64
|
+
DummyImportingModel.stubs(:__batch_to_bulk)
|
65
|
+
|
66
|
+
assert_equal 1, DummyImportingModel.import
|
67
|
+
end
|
68
|
+
|
69
|
+
should "return an array of error elements" do
|
70
|
+
Elasticsearch::Model::Adapter.expects(:from_class)
|
71
|
+
.with(DummyImportingModel)
|
72
|
+
.returns(DummyImportingAdapter)
|
73
|
+
|
74
|
+
DummyImportingModel.__send__ :include, Elasticsearch::Model::Importing
|
75
|
+
|
76
|
+
client = mock('client')
|
77
|
+
client.expects(:bulk).returns({'items' => [ {'index' => {}}, {'index' => {'error' => 'FAILED'}} ]})
|
78
|
+
|
79
|
+
DummyImportingModel.stubs(:client).returns(client)
|
80
|
+
DummyImportingModel.stubs(:index_name).returns('foo')
|
81
|
+
DummyImportingModel.stubs(:document_type).returns('foo')
|
82
|
+
DummyImportingModel.stubs(:__batch_to_bulk)
|
83
|
+
|
84
|
+
assert_equal [{'index' => {'error' => 'FAILED'}}], DummyImportingModel.import(return: 'errors')
|
85
|
+
end
|
86
|
+
|
87
|
+
should "yield the response" do
|
88
|
+
Elasticsearch::Model::Adapter.expects(:from_class)
|
89
|
+
.with(DummyImportingModel)
|
90
|
+
.returns(DummyImportingAdapter)
|
91
|
+
|
92
|
+
DummyImportingModel.__send__ :include, Elasticsearch::Model::Importing
|
93
|
+
|
94
|
+
client = mock('client')
|
95
|
+
client.expects(:bulk).returns({'items' => [ {'index' => {}}, {'index' => {'error' => 'FAILED'}} ]})
|
96
|
+
|
97
|
+
DummyImportingModel.stubs(:client).returns(client)
|
98
|
+
DummyImportingModel.stubs(:index_name).returns('foo')
|
99
|
+
DummyImportingModel.stubs(:document_type).returns('foo')
|
100
|
+
DummyImportingModel.stubs(:__batch_to_bulk)
|
101
|
+
|
102
|
+
DummyImportingModel.import do |response|
|
103
|
+
assert_equal 2, response['items'].size
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
should "delete and create the index with the force option" do
|
108
|
+
DummyImportingModel.expects(:__find_in_batches).with do |options|
|
109
|
+
assert_equal 'bar', options[:foo]
|
110
|
+
assert_nil options[:force]
|
111
|
+
true
|
112
|
+
end
|
113
|
+
|
114
|
+
DummyImportingModel.expects(:create_index!).with do |options|
|
115
|
+
assert_equal true, options[:force]
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
DummyImportingModel.expects(:index_name).returns('foo')
|
120
|
+
DummyImportingModel.expects(:document_type).returns('foo')
|
121
|
+
|
122
|
+
DummyImportingModel.import force: true, foo: 'bar'
|
123
|
+
end
|
124
|
+
|
125
|
+
should "allow passing a different index / type" do
|
126
|
+
Elasticsearch::Model::Adapter.expects(:from_class)
|
127
|
+
.with(DummyImportingModel)
|
128
|
+
.returns(DummyImportingAdapter)
|
129
|
+
|
130
|
+
DummyImportingModel.__send__ :include, Elasticsearch::Model::Importing
|
131
|
+
|
132
|
+
client = mock('client')
|
133
|
+
|
134
|
+
client
|
135
|
+
.expects(:bulk)
|
136
|
+
.with do |options|
|
137
|
+
assert_equal 'my-new-index', options[:index]
|
138
|
+
assert_equal 'my-other-type', options[:type]
|
139
|
+
true
|
140
|
+
end
|
141
|
+
.returns({'items' => [ {'index' => {} }]})
|
142
|
+
|
143
|
+
DummyImportingModel.stubs(:client).returns(client)
|
144
|
+
DummyImportingModel.stubs(:__batch_to_bulk)
|
145
|
+
|
146
|
+
DummyImportingModel.import index: 'my-new-index', type: 'my-other-type'
|
147
|
+
end
|
148
|
+
|
149
|
+
should "use the default transform from adapter" do
|
150
|
+
client = mock('client', bulk: {'items' => []})
|
151
|
+
transform = lambda {|a|}
|
152
|
+
|
153
|
+
DummyImportingModel.stubs(:client).returns(client)
|
154
|
+
DummyImportingModel.expects(:__transform).returns(transform)
|
155
|
+
DummyImportingModel.expects(:__batch_to_bulk).with(anything, transform)
|
156
|
+
|
157
|
+
DummyImportingModel.import index: 'foo', type: 'bar'
|
158
|
+
end
|
159
|
+
|
160
|
+
should "use the transformer from options" do
|
161
|
+
client = mock('client', bulk: {'items' => []})
|
162
|
+
transform = lambda {|a|}
|
163
|
+
|
164
|
+
DummyImportingModel.stubs(:client).returns(client)
|
165
|
+
DummyImportingModel.expects(:__batch_to_bulk).with(anything, transform)
|
166
|
+
|
167
|
+
DummyImportingModel.import index: 'foo', type: 'bar', transform: transform
|
168
|
+
end
|
169
|
+
|
170
|
+
should "raise an ArgumentError if transform doesn't respond to the call method" do
|
171
|
+
assert_raise ArgumentError do
|
172
|
+
DummyImportingModel.import index: 'foo', type: 'bar', transform: "not_callable"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,478 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::IndexingTest < Test::Unit::TestCase
|
4
|
+
context "Indexing module: " do
|
5
|
+
class ::DummyIndexingModel
|
6
|
+
extend ActiveModel::Naming
|
7
|
+
extend Elasticsearch::Model::Naming::ClassMethods
|
8
|
+
extend Elasticsearch::Model::Indexing::ClassMethods
|
9
|
+
|
10
|
+
def self.foo
|
11
|
+
'bar'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "Settings class" do
|
16
|
+
should "be convertible to hash" do
|
17
|
+
hash = { foo: 'bar' }
|
18
|
+
settings = Elasticsearch::Model::Indexing::Settings.new hash
|
19
|
+
assert_equal hash, settings.to_hash
|
20
|
+
assert_equal settings.to_hash, settings.as_json
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "Settings method" do
|
25
|
+
should "initialize the index settings" do
|
26
|
+
assert_instance_of Elasticsearch::Model::Indexing::Settings, DummyIndexingModel.settings
|
27
|
+
end
|
28
|
+
|
29
|
+
should "update and return the index settings" do
|
30
|
+
DummyIndexingModel.settings foo: 'boo'
|
31
|
+
DummyIndexingModel.settings bar: 'bam'
|
32
|
+
|
33
|
+
assert_equal( {foo: 'boo', bar: 'bam'}, DummyIndexingModel.settings.to_hash)
|
34
|
+
end
|
35
|
+
|
36
|
+
should "evaluate the block" do
|
37
|
+
DummyIndexingModel.expects(:foo)
|
38
|
+
|
39
|
+
DummyIndexingModel.settings do
|
40
|
+
foo
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "Mappings class" do
|
46
|
+
should "initialize the index mappings" do
|
47
|
+
assert_instance_of Elasticsearch::Model::Indexing::Mappings, DummyIndexingModel.mappings
|
48
|
+
end
|
49
|
+
|
50
|
+
should "raise an exception when not passed type" do
|
51
|
+
assert_raise ArgumentError do
|
52
|
+
Elasticsearch::Model::Indexing::Mappings.new
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
should "be convertible to hash" do
|
57
|
+
mappings = Elasticsearch::Model::Indexing::Mappings.new :mytype, { foo: 'bar' }
|
58
|
+
assert_equal( { :mytype => { foo: 'bar', :properties => {} } }, mappings.to_hash )
|
59
|
+
assert_equal mappings.to_hash, mappings.as_json
|
60
|
+
end
|
61
|
+
|
62
|
+
should "define properties" do
|
63
|
+
mappings = Elasticsearch::Model::Indexing::Mappings.new :mytype
|
64
|
+
assert_respond_to mappings, :indexes
|
65
|
+
|
66
|
+
mappings.indexes :foo, { type: 'boolean', include_in_all: false }
|
67
|
+
assert_equal 'boolean', mappings.to_hash[:mytype][:properties][:foo][:type]
|
68
|
+
end
|
69
|
+
|
70
|
+
should "define type as string by default" do
|
71
|
+
mappings = Elasticsearch::Model::Indexing::Mappings.new :mytype
|
72
|
+
|
73
|
+
mappings.indexes :bar, {}
|
74
|
+
assert_equal 'string', mappings.to_hash[:mytype][:properties][:bar][:type]
|
75
|
+
end
|
76
|
+
|
77
|
+
should "define embedded properties" do
|
78
|
+
mappings = Elasticsearch::Model::Indexing::Mappings.new :mytype
|
79
|
+
|
80
|
+
mappings.indexes :foo do
|
81
|
+
indexes :bar
|
82
|
+
end
|
83
|
+
|
84
|
+
mappings.indexes :multi, type: 'multi_field' do
|
85
|
+
indexes :multi, analyzer: 'snowball'
|
86
|
+
indexes :raw, analyzer: 'keyword'
|
87
|
+
end
|
88
|
+
|
89
|
+
assert_equal 'object', mappings.to_hash[:mytype][:properties][:foo][:type]
|
90
|
+
assert_equal 'string', mappings.to_hash[:mytype][:properties][:foo][:properties][:bar][:type]
|
91
|
+
|
92
|
+
assert_equal 'multi_field', mappings.to_hash[:mytype][:properties][:multi][:type]
|
93
|
+
assert_equal 'snowball', mappings.to_hash[:mytype][:properties][:multi][:fields][:multi][:analyzer]
|
94
|
+
assert_equal 'keyword', mappings.to_hash[:mytype][:properties][:multi][:fields][:raw][:analyzer]
|
95
|
+
end
|
96
|
+
|
97
|
+
should "define multi_field properties" do
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "Mappings method" do
|
102
|
+
should "initialize the index mappings" do
|
103
|
+
assert_instance_of Elasticsearch::Model::Indexing::Mappings, DummyIndexingModel.mappings
|
104
|
+
end
|
105
|
+
|
106
|
+
should "update and return the index mappings" do
|
107
|
+
DummyIndexingModel.mappings foo: 'boo' do; end
|
108
|
+
DummyIndexingModel.mappings bar: 'bam' do; end
|
109
|
+
assert_equal( { dummy_indexing_model: { foo: "boo", bar: "bam", properties: {} } },
|
110
|
+
DummyIndexingModel.mappings.to_hash )
|
111
|
+
end
|
112
|
+
|
113
|
+
should "evaluate the block" do
|
114
|
+
DummyIndexingModel.mappings.expects(:indexes).with(:foo).returns(true)
|
115
|
+
|
116
|
+
DummyIndexingModel.mappings do
|
117
|
+
indexes :foo
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "Instance methods" do
|
123
|
+
class ::DummyIndexingModelWithCallbacks
|
124
|
+
extend Elasticsearch::Model::Indexing::ClassMethods
|
125
|
+
include Elasticsearch::Model::Indexing::InstanceMethods
|
126
|
+
|
127
|
+
def self.before_save(&block)
|
128
|
+
(@callbacks ||= {})[block.hash] = block
|
129
|
+
end
|
130
|
+
|
131
|
+
def changed_attributes; [:foo]; end
|
132
|
+
|
133
|
+
def changes
|
134
|
+
{:foo => ['One', 'Two']}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class ::DummyIndexingModelWithCallbacksAndCustomAsIndexedJson
|
139
|
+
extend Elasticsearch::Model::Indexing::ClassMethods
|
140
|
+
include Elasticsearch::Model::Indexing::InstanceMethods
|
141
|
+
|
142
|
+
def self.before_save(&block)
|
143
|
+
(@callbacks ||= {})[block.hash] = block
|
144
|
+
end
|
145
|
+
|
146
|
+
def changed_attributes; [:foo, :bar]; end
|
147
|
+
|
148
|
+
def changes
|
149
|
+
{:foo => ['A', 'B'], :bar => ['C', 'D']}
|
150
|
+
end
|
151
|
+
|
152
|
+
def as_indexed_json(options={})
|
153
|
+
{ :foo => 'B' }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
should "register before_save callback when included" do
|
158
|
+
::DummyIndexingModelWithCallbacks.expects(:before_save).returns(true)
|
159
|
+
::DummyIndexingModelWithCallbacks.__send__ :include, Elasticsearch::Model::Indexing::InstanceMethods
|
160
|
+
end
|
161
|
+
|
162
|
+
should "set the @__changed_attributes variable before save" do
|
163
|
+
instance = ::DummyIndexingModelWithCallbacks.new
|
164
|
+
instance.expects(:instance_variable_set).with do |name, value|
|
165
|
+
assert_equal :@__changed_attributes, name
|
166
|
+
assert_equal({foo: 'Two'}, value)
|
167
|
+
true
|
168
|
+
end
|
169
|
+
|
170
|
+
::DummyIndexingModelWithCallbacks.__send__ :include, Elasticsearch::Model::Indexing::InstanceMethods
|
171
|
+
|
172
|
+
::DummyIndexingModelWithCallbacks.instance_variable_get(:@callbacks).each do |n,b|
|
173
|
+
instance.instance_eval(&b)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
should "have the index_document method" do
|
178
|
+
client = mock('client')
|
179
|
+
instance = ::DummyIndexingModelWithCallbacks.new
|
180
|
+
|
181
|
+
client.expects(:index).with do |payload|
|
182
|
+
assert_equal 'foo', payload[:index]
|
183
|
+
assert_equal 'bar', payload[:type]
|
184
|
+
assert_equal '1', payload[:id]
|
185
|
+
assert_equal 'JSON', payload[:body]
|
186
|
+
true
|
187
|
+
end
|
188
|
+
|
189
|
+
instance.expects(:client).returns(client)
|
190
|
+
instance.expects(:as_indexed_json).returns('JSON')
|
191
|
+
instance.expects(:index_name).returns('foo')
|
192
|
+
instance.expects(:document_type).returns('bar')
|
193
|
+
instance.expects(:id).returns('1')
|
194
|
+
|
195
|
+
instance.index_document
|
196
|
+
end
|
197
|
+
|
198
|
+
should "pass extra options to the index_document method to client.index" do
|
199
|
+
client = mock('client')
|
200
|
+
instance = ::DummyIndexingModelWithCallbacks.new
|
201
|
+
|
202
|
+
client.expects(:index).with do |payload|
|
203
|
+
assert_equal 'A', payload[:parent]
|
204
|
+
true
|
205
|
+
end
|
206
|
+
|
207
|
+
instance.expects(:client).returns(client)
|
208
|
+
instance.expects(:as_indexed_json).returns('JSON')
|
209
|
+
instance.expects(:index_name).returns('foo')
|
210
|
+
instance.expects(:document_type).returns('bar')
|
211
|
+
instance.expects(:id).returns('1')
|
212
|
+
|
213
|
+
instance.index_document(parent: 'A')
|
214
|
+
end
|
215
|
+
|
216
|
+
should "have the delete_document method" do
|
217
|
+
client = mock('client')
|
218
|
+
instance = ::DummyIndexingModelWithCallbacks.new
|
219
|
+
|
220
|
+
client.expects(:delete).with do |payload|
|
221
|
+
assert_equal 'foo', payload[:index]
|
222
|
+
assert_equal 'bar', payload[:type]
|
223
|
+
assert_equal '1', payload[:id]
|
224
|
+
true
|
225
|
+
end
|
226
|
+
|
227
|
+
instance.expects(:client).returns(client)
|
228
|
+
instance.expects(:index_name).returns('foo')
|
229
|
+
instance.expects(:document_type).returns('bar')
|
230
|
+
instance.expects(:id).returns('1')
|
231
|
+
|
232
|
+
instance.delete_document()
|
233
|
+
end
|
234
|
+
|
235
|
+
should "pass extra options to the delete_document method to client.delete" do
|
236
|
+
client = mock('client')
|
237
|
+
instance = ::DummyIndexingModelWithCallbacks.new
|
238
|
+
|
239
|
+
client.expects(:delete).with do |payload|
|
240
|
+
assert_equal 'A', payload[:parent]
|
241
|
+
true
|
242
|
+
end
|
243
|
+
|
244
|
+
instance.expects(:client).returns(client)
|
245
|
+
instance.expects(:id).returns('1')
|
246
|
+
instance.expects(:index_name).returns('foo')
|
247
|
+
instance.expects(:document_type).returns('bar')
|
248
|
+
|
249
|
+
instance.delete_document(parent: 'A')
|
250
|
+
end
|
251
|
+
|
252
|
+
should "update the document by re-indexing when no changes are present" do
|
253
|
+
client = mock('client')
|
254
|
+
instance = ::DummyIndexingModelWithCallbacks.new
|
255
|
+
|
256
|
+
# Reset the fake `changes`
|
257
|
+
instance.instance_variable_set(:@__changed_attributes, nil)
|
258
|
+
|
259
|
+
instance.expects(:index_document)
|
260
|
+
instance.update_document
|
261
|
+
end
|
262
|
+
|
263
|
+
should "update the document by partial update when changes are present" do
|
264
|
+
client = mock('client')
|
265
|
+
instance = ::DummyIndexingModelWithCallbacks.new
|
266
|
+
|
267
|
+
# Set the fake `changes` hash
|
268
|
+
instance.instance_variable_set(:@__changed_attributes, {foo: 'bar'})
|
269
|
+
|
270
|
+
client.expects(:update).with do |payload|
|
271
|
+
assert_equal 'foo', payload[:index]
|
272
|
+
assert_equal 'bar', payload[:type]
|
273
|
+
assert_equal '1', payload[:id]
|
274
|
+
assert_equal({foo: 'bar'}, payload[:body][:doc])
|
275
|
+
true
|
276
|
+
end
|
277
|
+
|
278
|
+
instance.expects(:client).returns(client)
|
279
|
+
instance.expects(:index_name).returns('foo')
|
280
|
+
instance.expects(:document_type).returns('bar')
|
281
|
+
instance.expects(:id).returns('1')
|
282
|
+
|
283
|
+
instance.update_document
|
284
|
+
end
|
285
|
+
|
286
|
+
should "exclude attributes not contained in custom as_indexed_json during partial update" do
|
287
|
+
client = mock('client')
|
288
|
+
instance = ::DummyIndexingModelWithCallbacksAndCustomAsIndexedJson.new
|
289
|
+
|
290
|
+
# Set the fake `changes` hash
|
291
|
+
instance.instance_variable_set(:@__changed_attributes, {'foo' => 'B', 'bar' => 'D' })
|
292
|
+
|
293
|
+
client.expects(:update).with do |payload|
|
294
|
+
assert_equal({:foo => 'B'}, payload[:body][:doc])
|
295
|
+
true
|
296
|
+
end
|
297
|
+
|
298
|
+
instance.expects(:client).returns(client)
|
299
|
+
instance.expects(:index_name).returns('foo')
|
300
|
+
instance.expects(:document_type).returns('bar')
|
301
|
+
instance.expects(:id).returns('1')
|
302
|
+
|
303
|
+
instance.update_document
|
304
|
+
end
|
305
|
+
|
306
|
+
should "get attributes from as_indexed_json during partial update" do
|
307
|
+
client = mock('client')
|
308
|
+
instance = ::DummyIndexingModelWithCallbacksAndCustomAsIndexedJson.new
|
309
|
+
|
310
|
+
instance.instance_variable_set(:@__changed_attributes, { 'foo' => { 'bar' => 'BAR'} })
|
311
|
+
# Overload as_indexed_json
|
312
|
+
instance.expects(:as_indexed_json).returns({ 'foo' => 'BAR' })
|
313
|
+
|
314
|
+
client.expects(:update).with do |payload|
|
315
|
+
assert_equal({'foo' => 'BAR'}, payload[:body][:doc])
|
316
|
+
true
|
317
|
+
end
|
318
|
+
|
319
|
+
instance.expects(:client).returns(client)
|
320
|
+
instance.expects(:index_name).returns('foo')
|
321
|
+
instance.expects(:document_type).returns('bar')
|
322
|
+
instance.expects(:id).returns('1')
|
323
|
+
|
324
|
+
instance.update_document
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
context "Re-creating the index" do
|
329
|
+
class ::DummyIndexingModelForRecreate
|
330
|
+
extend ActiveModel::Naming
|
331
|
+
extend Elasticsearch::Model::Naming::ClassMethods
|
332
|
+
extend Elasticsearch::Model::Indexing::ClassMethods
|
333
|
+
|
334
|
+
settings index: { number_of_shards: 1 } do
|
335
|
+
mappings do
|
336
|
+
indexes :foo, analyzer: 'keyword'
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
should "delete the index without raising exception" do
|
342
|
+
client = stub('client')
|
343
|
+
indices = stub('indices')
|
344
|
+
client.stubs(:indices).returns(indices)
|
345
|
+
|
346
|
+
indices.expects(:delete).returns({}).then.raises(Exception).at_least_once
|
347
|
+
|
348
|
+
DummyIndexingModelForRecreate.expects(:client).returns(client).at_least_once
|
349
|
+
|
350
|
+
assert_nothing_raised do
|
351
|
+
DummyIndexingModelForRecreate.delete_index!
|
352
|
+
DummyIndexingModelForRecreate.delete_index!
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
should "create the index with correct settings and mappings when it doesn't exist" do
|
357
|
+
client = stub('client')
|
358
|
+
indices = stub('indices')
|
359
|
+
client.stubs(:indices).returns(indices)
|
360
|
+
|
361
|
+
indices.expects(:exists).returns(false)
|
362
|
+
|
363
|
+
indices.expects(:create).with do |payload|
|
364
|
+
assert_equal 'dummy_indexing_model_for_recreates', payload[:index]
|
365
|
+
assert_equal 1, payload[:body][:settings][:index][:number_of_shards]
|
366
|
+
assert_equal 'keyword', payload[:body][:mappings][:dummy_indexing_model_for_recreate][:properties][:foo][:analyzer]
|
367
|
+
true
|
368
|
+
end.returns({})
|
369
|
+
|
370
|
+
DummyIndexingModelForRecreate.expects(:client).returns(client).at_least_once
|
371
|
+
|
372
|
+
assert_nothing_raised { DummyIndexingModelForRecreate.create_index! }
|
373
|
+
end
|
374
|
+
|
375
|
+
should "not create the index when it exists" do
|
376
|
+
client = stub('client')
|
377
|
+
indices = stub('indices')
|
378
|
+
client.stubs(:indices).returns(indices)
|
379
|
+
|
380
|
+
indices.expects(:exists).returns(true)
|
381
|
+
|
382
|
+
indices.expects(:create).never
|
383
|
+
|
384
|
+
DummyIndexingModelForRecreate.expects(:client).returns(client).at_least_once
|
385
|
+
|
386
|
+
assert_nothing_raised { DummyIndexingModelForRecreate.create_index! }
|
387
|
+
end
|
388
|
+
|
389
|
+
should "not raise exception during index creation" do
|
390
|
+
client = stub('client')
|
391
|
+
indices = stub('indices')
|
392
|
+
client.stubs(:indices).returns(indices)
|
393
|
+
|
394
|
+
indices.expects(:exists).returns(false)
|
395
|
+
indices.expects(:create).raises(Exception).at_least_once
|
396
|
+
|
397
|
+
DummyIndexingModelForRecreate.expects(:client).returns(client).at_least_once
|
398
|
+
|
399
|
+
assert_nothing_raised do
|
400
|
+
DummyIndexingModelForRecreate.create_index!
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
should "delete the index first with the force option" do
|
405
|
+
client = stub('client')
|
406
|
+
indices = stub('indices')
|
407
|
+
client.stubs(:indices).returns(indices)
|
408
|
+
|
409
|
+
indices.expects(:delete).returns({})
|
410
|
+
indices.expects(:exists).returns(false)
|
411
|
+
indices.expects(:create).returns({}).at_least_once
|
412
|
+
|
413
|
+
DummyIndexingModelForRecreate.expects(:client).returns(client).at_least_once
|
414
|
+
|
415
|
+
assert_nothing_raised do
|
416
|
+
DummyIndexingModelForRecreate.create_index! force: true
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
should "refresh the index without raising exception" do
|
421
|
+
client = stub('client')
|
422
|
+
indices = stub('indices')
|
423
|
+
client.stubs(:indices).returns(indices)
|
424
|
+
|
425
|
+
indices.expects(:refresh).returns({}).then.raises(Exception).at_least_once
|
426
|
+
|
427
|
+
DummyIndexingModelForRecreate.expects(:client).returns(client).at_least_once
|
428
|
+
|
429
|
+
assert_nothing_raised do
|
430
|
+
DummyIndexingModelForRecreate.refresh_index!
|
431
|
+
DummyIndexingModelForRecreate.refresh_index!
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
context "with a custom index name" do
|
436
|
+
setup do
|
437
|
+
@client = stub('client')
|
438
|
+
@indices = stub('indices')
|
439
|
+
@client.stubs(:indices).returns(@indices)
|
440
|
+
DummyIndexingModelForRecreate.expects(:client).returns(@client).at_least_once
|
441
|
+
end
|
442
|
+
|
443
|
+
should "create the custom index" do
|
444
|
+
@indices.expects(:exists).with do |arguments|
|
445
|
+
assert_equal 'custom-foo', arguments[:index]
|
446
|
+
true
|
447
|
+
end
|
448
|
+
|
449
|
+
@indices.expects(:create).with do |arguments|
|
450
|
+
assert_equal 'custom-foo', arguments[:index]
|
451
|
+
true
|
452
|
+
end
|
453
|
+
|
454
|
+
DummyIndexingModelForRecreate.create_index! index: 'custom-foo'
|
455
|
+
end
|
456
|
+
|
457
|
+
should "delete the custom index" do
|
458
|
+
@indices.expects(:delete).with do |arguments|
|
459
|
+
assert_equal 'custom-foo', arguments[:index]
|
460
|
+
true
|
461
|
+
end
|
462
|
+
|
463
|
+
DummyIndexingModelForRecreate.delete_index! index: 'custom-foo'
|
464
|
+
end
|
465
|
+
|
466
|
+
should "refresh the custom index" do
|
467
|
+
@indices.expects(:refresh).with do |arguments|
|
468
|
+
assert_equal 'custom-foo', arguments[:index]
|
469
|
+
true
|
470
|
+
end
|
471
|
+
|
472
|
+
DummyIndexingModelForRecreate.refresh_index! index: 'custom-foo'
|
473
|
+
end
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
end
|
478
|
+
end
|