elasticsearch-persistence-queryable 0.1.8
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 +17 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +678 -0
- data/Rakefile +57 -0
- data/elasticsearch-persistence.gemspec +57 -0
- data/examples/music/album.rb +34 -0
- data/examples/music/artist.rb +50 -0
- data/examples/music/artists/_form.html.erb +8 -0
- data/examples/music/artists/artists_controller.rb +67 -0
- data/examples/music/artists/artists_controller_test.rb +53 -0
- data/examples/music/artists/index.html.erb +57 -0
- data/examples/music/artists/show.html.erb +51 -0
- data/examples/music/assets/application.css +226 -0
- data/examples/music/assets/autocomplete.css +48 -0
- data/examples/music/assets/blank_cover.png +0 -0
- data/examples/music/assets/form.css +113 -0
- data/examples/music/index_manager.rb +60 -0
- data/examples/music/search/index.html.erb +93 -0
- data/examples/music/search/search_controller.rb +41 -0
- data/examples/music/search/search_controller_test.rb +9 -0
- data/examples/music/search/search_helper.rb +15 -0
- data/examples/music/suggester.rb +45 -0
- data/examples/music/template.rb +392 -0
- data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.css +7 -0
- data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.js +6 -0
- data/examples/notes/.gitignore +7 -0
- data/examples/notes/Gemfile +28 -0
- data/examples/notes/README.markdown +36 -0
- data/examples/notes/application.rb +238 -0
- data/examples/notes/config.ru +7 -0
- data/examples/notes/test.rb +118 -0
- data/lib/elasticsearch/per_thread_registry.rb +53 -0
- data/lib/elasticsearch/persistence/client.rb +51 -0
- data/lib/elasticsearch/persistence/inheritence.rb +9 -0
- data/lib/elasticsearch/persistence/model/base.rb +95 -0
- data/lib/elasticsearch/persistence/model/callbacks.rb +37 -0
- data/lib/elasticsearch/persistence/model/errors.rb +9 -0
- data/lib/elasticsearch/persistence/model/find.rb +155 -0
- data/lib/elasticsearch/persistence/model/gateway_delegation.rb +23 -0
- data/lib/elasticsearch/persistence/model/hash_wrapper.rb +17 -0
- data/lib/elasticsearch/persistence/model/rails.rb +39 -0
- data/lib/elasticsearch/persistence/model/store.rb +271 -0
- data/lib/elasticsearch/persistence/model.rb +148 -0
- data/lib/elasticsearch/persistence/null_relation.rb +56 -0
- data/lib/elasticsearch/persistence/query_cache.rb +68 -0
- data/lib/elasticsearch/persistence/querying.rb +21 -0
- data/lib/elasticsearch/persistence/relation/delegation.rb +130 -0
- data/lib/elasticsearch/persistence/relation/finder_methods.rb +39 -0
- data/lib/elasticsearch/persistence/relation/merger.rb +179 -0
- data/lib/elasticsearch/persistence/relation/query_builder.rb +279 -0
- data/lib/elasticsearch/persistence/relation/query_methods.rb +362 -0
- data/lib/elasticsearch/persistence/relation/search_option_methods.rb +44 -0
- data/lib/elasticsearch/persistence/relation/spawn_methods.rb +61 -0
- data/lib/elasticsearch/persistence/relation.rb +110 -0
- data/lib/elasticsearch/persistence/repository/class.rb +71 -0
- data/lib/elasticsearch/persistence/repository/find.rb +73 -0
- data/lib/elasticsearch/persistence/repository/naming.rb +115 -0
- data/lib/elasticsearch/persistence/repository/response/results.rb +105 -0
- data/lib/elasticsearch/persistence/repository/search.rb +156 -0
- data/lib/elasticsearch/persistence/repository/serialize.rb +31 -0
- data/lib/elasticsearch/persistence/repository/store.rb +94 -0
- data/lib/elasticsearch/persistence/repository.rb +77 -0
- data/lib/elasticsearch/persistence/scoping/default.rb +137 -0
- data/lib/elasticsearch/persistence/scoping/named.rb +70 -0
- data/lib/elasticsearch/persistence/scoping.rb +52 -0
- data/lib/elasticsearch/persistence/version.rb +5 -0
- data/lib/elasticsearch/persistence.rb +157 -0
- data/lib/elasticsearch/rails_compatibility.rb +17 -0
- data/lib/rails/generators/elasticsearch/model/model_generator.rb +21 -0
- data/lib/rails/generators/elasticsearch/model/templates/model.rb.tt +9 -0
- data/lib/rails/generators/elasticsearch_generator.rb +2 -0
- data/lib/rails/instrumentation/railtie.rb +31 -0
- data/lib/rails/instrumentation.rb +10 -0
- data/test/integration/model/model_basic_test.rb +157 -0
- data/test/integration/repository/custom_class_test.rb +85 -0
- data/test/integration/repository/customized_class_test.rb +82 -0
- data/test/integration/repository/default_class_test.rb +114 -0
- data/test/integration/repository/virtus_model_test.rb +114 -0
- data/test/test_helper.rb +53 -0
- data/test/unit/model_base_test.rb +48 -0
- data/test/unit/model_find_test.rb +148 -0
- data/test/unit/model_gateway_test.rb +99 -0
- data/test/unit/model_rails_test.rb +88 -0
- data/test/unit/model_store_test.rb +514 -0
- data/test/unit/persistence_test.rb +32 -0
- data/test/unit/repository_class_test.rb +51 -0
- data/test/unit/repository_client_test.rb +32 -0
- data/test/unit/repository_find_test.rb +388 -0
- data/test/unit/repository_indexing_test.rb +37 -0
- data/test/unit/repository_module_test.rb +146 -0
- data/test/unit/repository_naming_test.rb +146 -0
- data/test/unit/repository_response_results_test.rb +98 -0
- data/test/unit/repository_search_test.rb +117 -0
- data/test/unit/repository_serialize_test.rb +57 -0
- data/test/unit/repository_store_test.rb +303 -0
- metadata +487 -0
@@ -0,0 +1,514 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
require 'virtus'
|
5
|
+
|
6
|
+
require 'elasticsearch/persistence/model/base'
|
7
|
+
require 'elasticsearch/persistence/model/errors'
|
8
|
+
require 'elasticsearch/persistence/model/store'
|
9
|
+
|
10
|
+
class Elasticsearch::Persistence::ModelStoreTest < Test::Unit::TestCase
|
11
|
+
context "The model store module," do
|
12
|
+
|
13
|
+
class DummyStoreModel
|
14
|
+
include ActiveModel::Naming
|
15
|
+
include ActiveModel::Conversion
|
16
|
+
include ActiveModel::Serialization
|
17
|
+
include ActiveModel::Serializers::JSON
|
18
|
+
include ActiveModel::Validations
|
19
|
+
|
20
|
+
include Virtus.model
|
21
|
+
|
22
|
+
include Elasticsearch::Persistence::Model::Base::InstanceMethods
|
23
|
+
extend Elasticsearch::Persistence::Model::Store::ClassMethods
|
24
|
+
include Elasticsearch::Persistence::Model::Store::InstanceMethods
|
25
|
+
|
26
|
+
extend ActiveModel::Callbacks
|
27
|
+
define_model_callbacks :create, :save, :update, :destroy
|
28
|
+
define_model_callbacks :find, :touch, only: :after
|
29
|
+
|
30
|
+
attribute :title, String
|
31
|
+
attribute :count, Integer, default: 0
|
32
|
+
attribute :created_at, DateTime, default: lambda { |o,a| Time.now.utc }
|
33
|
+
attribute :updated_at, DateTime, default: lambda { |o,a| Time.now.utc }
|
34
|
+
end
|
35
|
+
|
36
|
+
setup do
|
37
|
+
@shoulda_subject = DummyStoreModel.new title: 'Test'
|
38
|
+
@gateway = stub
|
39
|
+
DummyStoreModel.stubs(:gateway).returns(@gateway)
|
40
|
+
end
|
41
|
+
|
42
|
+
teardown do
|
43
|
+
Elasticsearch::Persistence::ModelStoreTest.__send__ :remove_const, :DummyStoreModelWithCallback \
|
44
|
+
rescue NameError; nil
|
45
|
+
end
|
46
|
+
|
47
|
+
should "be new_record" do
|
48
|
+
assert subject.new_record?
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when creating," do
|
52
|
+
should "save the object and return it" do
|
53
|
+
DummyStoreModel.any_instance.expects(:save).returns({'_id' => 'X'})
|
54
|
+
|
55
|
+
assert_instance_of DummyStoreModel, DummyStoreModel.create(title: 'Test')
|
56
|
+
end
|
57
|
+
|
58
|
+
should "execute the callbacks" do
|
59
|
+
DummyStoreModelWithCallback = Class.new(DummyStoreModel)
|
60
|
+
@gateway.expects(:save).returns({'_id' => 'X'})
|
61
|
+
|
62
|
+
DummyStoreModelWithCallback.after_create { $stderr.puts "CREATED" }
|
63
|
+
DummyStoreModelWithCallback.after_save { $stderr.puts "SAVED" }
|
64
|
+
|
65
|
+
$stderr.expects(:puts).with('CREATED')
|
66
|
+
$stderr.expects(:puts).with('SAVED')
|
67
|
+
|
68
|
+
DummyStoreModelWithCallback.create name: 'test'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when saving," do
|
73
|
+
should "save the model" do
|
74
|
+
@gateway
|
75
|
+
.expects(:save)
|
76
|
+
.with do |object, options|
|
77
|
+
assert_equal subject, object
|
78
|
+
assert_equal nil, options[:id]
|
79
|
+
true
|
80
|
+
end
|
81
|
+
.returns({'_id' => 'abc123'})
|
82
|
+
|
83
|
+
assert ! subject.persisted?
|
84
|
+
|
85
|
+
assert subject.save
|
86
|
+
assert subject.persisted?
|
87
|
+
end
|
88
|
+
|
89
|
+
should "save the model and set the ID" do
|
90
|
+
@gateway
|
91
|
+
.expects(:save)
|
92
|
+
.returns({'_id' => 'abc123'})
|
93
|
+
|
94
|
+
assert_nil subject.id
|
95
|
+
|
96
|
+
subject.save
|
97
|
+
assert_equal 'abc123', subject.id
|
98
|
+
end
|
99
|
+
|
100
|
+
should "save the model and update the timestamp" do
|
101
|
+
now = Time.parse('2014-01-01T00:00:00Z')
|
102
|
+
Time.expects(:now).returns(now).at_least_once
|
103
|
+
@gateway
|
104
|
+
.expects(:save)
|
105
|
+
.returns({'_id' => 'abc123'})
|
106
|
+
|
107
|
+
subject.save
|
108
|
+
assert_equal Time.parse('2014-01-01T00:00:00Z'), subject.updated_at
|
109
|
+
end
|
110
|
+
|
111
|
+
should "pass the options to gateway" do
|
112
|
+
@gateway
|
113
|
+
.expects(:save)
|
114
|
+
.with do |object, options|
|
115
|
+
assert_equal 'ABC', options[:routing]
|
116
|
+
true
|
117
|
+
end
|
118
|
+
.returns({'_id' => 'abc123'})
|
119
|
+
|
120
|
+
assert subject.save routing: 'ABC'
|
121
|
+
end
|
122
|
+
|
123
|
+
should "return the response" do
|
124
|
+
@gateway
|
125
|
+
.expects(:save)
|
126
|
+
.returns('FOOBAR')
|
127
|
+
|
128
|
+
assert_equal 'FOOBAR', subject.save
|
129
|
+
end
|
130
|
+
|
131
|
+
should "execute the callbacks" do
|
132
|
+
@gateway.expects(:save).returns({'_id' => 'abc'})
|
133
|
+
DummyStoreModelWithCallback = Class.new(DummyStoreModel)
|
134
|
+
|
135
|
+
DummyStoreModelWithCallback.after_save { $stderr.puts "SAVED" }
|
136
|
+
|
137
|
+
$stderr.expects(:puts).with('SAVED')
|
138
|
+
d = DummyStoreModelWithCallback.new name: 'Test'
|
139
|
+
d.save
|
140
|
+
end
|
141
|
+
|
142
|
+
should "save the model to its own index" do
|
143
|
+
@gateway.expects(:save)
|
144
|
+
.with do |model, options|
|
145
|
+
assert_equal 'my_custom_index', options[:index]
|
146
|
+
assert_equal 'my_custom_type', options[:type]
|
147
|
+
true
|
148
|
+
end
|
149
|
+
.returns({'_id' => 'abc'})
|
150
|
+
|
151
|
+
d = DummyStoreModel.new name: 'Test'
|
152
|
+
d.instance_variable_set(:@_index, 'my_custom_index')
|
153
|
+
d.instance_variable_set(:@_type, 'my_custom_type')
|
154
|
+
d.save
|
155
|
+
end
|
156
|
+
|
157
|
+
should "set the meta attributes from response" do
|
158
|
+
@gateway.expects(:save)
|
159
|
+
.with do |model, options|
|
160
|
+
assert_equal 'my_custom_index', options[:index]
|
161
|
+
assert_equal 'my_custom_type', options[:type]
|
162
|
+
true
|
163
|
+
end
|
164
|
+
.returns({'_id' => 'abc', '_index' => 'foo', '_type' => 'bar', '_version' => '100'})
|
165
|
+
|
166
|
+
d = DummyStoreModel.new name: 'Test'
|
167
|
+
d.instance_variable_set(:@_index, 'my_custom_index')
|
168
|
+
d.instance_variable_set(:@_type, 'my_custom_type')
|
169
|
+
d.save
|
170
|
+
|
171
|
+
assert_equal 'foo', d._index
|
172
|
+
assert_equal 'bar', d._type
|
173
|
+
assert_equal '100', d._version
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context "when destroying," do
|
178
|
+
should "remove the model from Elasticsearch" do
|
179
|
+
subject.expects(:persisted?).returns(true)
|
180
|
+
subject.expects(:id).returns('abc123')
|
181
|
+
subject.expects(:freeze).returns(subject)
|
182
|
+
|
183
|
+
@gateway
|
184
|
+
.expects(:delete)
|
185
|
+
.with('abc123', {})
|
186
|
+
.returns({'_id' => 'abc123', 'version' => 2})
|
187
|
+
|
188
|
+
assert subject.destroy
|
189
|
+
assert subject.destroyed?
|
190
|
+
end
|
191
|
+
|
192
|
+
should "pass the options to gateway" do
|
193
|
+
subject.expects(:persisted?).returns(true)
|
194
|
+
subject.expects(:freeze).returns(subject)
|
195
|
+
|
196
|
+
@gateway
|
197
|
+
.expects(:delete)
|
198
|
+
.with do |object, options|
|
199
|
+
assert_equal 'ABC', options[:routing]
|
200
|
+
true
|
201
|
+
end
|
202
|
+
.returns({'_id' => 'abc123'})
|
203
|
+
|
204
|
+
assert subject.destroy routing: 'ABC'
|
205
|
+
end
|
206
|
+
|
207
|
+
should "return the response" do
|
208
|
+
subject.expects(:persisted?).returns(true)
|
209
|
+
subject.expects(:freeze).returns(subject)
|
210
|
+
|
211
|
+
@gateway
|
212
|
+
.expects(:delete)
|
213
|
+
.returns('FOOBAR')
|
214
|
+
|
215
|
+
assert_equal 'FOOBAR', subject.destroy
|
216
|
+
end
|
217
|
+
|
218
|
+
should "execute the callbacks" do
|
219
|
+
@gateway.expects(:delete).returns({'_id' => 'abc'})
|
220
|
+
DummyStoreModelWithCallback = Class.new(DummyStoreModel)
|
221
|
+
|
222
|
+
DummyStoreModelWithCallback.after_destroy { $stderr.puts "DELETED" }
|
223
|
+
|
224
|
+
$stderr.expects(:puts).with('DELETED')
|
225
|
+
d = DummyStoreModelWithCallback.new name: 'Test'
|
226
|
+
d.expects(:persisted?).returns(true)
|
227
|
+
d.expects(:freeze).returns(d)
|
228
|
+
|
229
|
+
d.destroy
|
230
|
+
end
|
231
|
+
|
232
|
+
should "remove the model from its own index" do
|
233
|
+
@gateway.expects(:delete)
|
234
|
+
.with do |model, options|
|
235
|
+
assert_equal 'my_custom_index', options[:index]
|
236
|
+
assert_equal 'my_custom_type', options[:type]
|
237
|
+
true
|
238
|
+
end
|
239
|
+
.returns({'_id' => 'abc'})
|
240
|
+
|
241
|
+
d = DummyStoreModel.new name: 'Test'
|
242
|
+
d.instance_variable_set(:@_index, 'my_custom_index')
|
243
|
+
d.instance_variable_set(:@_type, 'my_custom_type')
|
244
|
+
d.expects(:persisted?).returns(true)
|
245
|
+
d.expects(:freeze).returns(d)
|
246
|
+
|
247
|
+
d.destroy
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context "when updating," do
|
252
|
+
should "update the document with partial attributes" do
|
253
|
+
subject.expects(:persisted?).returns(true)
|
254
|
+
subject.expects(:id).returns('abc123').at_least_once
|
255
|
+
|
256
|
+
@gateway
|
257
|
+
.expects(:update)
|
258
|
+
.with do |id, options|
|
259
|
+
assert_equal 'abc123', id
|
260
|
+
assert_equal 'UPDATED', options[:doc][:title]
|
261
|
+
true
|
262
|
+
end
|
263
|
+
.returns({'_id' => 'abc123', 'version' => 2})
|
264
|
+
|
265
|
+
assert subject.update title: 'UPDATED'
|
266
|
+
|
267
|
+
assert_equal 'UPDATED', subject.title
|
268
|
+
end
|
269
|
+
|
270
|
+
should "allow to update the document with a custom script" do
|
271
|
+
subject.expects(:persisted?).returns(true)
|
272
|
+
subject.expects(:id).returns('abc123').at_least_once
|
273
|
+
|
274
|
+
@gateway
|
275
|
+
.expects(:update)
|
276
|
+
.with do |id, options|
|
277
|
+
assert_equal 'abc123', id
|
278
|
+
assert_equal 'EXEC', options[:script]
|
279
|
+
true
|
280
|
+
end
|
281
|
+
.returns({'_id' => 'abc123', 'version' => 2})
|
282
|
+
|
283
|
+
assert subject.update( {}, { script: 'EXEC' } )
|
284
|
+
end
|
285
|
+
|
286
|
+
should "pass the options to gateway" do
|
287
|
+
subject.expects(:persisted?).returns(true)
|
288
|
+
|
289
|
+
@gateway
|
290
|
+
.expects(:update)
|
291
|
+
.with do |object, options|
|
292
|
+
assert_equal 'ABC', options[:routing]
|
293
|
+
true
|
294
|
+
end
|
295
|
+
.returns({'_id' => 'abc123'})
|
296
|
+
|
297
|
+
assert subject.update( { title: 'UPDATED' }, { routing: 'ABC' } )
|
298
|
+
end
|
299
|
+
|
300
|
+
should "return the response" do
|
301
|
+
subject.expects(:persisted?).returns(true)
|
302
|
+
|
303
|
+
@gateway
|
304
|
+
.expects(:update)
|
305
|
+
.returns('FOOBAR')
|
306
|
+
|
307
|
+
assert_equal 'FOOBAR', subject.update
|
308
|
+
end
|
309
|
+
|
310
|
+
should "execute the callbacks" do
|
311
|
+
@gateway.expects(:update).returns({'_id' => 'abc'})
|
312
|
+
DummyStoreModelWithCallback = Class.new(DummyStoreModel)
|
313
|
+
|
314
|
+
DummyStoreModelWithCallback.after_update { $stderr.puts "UPDATED" }
|
315
|
+
|
316
|
+
$stderr.expects(:puts).with('UPDATED')
|
317
|
+
d = DummyStoreModelWithCallback.new name: 'Test'
|
318
|
+
d.expects(:persisted?).returns(true)
|
319
|
+
d.update name: 'Update'
|
320
|
+
end
|
321
|
+
|
322
|
+
should "update the model in its own index" do
|
323
|
+
@gateway.expects(:update)
|
324
|
+
.with do |model, options|
|
325
|
+
assert_equal 'my_custom_index', options[:index]
|
326
|
+
assert_equal 'my_custom_type', options[:type]
|
327
|
+
true
|
328
|
+
end
|
329
|
+
.returns({'_id' => 'abc'})
|
330
|
+
|
331
|
+
d = DummyStoreModel.new name: 'Test'
|
332
|
+
d.instance_variable_set(:@_index, 'my_custom_index')
|
333
|
+
d.instance_variable_set(:@_type, 'my_custom_type')
|
334
|
+
d.expects(:persisted?).returns(true)
|
335
|
+
|
336
|
+
d.update name: 'Update'
|
337
|
+
end
|
338
|
+
|
339
|
+
should "set the meta attributes from response" do
|
340
|
+
@gateway.expects(:update)
|
341
|
+
.with do |model, options|
|
342
|
+
assert_equal 'my_custom_index', options[:index]
|
343
|
+
assert_equal 'my_custom_type', options[:type]
|
344
|
+
true
|
345
|
+
end
|
346
|
+
.returns({'_id' => 'abc', '_index' => 'foo', '_type' => 'bar', '_version' => '100'})
|
347
|
+
|
348
|
+
d = DummyStoreModel.new name: 'Test'
|
349
|
+
d.instance_variable_set(:@_index, 'my_custom_index')
|
350
|
+
d.instance_variable_set(:@_type, 'my_custom_type')
|
351
|
+
d.expects(:persisted?).returns(true)
|
352
|
+
|
353
|
+
d.update name: 'Update'
|
354
|
+
|
355
|
+
assert_equal 'foo', d._index
|
356
|
+
assert_equal 'bar', d._type
|
357
|
+
assert_equal '100', d._version
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
context "when incrementing," do
|
362
|
+
should "increment the attribute" do
|
363
|
+
subject.expects(:persisted?).returns(true)
|
364
|
+
|
365
|
+
@gateway
|
366
|
+
.expects(:update)
|
367
|
+
.with do |id, options|
|
368
|
+
assert_equal 'ctx._source.count += 1', options[:script]
|
369
|
+
true
|
370
|
+
end
|
371
|
+
.returns({'_id' => 'abc123', 'version' => 2})
|
372
|
+
|
373
|
+
assert subject.increment :count
|
374
|
+
|
375
|
+
assert_equal 1, subject.count
|
376
|
+
end
|
377
|
+
|
378
|
+
should "set the meta attributes from response" do
|
379
|
+
subject.expects(:persisted?).returns(true)
|
380
|
+
|
381
|
+
@gateway.expects(:update)
|
382
|
+
.with do |model, options|
|
383
|
+
assert_equal 'my_custom_index', options[:index]
|
384
|
+
assert_equal 'my_custom_type', options[:type]
|
385
|
+
true
|
386
|
+
end
|
387
|
+
.returns({'_id' => 'abc', '_index' => 'foo', '_type' => 'bar', '_version' => '100'})
|
388
|
+
|
389
|
+
subject.instance_variable_set(:@_index, 'my_custom_index')
|
390
|
+
subject.instance_variable_set(:@_type, 'my_custom_type')
|
391
|
+
|
392
|
+
subject.increment :count
|
393
|
+
|
394
|
+
assert_equal 'foo', subject._index
|
395
|
+
assert_equal 'bar', subject._type
|
396
|
+
assert_equal '100', subject._version
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
context "when decrement," do
|
401
|
+
should "decrement the attribute" do
|
402
|
+
subject.expects(:persisted?).returns(true)
|
403
|
+
|
404
|
+
@gateway
|
405
|
+
.expects(:update)
|
406
|
+
.with do |id, options|
|
407
|
+
assert_equal 'ctx._source.count = ctx._source.count - 1', options[:script]
|
408
|
+
true
|
409
|
+
end
|
410
|
+
.returns({'_id' => 'abc123', 'version' => 2})
|
411
|
+
|
412
|
+
assert subject.decrement :count
|
413
|
+
|
414
|
+
assert_equal -1, subject.count
|
415
|
+
end
|
416
|
+
|
417
|
+
should "set the meta attributes from response" do
|
418
|
+
subject.expects(:persisted?).returns(true)
|
419
|
+
|
420
|
+
@gateway.expects(:update)
|
421
|
+
.with do |model, options|
|
422
|
+
assert_equal 'my_custom_index', options[:index]
|
423
|
+
assert_equal 'my_custom_type', options[:type]
|
424
|
+
true
|
425
|
+
end
|
426
|
+
.returns({'_id' => 'abc', '_index' => 'foo', '_type' => 'bar', '_version' => '100'})
|
427
|
+
|
428
|
+
subject.instance_variable_set(:@_index, 'my_custom_index')
|
429
|
+
subject.instance_variable_set(:@_type, 'my_custom_type')
|
430
|
+
|
431
|
+
subject.decrement :count
|
432
|
+
|
433
|
+
assert_equal 'foo', subject._index
|
434
|
+
assert_equal 'bar', subject._type
|
435
|
+
assert_equal '100', subject._version
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
context "when touching," do
|
440
|
+
should "raise exception when touching not existing attribute" do
|
441
|
+
subject.expects(:persisted?).returns(true)
|
442
|
+
assert_raise(ArgumentError) { subject.touch :foobar }
|
443
|
+
end
|
444
|
+
|
445
|
+
should "update updated_at by default" do
|
446
|
+
subject.expects(:persisted?).returns(true)
|
447
|
+
now = Time.parse('2014-01-01T00:00:00Z')
|
448
|
+
Time.expects(:now).returns(now).at_least_once
|
449
|
+
|
450
|
+
@gateway
|
451
|
+
.expects(:update)
|
452
|
+
.with do |id, options|
|
453
|
+
assert_equal '2014-01-01T00:00:00Z', options[:doc][:updated_at]
|
454
|
+
true
|
455
|
+
end
|
456
|
+
.returns({'_id' => 'abc123', 'version' => 2})
|
457
|
+
|
458
|
+
subject.touch
|
459
|
+
assert_equal Time.parse('2014-01-01T00:00:00Z'), subject.updated_at
|
460
|
+
end
|
461
|
+
|
462
|
+
should "update a custom attribute by default" do
|
463
|
+
subject.expects(:persisted?).returns(true)
|
464
|
+
now = Time.parse('2014-01-01T00:00:00Z')
|
465
|
+
Time.expects(:now).returns(now).at_least_once
|
466
|
+
|
467
|
+
@gateway
|
468
|
+
.expects(:update)
|
469
|
+
.with do |id, options|
|
470
|
+
assert_equal '2014-01-01T00:00:00Z', options[:doc][:created_at]
|
471
|
+
true
|
472
|
+
end
|
473
|
+
.returns({'_id' => 'abc123', 'version' => 2})
|
474
|
+
|
475
|
+
subject.touch :created_at
|
476
|
+
assert_equal Time.parse('2014-01-01T00:00:00Z'), subject.created_at
|
477
|
+
end
|
478
|
+
|
479
|
+
should "execute the callbacks" do
|
480
|
+
@gateway.expects(:update).returns({'_id' => 'abc'})
|
481
|
+
DummyStoreModelWithCallback = Class.new(DummyStoreModel)
|
482
|
+
|
483
|
+
DummyStoreModelWithCallback.after_touch { $stderr.puts "TOUCHED" }
|
484
|
+
|
485
|
+
$stderr.expects(:puts).with('TOUCHED')
|
486
|
+
d = DummyStoreModelWithCallback.new name: 'Test'
|
487
|
+
d.expects(:persisted?).returns(true)
|
488
|
+
d.touch
|
489
|
+
end
|
490
|
+
|
491
|
+
should "set the meta attributes from response" do
|
492
|
+
subject.expects(:persisted?).returns(true)
|
493
|
+
|
494
|
+
@gateway.expects(:update)
|
495
|
+
.with do |model, options|
|
496
|
+
assert_equal 'my_custom_index', options[:index]
|
497
|
+
assert_equal 'my_custom_type', options[:type]
|
498
|
+
true
|
499
|
+
end
|
500
|
+
.returns({'_id' => 'abc', '_index' => 'foo', '_type' => 'bar', '_version' => '100'})
|
501
|
+
|
502
|
+
subject.instance_variable_set(:@_index, 'my_custom_index')
|
503
|
+
subject.instance_variable_set(:@_type, 'my_custom_type')
|
504
|
+
|
505
|
+
subject.touch
|
506
|
+
|
507
|
+
assert_equal 'foo', subject._index
|
508
|
+
assert_equal 'bar', subject._type
|
509
|
+
assert_equal '100', subject._version
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
end
|
514
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Persistence::ModuleTest < Test::Unit::TestCase
|
4
|
+
context "The Persistence module" do
|
5
|
+
|
6
|
+
context "client" do
|
7
|
+
should "have a default client" do
|
8
|
+
client = Elasticsearch::Persistence.client
|
9
|
+
assert_not_nil client
|
10
|
+
assert_instance_of Elasticsearch::Transport::Client, client
|
11
|
+
end
|
12
|
+
|
13
|
+
should "allow to set a client" do
|
14
|
+
begin
|
15
|
+
Elasticsearch::Persistence.client = "Foobar"
|
16
|
+
assert_equal "Foobar", Elasticsearch::Persistence.client
|
17
|
+
ensure
|
18
|
+
Elasticsearch::Persistence.client = nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
should "allow to set a client with DSL" do
|
23
|
+
begin
|
24
|
+
Elasticsearch::Persistence.client "Foobar"
|
25
|
+
assert_equal "Foobar", Elasticsearch::Persistence.client
|
26
|
+
ensure
|
27
|
+
Elasticsearch::Persistence.client = nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Persistence::RepositoryClassTest < Test::Unit::TestCase
|
4
|
+
context "The default repository class" do
|
5
|
+
|
6
|
+
context "when initialized" do
|
7
|
+
should "be created from the module" do
|
8
|
+
repository = Elasticsearch::Persistence::Repository.new
|
9
|
+
assert_instance_of Elasticsearch::Persistence::Repository::Class, repository
|
10
|
+
end
|
11
|
+
|
12
|
+
should "store and access the options" do
|
13
|
+
repository = Elasticsearch::Persistence::Repository::Class.new foo: 'bar'
|
14
|
+
assert_equal 'bar', repository.options[:foo]
|
15
|
+
end
|
16
|
+
|
17
|
+
should "instance eval a passed block" do
|
18
|
+
$foo = 100
|
19
|
+
repository = Elasticsearch::Persistence::Repository::Class.new() { $foo += 1 }
|
20
|
+
assert_equal 101, $foo
|
21
|
+
end
|
22
|
+
|
23
|
+
should "call a passed block with self" do
|
24
|
+
foo = 100
|
25
|
+
repository = Elasticsearch::Persistence::Repository::Class.new do |r|
|
26
|
+
assert_instance_of Elasticsearch::Persistence::Repository::Class, r
|
27
|
+
foo += 1
|
28
|
+
end
|
29
|
+
assert_equal 101, foo
|
30
|
+
end
|
31
|
+
|
32
|
+
should "configure the index name based on options" do
|
33
|
+
repository = Elasticsearch::Persistence::Repository::Class.new index: 'foobar'
|
34
|
+
assert_equal 'foobar', repository.index_name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
should "include the repository methods" do
|
39
|
+
repository = Elasticsearch::Persistence::Repository::Class.new
|
40
|
+
|
41
|
+
%w( index_name document_type klass
|
42
|
+
mappings settings client client=
|
43
|
+
create_index! delete_index! refresh_index!
|
44
|
+
save delete serialize deserialize
|
45
|
+
exists? find search ).each do |method|
|
46
|
+
assert_respond_to repository, method
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Persistence::RepositoryClientTest < Test::Unit::TestCase
|
4
|
+
context "The repository client" do
|
5
|
+
setup do
|
6
|
+
@shoulda_subject = Class.new() { include Elasticsearch::Persistence::Repository::Client }.new
|
7
|
+
end
|
8
|
+
|
9
|
+
should "have a default client" do
|
10
|
+
assert_not_nil subject.client
|
11
|
+
assert_instance_of Elasticsearch::Transport::Client, subject.client
|
12
|
+
end
|
13
|
+
|
14
|
+
should "allow to set a client" do
|
15
|
+
begin
|
16
|
+
subject.client = "Foobar"
|
17
|
+
assert_equal "Foobar", subject.client
|
18
|
+
ensure
|
19
|
+
subject.client = nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
should "allow to set the client with DSL" do
|
24
|
+
begin
|
25
|
+
subject.client "Foobar"
|
26
|
+
assert_equal "Foobar", subject.client
|
27
|
+
ensure
|
28
|
+
subject.client = nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|