elasticsearch-model 6.0.0 → 6.1.0

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.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/README.md +14 -7
  4. data/Rakefile +27 -36
  5. data/elasticsearch-model.gemspec +1 -1
  6. data/examples/activerecord_mapping_completion.rb +2 -15
  7. data/gemfiles/3.0.gemfile +6 -1
  8. data/gemfiles/4.0.gemfile +7 -1
  9. data/gemfiles/5.0.gemfile +6 -0
  10. data/lib/elasticsearch/model.rb +15 -8
  11. data/lib/elasticsearch/model/adapters/active_record.rb +7 -26
  12. data/lib/elasticsearch/model/indexing.rb +5 -3
  13. data/lib/elasticsearch/model/naming.rb +6 -1
  14. data/lib/elasticsearch/model/response.rb +2 -2
  15. data/lib/elasticsearch/model/response/pagination.rb +2 -192
  16. data/lib/elasticsearch/model/response/pagination/kaminari.rb +109 -0
  17. data/lib/elasticsearch/model/response/pagination/will_paginate.rb +95 -0
  18. data/lib/elasticsearch/model/response/result.rb +1 -1
  19. data/lib/elasticsearch/model/version.rb +1 -1
  20. data/spec/elasticsearch/model/adapter_spec.rb +119 -0
  21. data/spec/elasticsearch/model/adapters/active_record/associations_spec.rb +334 -0
  22. data/spec/elasticsearch/model/adapters/active_record/basic_spec.rb +340 -0
  23. data/spec/elasticsearch/model/adapters/active_record/dynamic_index_name_spec.rb +18 -0
  24. data/spec/elasticsearch/model/adapters/active_record/import_spec.rb +187 -0
  25. data/spec/elasticsearch/model/adapters/active_record/multi_model_spec.rb +110 -0
  26. data/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb +38 -0
  27. data/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb +315 -0
  28. data/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb +75 -0
  29. data/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb +61 -0
  30. data/spec/elasticsearch/model/adapters/active_record_spec.rb +207 -0
  31. data/spec/elasticsearch/model/adapters/default_spec.rb +41 -0
  32. data/spec/elasticsearch/model/adapters/mongoid/basic_spec.rb +267 -0
  33. data/spec/elasticsearch/model/adapters/mongoid/multi_model_spec.rb +66 -0
  34. data/spec/elasticsearch/model/adapters/mongoid_spec.rb +235 -0
  35. data/spec/elasticsearch/model/adapters/multiple_spec.rb +125 -0
  36. data/spec/elasticsearch/model/callbacks_spec.rb +33 -0
  37. data/spec/elasticsearch/model/client_spec.rb +66 -0
  38. data/spec/elasticsearch/model/hash_wrapper_spec.rb +12 -0
  39. data/spec/elasticsearch/model/importing_spec.rb +214 -0
  40. data/spec/elasticsearch/model/indexing_spec.rb +918 -0
  41. data/spec/elasticsearch/model/module_spec.rb +101 -0
  42. data/spec/elasticsearch/model/multimodel_spec.rb +55 -0
  43. data/spec/elasticsearch/model/naming_inheritance_spec.rb +184 -0
  44. data/spec/elasticsearch/model/naming_spec.rb +186 -0
  45. data/spec/elasticsearch/model/proxy_spec.rb +107 -0
  46. data/spec/elasticsearch/model/response/aggregations_spec.rb +66 -0
  47. data/spec/elasticsearch/model/response/base_spec.rb +90 -0
  48. data/spec/elasticsearch/model/response/pagination/kaminari_spec.rb +410 -0
  49. data/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb +262 -0
  50. data/spec/elasticsearch/model/response/records_spec.rb +118 -0
  51. data/spec/elasticsearch/model/response/response_spec.rb +131 -0
  52. data/spec/elasticsearch/model/response/result_spec.rb +122 -0
  53. data/spec/elasticsearch/model/response/results_spec.rb +56 -0
  54. data/spec/elasticsearch/model/searching_search_request_spec.rb +112 -0
  55. data/spec/elasticsearch/model/searching_spec.rb +49 -0
  56. data/spec/elasticsearch/model/serializing_spec.rb +22 -0
  57. data/spec/spec_helper.rb +161 -0
  58. data/spec/support/app.rb +21 -0
  59. data/spec/support/app/answer.rb +33 -0
  60. data/spec/support/app/article.rb +22 -0
  61. data/spec/support/app/article_for_pagination.rb +12 -0
  62. data/spec/support/app/article_with_custom_serialization.rb +13 -0
  63. data/spec/support/app/article_with_dynamic_index_name.rb +15 -0
  64. data/spec/support/app/author.rb +9 -0
  65. data/spec/support/app/authorship.rb +4 -0
  66. data/spec/support/app/category.rb +3 -0
  67. data/spec/support/app/comment.rb +3 -0
  68. data/spec/support/app/episode.rb +11 -0
  69. data/spec/support/app/image.rb +19 -0
  70. data/spec/support/app/import_article.rb +12 -0
  71. data/spec/support/app/mongoid_article.rb +21 -0
  72. data/spec/support/app/namespaced_book.rb +10 -0
  73. data/spec/support/app/parent_and_child_searchable.rb +24 -0
  74. data/spec/support/app/post.rb +14 -0
  75. data/spec/support/app/question.rb +27 -0
  76. data/spec/support/app/searchable.rb +48 -0
  77. data/spec/support/app/series.rb +11 -0
  78. data/spec/support/model.json +1 -0
  79. data/{test → spec}/support/model.yml +0 -0
  80. metadata +129 -86
  81. data/test/integration/active_record_associations_parent_child_test.rb +0 -188
  82. data/test/integration/active_record_associations_test.rb +0 -339
  83. data/test/integration/active_record_basic_test.rb +0 -255
  84. data/test/integration/active_record_custom_serialization_test.rb +0 -67
  85. data/test/integration/active_record_import_test.rb +0 -168
  86. data/test/integration/active_record_namespaced_model_test.rb +0 -56
  87. data/test/integration/active_record_pagination_test.rb +0 -149
  88. data/test/integration/dynamic_index_name_test.rb +0 -52
  89. data/test/integration/mongoid_basic_test.rb +0 -240
  90. data/test/integration/multiple_models_test.rb +0 -176
  91. data/test/support/model.json +0 -1
  92. data/test/test_helper.rb +0 -92
  93. data/test/unit/adapter_active_record_test.rb +0 -157
  94. data/test/unit/adapter_default_test.rb +0 -41
  95. data/test/unit/adapter_mongoid_test.rb +0 -161
  96. data/test/unit/adapter_multiple_test.rb +0 -106
  97. data/test/unit/adapter_test.rb +0 -69
  98. data/test/unit/callbacks_test.rb +0 -31
  99. data/test/unit/client_test.rb +0 -27
  100. data/test/unit/hash_wrapper_test.rb +0 -13
  101. data/test/unit/importing_test.rb +0 -224
  102. data/test/unit/indexing_test.rb +0 -720
  103. data/test/unit/module_test.rb +0 -68
  104. data/test/unit/multimodel_test.rb +0 -38
  105. data/test/unit/naming_inheritance_test.rb +0 -94
  106. data/test/unit/naming_test.rb +0 -103
  107. data/test/unit/proxy_test.rb +0 -98
  108. data/test/unit/response_aggregations_test.rb +0 -46
  109. data/test/unit/response_base_test.rb +0 -40
  110. data/test/unit/response_pagination_kaminari_test.rb +0 -433
  111. data/test/unit/response_pagination_will_paginate_test.rb +0 -398
  112. data/test/unit/response_records_test.rb +0 -91
  113. data/test/unit/response_result_test.rb +0 -90
  114. data/test/unit/response_results_test.rb +0 -34
  115. data/test/unit/response_test.rb +0 -104
  116. data/test/unit/searching_search_request_test.rb +0 -78
  117. data/test/unit/searching_test.rb +0 -41
  118. data/test/unit/serializing_test.rb +0 -17
@@ -0,0 +1,340 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticsearch::Model::Adapter::ActiveRecord do
4
+
5
+ before(:all) do
6
+ ActiveRecord::Schema.define(:version => 1) do
7
+ create_table :articles do |t|
8
+ t.string :title
9
+ t.string :body
10
+ t.integer :clicks, :default => 0
11
+ t.datetime :created_at, :default => 'NOW()'
12
+ end
13
+ end
14
+
15
+ Article.delete_all
16
+ Article.__elasticsearch__.create_index!(force: true)
17
+
18
+ Article.create!(title: 'Test', body: '', clicks: 1)
19
+ Article.create!(title: 'Testing Coding', body: '', clicks: 2)
20
+ Article.create!(title: 'Coding', body: '', clicks: 3)
21
+
22
+ Article.__elasticsearch__.refresh_index!
23
+ end
24
+
25
+ describe 'indexing a document' do
26
+
27
+ let(:search_result) do
28
+ Article.search('title:test')
29
+ end
30
+
31
+ it 'allows searching for documents' do
32
+ expect(search_result.results.size).to be(2)
33
+ expect(search_result.records.size).to be(2)
34
+ end
35
+ end
36
+
37
+ describe '#results' do
38
+
39
+ let(:search_result) do
40
+ Article.search('title:test')
41
+ end
42
+
43
+ it 'returns an instance of Response::Result' do
44
+ expect(search_result.results.first).to be_a(Elasticsearch::Model::Response::Result)
45
+ end
46
+
47
+ it 'prooperly loads the document' do
48
+ expect(search_result.results.first.title).to eq('Test')
49
+ end
50
+
51
+ context 'when the result contains other data' do
52
+
53
+ let(:search_result) do
54
+ Article.search(query: { match: { title: 'test' } }, highlight: { fields: { title: {} } })
55
+ end
56
+
57
+ it 'allows access to the Elasticsearch result' do
58
+ expect(search_result.results.first.title).to eq('Test')
59
+ expect(search_result.results.first.title?).to be(true)
60
+ expect(search_result.results.first.boo?).to be(false)
61
+ expect(search_result.results.first.highlight?).to be(true)
62
+ expect(search_result.results.first.highlight.title?).to be(true)
63
+ expect(search_result.results.first.highlight.boo?).to be(false)
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '#records' do
69
+
70
+ let(:search_result) do
71
+ Article.search('title:test')
72
+ end
73
+
74
+ it 'returns an instance of the model' do
75
+ expect(search_result.records.first).to be_a(Article)
76
+ end
77
+
78
+ it 'prooperly loads the document' do
79
+ expect(search_result.records.first.title).to eq('Test')
80
+ end
81
+ end
82
+
83
+ describe 'Enumerable' do
84
+
85
+ let(:search_result) do
86
+ Article.search('title:test')
87
+ end
88
+
89
+ it 'allows iteration over results' do
90
+ expect(search_result.results.map(&:_id)).to eq(['1', '2'])
91
+ end
92
+
93
+ it 'allows iteration over records' do
94
+ expect(search_result.records.map(&:id)).to eq([1, 2])
95
+ end
96
+ end
97
+
98
+ describe '#id' do
99
+
100
+ let(:search_result) do
101
+ Article.search('title:test')
102
+ end
103
+
104
+ it 'returns the id' do
105
+ expect(search_result.results.first.id).to eq('1')
106
+ end
107
+ end
108
+
109
+ describe '#id' do
110
+
111
+ let(:search_result) do
112
+ Article.search('title:test')
113
+ end
114
+
115
+ it 'returns the type' do
116
+ expect(search_result.results.first.type).to eq('article')
117
+ end
118
+ end
119
+
120
+ describe '#each_with_hit' do
121
+
122
+ let(:search_result) do
123
+ Article.search('title:test')
124
+ end
125
+
126
+ it 'returns the record with the Elasticsearch hit' do
127
+ search_result.records.each_with_hit do |r, h|
128
+ expect(h._score).not_to be_nil
129
+ expect(h._source.title).not_to be_nil
130
+ end
131
+ end
132
+ end
133
+
134
+ describe 'search results order' do
135
+
136
+ let(:search_result) do
137
+ Article.search(query: { match: { title: 'code' }}, sort: { clicks: :desc })
138
+ end
139
+
140
+ it 'preserves the search results order when accessing a single record' do
141
+ expect(search_result.records[0].clicks).to be(3)
142
+ expect(search_result.records[1].clicks).to be(2)
143
+ expect(search_result.records.first).to eq(search_result.records[0])
144
+ end
145
+
146
+ it 'preserves the search results order for the list of records' do
147
+ search_result.records.each_with_hit do |r, h|
148
+ expect(r.id.to_s).to eq(h._id)
149
+ end
150
+
151
+ search_result.records.map_with_hit do |r, h|
152
+ expect(r.id.to_s).to eq(h._id)
153
+ end
154
+ end
155
+ end
156
+
157
+ describe 'a paged collection' do
158
+
159
+ let(:search_result) do
160
+ Article.search(query: { match: { title: { query: 'test' } } },
161
+ size: 2,
162
+ from: 1)
163
+ end
164
+
165
+ it 'applies the paged options to the search' do
166
+ expect(search_result.results.size).to eq(1)
167
+ expect(search_result.results.first.title).to eq('Testing Coding')
168
+ expect(search_result.records.size).to eq(1)
169
+ expect(search_result.records.first.title).to eq('Testing Coding')
170
+ end
171
+ end
172
+
173
+ describe '#destroy' do
174
+
175
+ before do
176
+ Article.create!(title: 'destroy', body: '', clicks: 1)
177
+ Article.__elasticsearch__.refresh_index!
178
+ Article.where(title: 'destroy').first.destroy
179
+
180
+ Article.__elasticsearch__.refresh_index!
181
+ end
182
+
183
+ let(:search_result) do
184
+ Article.search('title:test')
185
+ end
186
+
187
+ it 'removes the document from the index' do
188
+ expect(Article.count).to eq(3)
189
+ expect(search_result.results.size).to eq(2)
190
+ expect(search_result.records.size).to eq(2)
191
+ end
192
+ end
193
+
194
+ describe 'full document updates' do
195
+
196
+ before do
197
+ article = Article.create!(title: 'update', body: '', clicks: 1)
198
+ Article.__elasticsearch__.refresh_index!
199
+ article.title = 'Writing'
200
+ article.save
201
+
202
+ Article.__elasticsearch__.refresh_index!
203
+ end
204
+
205
+ let(:search_result) do
206
+ Article.search('title:write')
207
+ end
208
+
209
+ it 'applies the update' do
210
+ expect(search_result.results.size).to eq(1)
211
+ expect(search_result.records.size).to eq(1)
212
+ end
213
+ end
214
+
215
+ describe 'attribute updates' do
216
+
217
+ before do
218
+ article = Article.create!(title: 'update', body: '', clicks: 1)
219
+ Article.__elasticsearch__.refresh_index!
220
+ article.title = 'special'
221
+ article.save
222
+
223
+ Article.__elasticsearch__.refresh_index!
224
+ end
225
+
226
+ let(:search_result) do
227
+ Article.search('title:special')
228
+ end
229
+
230
+ it 'applies the update' do
231
+ expect(search_result.results.size).to eq(1)
232
+ expect(search_result.records.size).to eq(1)
233
+ end
234
+ end
235
+
236
+ describe '#save' do
237
+
238
+ before do
239
+ article = Article.create!(title: 'save', body: '', clicks: 1)
240
+
241
+ ActiveRecord::Base.transaction do
242
+ article.body = 'dummy'
243
+ article.save
244
+
245
+ article.title = 'special'
246
+ article.save
247
+ end
248
+
249
+ article.__elasticsearch__.update_document
250
+ Article.__elasticsearch__.refresh_index!
251
+ end
252
+
253
+ let(:search_result) do
254
+ Article.search('body:dummy')
255
+ end
256
+
257
+ it 'applies the save' do
258
+ expect(search_result.results.size).to eq(1)
259
+ expect(search_result.records.size).to eq(1)
260
+ end
261
+ end
262
+
263
+ describe 'a DSL search' do
264
+
265
+ let(:search_result) do
266
+ Article.search(query: { match: { title: { query: 'test' } } })
267
+ end
268
+
269
+ it 'returns the results' do
270
+ expect(search_result.results.size).to eq(2)
271
+ expect(search_result.records.size).to eq(2)
272
+ end
273
+ end
274
+
275
+ describe 'chaining SQL queries on response.records' do
276
+
277
+ let(:search_result) do
278
+ Article.search(query: { match: { title: { query: 'test' } } })
279
+ end
280
+
281
+ it 'executes the SQL request with the chained query criteria' do
282
+ expect(search_result.records.size).to eq(2)
283
+ expect(search_result.records.where(title: 'Test').size).to eq(1)
284
+ expect(search_result.records.where(title: 'Test').first.title).to eq('Test')
285
+ end
286
+ end
287
+
288
+ describe 'ordering of SQL queries' do
289
+
290
+ context 'when order is called on the ActiveRecord query' do
291
+
292
+ let(:search_result) do
293
+ Article.search query: { match: { title: { query: 'test' } } }
294
+ end
295
+
296
+ it 'allows the SQL query to be ordered independent of the Elasticsearch results order', unless: active_record_at_least_4? do
297
+ expect(search_result.records.order('title DESC').first.title).to eq('Testing Coding')
298
+ expect(search_result.records.order('title DESC')[0].title).to eq('Testing Coding')
299
+ end
300
+
301
+ it 'allows the SQL query to be ordered independent of the Elasticsearch results order', if: active_record_at_least_4? do
302
+ expect(search_result.records.order(title: :desc).first.title).to eq('Testing Coding')
303
+ expect(search_result.records.order(title: :desc)[0].title).to eq('Testing Coding')
304
+ end
305
+ end
306
+
307
+ context 'when more methods are chained on the ActiveRecord query' do
308
+
309
+ let(:search_result) do
310
+ Article.search query: {match: {title: {query: 'test'}}}
311
+ end
312
+
313
+ it 'allows the SQL query to be ordered independent of the Elasticsearch results order', if: active_record_at_least_4? do
314
+ expect(search_result.records.distinct.order(title: :desc).first.title).to eq('Testing Coding')
315
+ expect(search_result.records.distinct.order(title: :desc)[0].title).to eq('Testing Coding')
316
+ end
317
+ end
318
+ end
319
+
320
+ describe 'access to the response via methods' do
321
+
322
+ let(:search_result) do
323
+ Article.search(query: { match: { title: { query: 'test' } } },
324
+ aggregations: {
325
+ dates: { date_histogram: { field: 'created_at', interval: 'hour' } },
326
+ clicks: { global: {}, aggregations: { min: { min: { field: 'clicks' } } } }
327
+ },
328
+ suggest: { text: 'tezt', title: { term: { field: 'title', suggest_mode: 'always' } } })
329
+ end
330
+
331
+ it 'allows document keys to be access via methods' do
332
+ expect(search_result.aggregations.dates.buckets.first.doc_count).to eq(2)
333
+ expect(search_result.aggregations.clicks.doc_count).to eq(6)
334
+ expect(search_result.aggregations.clicks.min.value).to eq(1.0)
335
+ expect(search_result.aggregations.clicks.max).to be_nil
336
+ expect(search_result.suggestions.title.first.options.size).to eq(1)
337
+ expect(search_result.suggestions.terms).to eq(['test'])
338
+ end
339
+ end
340
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Elasticsearch::Model::Adapter::ActiveRecord Dynamic Index naming' do
4
+
5
+ before do
6
+ ArticleWithDynamicIndexName.counter = 0
7
+ end
8
+
9
+ it 'exavlues the index_name value' do
10
+ expect(ArticleWithDynamicIndexName.index_name).to eq('articles-1')
11
+ end
12
+
13
+ it 'revaluates the index name with each call' do
14
+ expect(ArticleWithDynamicIndexName.index_name).to eq('articles-1')
15
+ expect(ArticleWithDynamicIndexName.index_name).to eq('articles-2')
16
+ expect(ArticleWithDynamicIndexName.index_name).to eq('articles-3')
17
+ end
18
+ end
@@ -0,0 +1,187 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Elasticsearch::Model::Adapter::ActiveRecord Importing' do
4
+
5
+ before(:all) do
6
+ ActiveRecord::Schema.define(:version => 1) do
7
+ create_table :import_articles do |t|
8
+ t.string :title
9
+ t.integer :views
10
+ t.string :numeric # For the sake of invalid data sent to Elasticsearch
11
+ t.datetime :created_at, :default => 'NOW()'
12
+ end
13
+ end
14
+
15
+ ImportArticle.delete_all
16
+ ImportArticle.__elasticsearch__.client.cluster.health(wait_for_status: 'yellow')
17
+ end
18
+
19
+ before do
20
+ ImportArticle.__elasticsearch__.create_index!
21
+ end
22
+
23
+ after do
24
+ clear_indices(ImportArticle)
25
+ clear_tables(ImportArticle)
26
+ end
27
+
28
+ describe '#import' do
29
+
30
+ context 'when no search criteria is specified' do
31
+
32
+ before do
33
+ 10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
34
+ ImportArticle.import
35
+ ImportArticle.__elasticsearch__.refresh_index!
36
+ end
37
+
38
+ it 'imports all documents' do
39
+ expect(ImportArticle.search('*').results.total).to eq(10)
40
+ end
41
+ end
42
+
43
+ context 'when batch size is specified' do
44
+
45
+ before do
46
+ 10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
47
+ end
48
+
49
+ let!(:batch_count) do
50
+ batches = 0
51
+ errors = ImportArticle.import(batch_size: 5) do |response|
52
+ batches += 1
53
+ end
54
+ ImportArticle.__elasticsearch__.refresh_index!
55
+ batches
56
+ end
57
+
58
+ it 'imports using the batch size' do
59
+ expect(batch_count).to eq(2)
60
+ end
61
+
62
+ it 'imports all the documents' do
63
+ expect(ImportArticle.search('*').results.total).to eq(10)
64
+ end
65
+ end
66
+
67
+ context 'when a scope is specified' do
68
+
69
+ before do
70
+ 10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
71
+ ImportArticle.import(scope: 'popular', force: true)
72
+ ImportArticle.__elasticsearch__.refresh_index!
73
+ end
74
+
75
+ it 'applies the scope' do
76
+ expect(ImportArticle.search('*').results.total).to eq(5)
77
+ end
78
+ end
79
+
80
+ context 'when a query is specified' do
81
+
82
+ before do
83
+ 10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
84
+ ImportArticle.import(query: -> { where('views >= 3') })
85
+ ImportArticle.__elasticsearch__.refresh_index!
86
+ end
87
+
88
+ it 'applies the query' do
89
+ expect(ImportArticle.search('*').results.total).to eq(7)
90
+ end
91
+ end
92
+
93
+ context 'when there are invalid documents' do
94
+
95
+ let!(:result) do
96
+ 10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
97
+ new_article
98
+ batches = 0
99
+ errors = ImportArticle.__elasticsearch__.import(batch_size: 5) do |response|
100
+ batches += 1
101
+ end
102
+ ImportArticle.__elasticsearch__.refresh_index!
103
+ { batch_size: batches, errors: errors}
104
+ end
105
+
106
+ let(:new_article) do
107
+ ImportArticle.create!(title: "Test INVALID", numeric: "INVALID")
108
+ end
109
+
110
+ it 'does not import them' do
111
+ expect(ImportArticle.search('*').results.total).to eq(10)
112
+ expect(result[:batch_size]).to eq(3)
113
+ expect(result[:errors]).to eq(1)
114
+ end
115
+ end
116
+
117
+ context 'when a transform proc is specified' do
118
+
119
+ before do
120
+ 10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
121
+ ImportArticle.import( transform: ->(a) {{ index: { data: { name: a.title, foo: 'BAR' } }}} )
122
+ ImportArticle.__elasticsearch__.refresh_index!
123
+ end
124
+
125
+ it 'transforms the documents' do
126
+ expect(ImportArticle.search('*').results.first._source.keys).to include('name')
127
+ expect(ImportArticle.search('*').results.first._source.keys).to include('foo')
128
+ end
129
+
130
+ it 'imports all documents' do
131
+ expect(ImportArticle.search('test').results.total).to eq(10)
132
+ expect(ImportArticle.search('bar').results.total).to eq(10)
133
+ end
134
+ end
135
+
136
+ context 'when the model has a default scope' do
137
+
138
+ around(:all) do |example|
139
+ 10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
140
+ ImportArticle.instance_eval { default_scope { where('views > 3') } }
141
+ example.run
142
+ ImportArticle.default_scopes.pop
143
+ end
144
+
145
+ before do
146
+ ImportArticle.__elasticsearch__.import
147
+ ImportArticle.__elasticsearch__.refresh_index!
148
+ end
149
+
150
+ it 'uses the default scope' do
151
+ expect(ImportArticle.search('*').results.total).to eq(6)
152
+ end
153
+ end
154
+
155
+ context 'when there is a default scope and a query specified' do
156
+
157
+ around(:all) do |example|
158
+ 10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
159
+ ImportArticle.instance_eval { default_scope { where('views > 3') } }
160
+ example.run
161
+ ImportArticle.default_scopes.pop
162
+ end
163
+
164
+ before do
165
+ ImportArticle.import(query: -> { where('views <= 4') })
166
+ ImportArticle.__elasticsearch__.refresh_index!
167
+ end
168
+
169
+ it 'combines the query and the default scope' do
170
+ expect(ImportArticle.search('*').results.total).to eq(1)
171
+ end
172
+ end
173
+
174
+ context 'when the batch is empty' do
175
+
176
+ before do
177
+ ImportArticle.delete_all
178
+ ImportArticle.import
179
+ ImportArticle.__elasticsearch__.refresh_index!
180
+ end
181
+
182
+ it 'does not make any requests to create documents' do
183
+ expect(ImportArticle.search('*').results.total).to eq(0)
184
+ end
185
+ end
186
+ end
187
+ end