tire 0.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.
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +435 -0
- data/Rakefile +75 -0
- data/examples/dsl.rb +73 -0
- data/examples/rails-application-template.rb +144 -0
- data/examples/tire-dsl.rb +617 -0
- data/lib/tire.rb +35 -0
- data/lib/tire/client.rb +40 -0
- data/lib/tire/configuration.rb +29 -0
- data/lib/tire/dsl.rb +33 -0
- data/lib/tire/index.rb +209 -0
- data/lib/tire/logger.rb +60 -0
- data/lib/tire/model/callbacks.rb +23 -0
- data/lib/tire/model/import.rb +18 -0
- data/lib/tire/model/indexing.rb +50 -0
- data/lib/tire/model/naming.rb +30 -0
- data/lib/tire/model/persistence.rb +34 -0
- data/lib/tire/model/persistence/attributes.rb +60 -0
- data/lib/tire/model/persistence/finders.rb +61 -0
- data/lib/tire/model/persistence/storage.rb +75 -0
- data/lib/tire/model/search.rb +97 -0
- data/lib/tire/results/collection.rb +56 -0
- data/lib/tire/results/item.rb +39 -0
- data/lib/tire/results/pagination.rb +30 -0
- data/lib/tire/rubyext/hash.rb +3 -0
- data/lib/tire/rubyext/symbol.rb +11 -0
- data/lib/tire/search.rb +117 -0
- data/lib/tire/search/facet.rb +41 -0
- data/lib/tire/search/filter.rb +28 -0
- data/lib/tire/search/highlight.rb +37 -0
- data/lib/tire/search/query.rb +42 -0
- data/lib/tire/search/sort.rb +29 -0
- data/lib/tire/tasks.rb +88 -0
- data/lib/tire/version.rb +3 -0
- data/test/fixtures/articles/1.json +1 -0
- data/test/fixtures/articles/2.json +1 -0
- data/test/fixtures/articles/3.json +1 -0
- data/test/fixtures/articles/4.json +1 -0
- data/test/fixtures/articles/5.json +1 -0
- data/test/integration/active_model_searchable_test.rb +80 -0
- data/test/integration/active_record_searchable_test.rb +193 -0
- data/test/integration/facets_test.rb +65 -0
- data/test/integration/filters_test.rb +46 -0
- data/test/integration/highlight_test.rb +52 -0
- data/test/integration/index_mapping_test.rb +44 -0
- data/test/integration/index_store_test.rb +68 -0
- data/test/integration/persistent_model_test.rb +35 -0
- data/test/integration/query_string_test.rb +43 -0
- data/test/integration/results_test.rb +28 -0
- data/test/integration/sort_test.rb +36 -0
- data/test/models/active_model_article.rb +31 -0
- data/test/models/active_model_article_with_callbacks.rb +49 -0
- data/test/models/active_model_article_with_custom_index_name.rb +5 -0
- data/test/models/active_record_article.rb +12 -0
- data/test/models/article.rb +15 -0
- data/test/models/persistent_article.rb +11 -0
- data/test/models/persistent_articles_with_custom_index_name.rb +10 -0
- data/test/models/supermodel_article.rb +22 -0
- data/test/models/validated_model.rb +11 -0
- data/test/test_helper.rb +52 -0
- data/test/unit/active_model_lint_test.rb +17 -0
- data/test/unit/client_test.rb +43 -0
- data/test/unit/configuration_test.rb +71 -0
- data/test/unit/index_test.rb +390 -0
- data/test/unit/logger_test.rb +114 -0
- data/test/unit/model_callbacks_test.rb +90 -0
- data/test/unit/model_import_test.rb +71 -0
- data/test/unit/model_persistence_test.rb +400 -0
- data/test/unit/model_search_test.rb +289 -0
- data/test/unit/results_collection_test.rb +131 -0
- data/test/unit/results_item_test.rb +59 -0
- data/test/unit/rubyext_hash_test.rb +19 -0
- data/test/unit/search_facet_test.rb +69 -0
- data/test/unit/search_filter_test.rb +36 -0
- data/test/unit/search_highlight_test.rb +46 -0
- data/test/unit/search_query_test.rb +55 -0
- data/test/unit/search_sort_test.rb +50 -0
- data/test/unit/search_test.rb +204 -0
- data/test/unit/tire_test.rb +55 -0
- data/tire.gemspec +54 -0
- metadata +372 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Tire
|
4
|
+
|
5
|
+
class ClientTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context "Base" do
|
8
|
+
setup { @http ||= Client::Base.new }
|
9
|
+
|
10
|
+
should "have abstract methods" do
|
11
|
+
assert_raise(ArgumentError) { @http.get }
|
12
|
+
assert_raise(NoMethodError) { @http.get 'URL' }
|
13
|
+
|
14
|
+
assert_raise(ArgumentError) { @http.post }
|
15
|
+
assert_raise(ArgumentError) { @http.post 'URL' }
|
16
|
+
assert_raise(NoMethodError) { @http.post 'URL', 'DATA' }
|
17
|
+
|
18
|
+
assert_raise(ArgumentError) { @http.put }
|
19
|
+
assert_raise(ArgumentError) { @http.put 'URL' }
|
20
|
+
|
21
|
+
assert_raise(ArgumentError) { @http.delete }
|
22
|
+
assert_raise(NoMethodError) { @http.delete 'URL' }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "RestClient" do
|
27
|
+
|
28
|
+
should "be default" do
|
29
|
+
assert_equal Client::RestClient, Configuration.client
|
30
|
+
end
|
31
|
+
|
32
|
+
should "respond to HTTP methods" do
|
33
|
+
assert_respond_to Client::RestClient, :get
|
34
|
+
assert_respond_to Client::RestClient, :post
|
35
|
+
assert_respond_to Client::RestClient, :put
|
36
|
+
assert_respond_to Client::RestClient, :delete
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Tire
|
4
|
+
|
5
|
+
class ConfigurationTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def teardown
|
8
|
+
Tire::Configuration.reset
|
9
|
+
end
|
10
|
+
|
11
|
+
context "Configuration" do
|
12
|
+
setup do
|
13
|
+
Configuration.instance_variable_set(:@url, nil)
|
14
|
+
Configuration.instance_variable_set(:@client, nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
teardown do
|
18
|
+
Configuration.reset
|
19
|
+
end
|
20
|
+
|
21
|
+
should "return default URL" do
|
22
|
+
assert_equal 'http://localhost:9200', Configuration.url
|
23
|
+
end
|
24
|
+
|
25
|
+
should "allow setting and retrieving the URL" do
|
26
|
+
assert_nothing_raised { Configuration.url 'http://example.com' }
|
27
|
+
assert_equal 'http://example.com', Configuration.url
|
28
|
+
end
|
29
|
+
|
30
|
+
should "return default client" do
|
31
|
+
assert_equal Client::RestClient, Configuration.client
|
32
|
+
end
|
33
|
+
|
34
|
+
should "allow setting and retrieving the client" do
|
35
|
+
assert_nothing_raised { Configuration.client Client::Base }
|
36
|
+
assert_equal Client::Base, Configuration.client
|
37
|
+
end
|
38
|
+
|
39
|
+
should "return nil as logger by default" do
|
40
|
+
assert_nil Configuration.logger
|
41
|
+
end
|
42
|
+
|
43
|
+
should "return set and return logger" do
|
44
|
+
Configuration.logger STDERR
|
45
|
+
assert_not_nil Configuration.logger
|
46
|
+
assert_instance_of Tire::Logger, Configuration.logger
|
47
|
+
end
|
48
|
+
|
49
|
+
should "allow to reset the configuration for specific property" do
|
50
|
+
Configuration.url 'http://example.com'
|
51
|
+
Configuration.client Client::Base
|
52
|
+
assert_equal 'http://example.com', Configuration.url
|
53
|
+
Configuration.reset :url
|
54
|
+
assert_equal 'http://localhost:9200', Configuration.url
|
55
|
+
assert_equal Client::Base, Configuration.client
|
56
|
+
end
|
57
|
+
|
58
|
+
should "allow to reset the configuration for all properties" do
|
59
|
+
Configuration.url 'http://example.com'
|
60
|
+
Configuration.client Client::Base
|
61
|
+
assert_equal 'http://example.com', Configuration.url
|
62
|
+
assert_equal Client::Base, Configuration.client
|
63
|
+
Configuration.reset
|
64
|
+
assert_equal 'http://localhost:9200', Configuration.url
|
65
|
+
assert_equal Client::RestClient, Configuration.client
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,390 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Tire
|
4
|
+
|
5
|
+
class IndexTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context "Index" do
|
8
|
+
|
9
|
+
setup do
|
10
|
+
@index = Tire::Index.new 'dummy'
|
11
|
+
end
|
12
|
+
|
13
|
+
should "have a name" do
|
14
|
+
assert_equal 'dummy', @index.name
|
15
|
+
end
|
16
|
+
|
17
|
+
should "return true when exists" do
|
18
|
+
Configuration.client.expects(:get).returns(mock_response('{"dummy":{"document":{"properties":{}}}}'))
|
19
|
+
assert @index.exists?
|
20
|
+
end
|
21
|
+
|
22
|
+
should "return false when does not exist" do
|
23
|
+
Configuration.client.expects(:get).raises(RestClient::ResourceNotFound)
|
24
|
+
assert ! @index.exists?
|
25
|
+
end
|
26
|
+
|
27
|
+
should "create new index" do
|
28
|
+
Configuration.client.expects(:post).returns(mock_response('{"ok":true,"acknowledged":true}'))
|
29
|
+
assert @index.create
|
30
|
+
end
|
31
|
+
|
32
|
+
should "not raise exception and just return false when trying to create existing index" do
|
33
|
+
Configuration.client.expects(:post).raises(RestClient::BadRequest)
|
34
|
+
assert_nothing_raised { assert ! @index.create }
|
35
|
+
end
|
36
|
+
|
37
|
+
should "delete index" do
|
38
|
+
Configuration.client.expects(:delete).returns(mock_response('{"ok":true,"acknowledged":true}'))
|
39
|
+
assert @index.delete
|
40
|
+
end
|
41
|
+
|
42
|
+
should "not raise exception and just return false when deleting non-existing index" do
|
43
|
+
Configuration.client.expects(:delete).returns(mock_response('{"error":"[articles] missing"}'))
|
44
|
+
assert_nothing_raised { assert ! @index.delete }
|
45
|
+
Configuration.client.expects(:delete).raises(RestClient::BadRequest)
|
46
|
+
assert_nothing_raised { assert ! @index.delete }
|
47
|
+
end
|
48
|
+
|
49
|
+
should "refresh the index" do
|
50
|
+
Configuration.client.expects(:post).returns(mock_response('{"ok":true,"_shards":{}}'))
|
51
|
+
assert_nothing_raised { assert @index.refresh }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "mapping" do
|
55
|
+
|
56
|
+
should "create index with mapping" do
|
57
|
+
Configuration.client.expects(:post).returns(mock_response('{"ok":true,"acknowledged":true}'))
|
58
|
+
|
59
|
+
assert @index.create :settings => { :number_of_shards => 1 },
|
60
|
+
:mappings => { :article => {
|
61
|
+
:properties => {
|
62
|
+
:title => { :boost => 2.0,
|
63
|
+
:type => 'string',
|
64
|
+
:store => 'yes',
|
65
|
+
:analyzer => 'snowball' }
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
should "return the mapping" do
|
72
|
+
json =<<-JSON
|
73
|
+
{
|
74
|
+
"dummy" : {
|
75
|
+
"article" : {
|
76
|
+
"properties" : {
|
77
|
+
"title" : { "type" : "string", "boost" : 2.0 },
|
78
|
+
"category" : { "type" : "string", "analyzed" : "no" }
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
JSON
|
84
|
+
Configuration.client.stubs(:get).returns(mock_response(json))
|
85
|
+
|
86
|
+
assert_equal 'string', @index.mapping['article']['properties']['title']['type']
|
87
|
+
assert_equal 2.0, @index.mapping['article']['properties']['title']['boost']
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
context "when storing" do
|
93
|
+
|
94
|
+
should "properly set type from args" do
|
95
|
+
Configuration.client.expects(:post).with("#{Configuration.url}/dummy/article/", '{"title":"Test"}').returns(mock_response('{"ok":true,"_id":"test"}')).twice
|
96
|
+
@index.store 'article', :title => 'Test'
|
97
|
+
@index.store :article, :title => 'Test'
|
98
|
+
end
|
99
|
+
|
100
|
+
should "set default type" do
|
101
|
+
Configuration.client.expects(:post).with("#{Configuration.url}/dummy/document/", '{"title":"Test"}').returns(mock_response('{"ok":true,"_id":"test"}'))
|
102
|
+
@index.store :title => 'Test'
|
103
|
+
end
|
104
|
+
|
105
|
+
should "call #to_indexed_json on non-String documents" do
|
106
|
+
document = { :title => 'Test' }
|
107
|
+
Configuration.client.expects(:post).returns(mock_response('{"ok":true,"_id":"test"}'))
|
108
|
+
document.expects(:to_indexed_json)
|
109
|
+
@index.store document
|
110
|
+
end
|
111
|
+
|
112
|
+
should "raise error when storing neither String nor object with #to_indexed_json method" do
|
113
|
+
class MyDocument;end; document = MyDocument.new
|
114
|
+
assert_raise(ArgumentError) { @index.store document }
|
115
|
+
end
|
116
|
+
|
117
|
+
context "document with ID" do
|
118
|
+
|
119
|
+
should "store Hash it under its ID property" do
|
120
|
+
Configuration.client.expects(:post).with("#{Configuration.url}/dummy/document/123",
|
121
|
+
Yajl::Encoder.encode({:id => 123, :title => 'Test'})).
|
122
|
+
returns(mock_response('{"ok":true,"_id":"123"}'))
|
123
|
+
@index.store :id => 123, :title => 'Test'
|
124
|
+
end
|
125
|
+
|
126
|
+
should "store a custom class under its ID property" do
|
127
|
+
Configuration.client.expects(:post).with("#{Configuration.url}/dummy/document/123",
|
128
|
+
{:id => 123, :title => 'Test', :body => 'Lorem'}.to_json).
|
129
|
+
returns(mock_response('{"ok":true,"_id":"123"}'))
|
130
|
+
@index.store Article.new(:id => 123, :title => 'Test', :body => 'Lorem')
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
context "when retrieving" do
|
138
|
+
|
139
|
+
setup do
|
140
|
+
Configuration.reset :wrapper
|
141
|
+
|
142
|
+
Configuration.client.stubs(:post).with("#{Configuration.url}/dummy/article/", '{"title":"Test"}').
|
143
|
+
returns(mock_response('{"ok":true,"_id":"id-1"}'))
|
144
|
+
@index.store :article, :title => 'Test'
|
145
|
+
end
|
146
|
+
|
147
|
+
should "return document in default wrapper" do
|
148
|
+
Configuration.client.expects(:get).with("#{Configuration.url}/dummy/article/id-1").
|
149
|
+
returns(mock_response('{"_id":"id-1","_version":1, "_source" : {"title":"Test"}}'))
|
150
|
+
article = @index.retrieve :article, 'id-1'
|
151
|
+
assert_instance_of Results::Item, article
|
152
|
+
assert_equal 'Test', article.title
|
153
|
+
assert_equal 'Test', article[:title]
|
154
|
+
end
|
155
|
+
|
156
|
+
should "return document as a hash" do
|
157
|
+
Configuration.wrapper Hash
|
158
|
+
|
159
|
+
Configuration.client.expects(:get).with("#{Configuration.url}/dummy/article/id-1").
|
160
|
+
returns(mock_response('{"_id":"id-1","_version":1, "_source" : {"title":"Test"}}'))
|
161
|
+
article = @index.retrieve :article, 'id-1'
|
162
|
+
assert_instance_of Hash, article
|
163
|
+
end
|
164
|
+
|
165
|
+
should "return document in custom wrapper" do
|
166
|
+
Configuration.wrapper Article
|
167
|
+
|
168
|
+
Configuration.client.expects(:get).with("#{Configuration.url}/dummy/article/id-1").
|
169
|
+
returns(mock_response('{"_id":"id-1","_version":1, "_source" : {"title":"Test"}}'))
|
170
|
+
article = @index.retrieve :article, 'id-1'
|
171
|
+
assert_instance_of Article, article
|
172
|
+
assert_equal 'Test', article.title
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
context "when removing" do
|
178
|
+
|
179
|
+
should "properly set type from args" do
|
180
|
+
Configuration.client.expects(:delete).with("#{Configuration.url}/dummy/article/").
|
181
|
+
returns('{"ok":true,"_id":"test"}').twice
|
182
|
+
@index.remove 'article', :title => 'Test'
|
183
|
+
@index.remove :article, :title => 'Test'
|
184
|
+
end
|
185
|
+
|
186
|
+
should "set default type" do
|
187
|
+
Configuration.client.expects(:delete).with("#{Configuration.url}/dummy/document/").
|
188
|
+
returns('{"ok":true,"_id":"test"}')
|
189
|
+
@index.remove :title => 'Test'
|
190
|
+
end
|
191
|
+
|
192
|
+
should "get ID from hash" do
|
193
|
+
Configuration.client.expects(:delete).with("#{Configuration.url}/dummy/document/1").
|
194
|
+
returns('{"ok":true,"_id":"1"}')
|
195
|
+
@index.remove :id => 1
|
196
|
+
end
|
197
|
+
|
198
|
+
should "get ID from method" do
|
199
|
+
document = stub('document', :id => 1)
|
200
|
+
Configuration.client.expects(:delete).with("#{Configuration.url}/dummy/document/1").
|
201
|
+
returns('{"ok":true,"_id":"1"}')
|
202
|
+
@index.remove document
|
203
|
+
end
|
204
|
+
|
205
|
+
should "get ID from arguments" do
|
206
|
+
Configuration.client.expects(:delete).with("#{Configuration.url}/dummy/document/1").
|
207
|
+
returns('{"ok":true,"_id":"1"}')
|
208
|
+
@index.remove :document, 1
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
context "when storing in bulk" do
|
214
|
+
# The expected JSON looks like this:
|
215
|
+
#
|
216
|
+
# {"index":{"_index":"dummy","_type":"document","_id":"1"}}
|
217
|
+
# {"id":"1","title":"One"}
|
218
|
+
# {"index":{"_index":"dummy","_type":"document","_id":"2"}}
|
219
|
+
# {"id":"2","title":"Two"}
|
220
|
+
#
|
221
|
+
# See http://www.elasticsearch.org/guide/reference/api/bulk.html
|
222
|
+
|
223
|
+
should "serialize Hashes" do
|
224
|
+
Configuration.client.expects(:post).with do |url, json|
|
225
|
+
url == "#{Configuration.url}/_bulk"
|
226
|
+
json =~ /"_index":"dummy"/
|
227
|
+
json =~ /"_type":"document"/
|
228
|
+
json =~ /"_id":"1"/
|
229
|
+
json =~ /"_id":"2"/
|
230
|
+
json =~ /"id":"1"/
|
231
|
+
json =~ /"id":"2"/
|
232
|
+
json =~ /"title":"One"/
|
233
|
+
json =~ /"title":"Two"/
|
234
|
+
end.returns('{}')
|
235
|
+
|
236
|
+
@index.bulk_store [ {:id => '1', :title => 'One'}, {:id => '2', :title => 'Two'} ]
|
237
|
+
|
238
|
+
end
|
239
|
+
|
240
|
+
should "serialize ActiveModel instances" do
|
241
|
+
Configuration.client.expects(:post).with do |url, json|
|
242
|
+
url == "#{Configuration.url}/_bulk"
|
243
|
+
json =~ /"_index":"active_model_articles"/
|
244
|
+
json =~ /"_type":"article"/
|
245
|
+
json =~ /"_id":"1"/
|
246
|
+
json =~ /"_id":"2"/
|
247
|
+
json =~ /"id":"1"/
|
248
|
+
json =~ /"id":"2"/
|
249
|
+
json =~ /"title":"One"/
|
250
|
+
json =~ /"title":"Two"/
|
251
|
+
end.returns('{}')
|
252
|
+
|
253
|
+
one = ActiveModelArticle.new 'title' => 'One'; one.id = '1'
|
254
|
+
two = ActiveModelArticle.new 'title' => 'Two'; two.id = '2'
|
255
|
+
|
256
|
+
ActiveModelArticle.index.bulk_store [ one, two ]
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
should "try again when an exception occurs" do
|
261
|
+
Configuration.client.expects(:post).raises(RestClient::RequestFailed).at_least(2)
|
262
|
+
|
263
|
+
assert_raise(RestClient::RequestFailed) do
|
264
|
+
@index.bulk_store [ {:id => '1', :title => 'One'}, {:id => '2', :title => 'Two'} ]
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
should_eventually "raise exception when collection item does not have ID" do
|
269
|
+
# TODO: raise exception when collection item does not have ID
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
context "when importing" do
|
275
|
+
setup do
|
276
|
+
@index = Tire::Index.new 'import'
|
277
|
+
end
|
278
|
+
|
279
|
+
class ::ImportData
|
280
|
+
DATA = (1..4).to_a
|
281
|
+
|
282
|
+
def self.paginate(options={})
|
283
|
+
options = {:page => 1, :per_page => 1000}.update options
|
284
|
+
DATA.slice( (options[:page]-1)*options[:per_page]...options[:page]*options[:per_page] )
|
285
|
+
end
|
286
|
+
|
287
|
+
def self.each(&block); DATA.each █ end
|
288
|
+
def self.map(&block); DATA.map █ end
|
289
|
+
def self.count; DATA.size; end
|
290
|
+
end
|
291
|
+
|
292
|
+
should "be initialized with a collection" do
|
293
|
+
@index.expects(:bulk_store).returns(:true)
|
294
|
+
|
295
|
+
assert_nothing_raised { @index.import [{ :id => 1, :title => 'Article' }] }
|
296
|
+
end
|
297
|
+
|
298
|
+
should "be initialized with a class and params" do
|
299
|
+
@index.expects(:bulk_store).returns(:true)
|
300
|
+
|
301
|
+
assert_nothing_raised { @index.import ImportData }
|
302
|
+
end
|
303
|
+
|
304
|
+
context "plain collection" do
|
305
|
+
|
306
|
+
should "just store it in bulk" do
|
307
|
+
collection = [{ :id => 1, :title => 'Article' }]
|
308
|
+
@index.expects(:bulk_store).with( collection ).returns(true)
|
309
|
+
|
310
|
+
@index.import collection
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|
314
|
+
|
315
|
+
context "class" do
|
316
|
+
|
317
|
+
should "call the passed method and bulk store the results" do
|
318
|
+
@index.expects(:bulk_store).with([1, 2, 3, 4]).returns(true)
|
319
|
+
|
320
|
+
@index.import ImportData, :paginate
|
321
|
+
end
|
322
|
+
|
323
|
+
should "pass the params to the passed method and bulk store the results" do
|
324
|
+
@index.expects(:bulk_store).with([1, 2]).returns(true)
|
325
|
+
@index.expects(:bulk_store).with([3, 4]).returns(true)
|
326
|
+
|
327
|
+
@index.import ImportData, :paginate, :page => 1, :per_page => 2
|
328
|
+
end
|
329
|
+
|
330
|
+
should "pass the class when method not passed" do
|
331
|
+
@index.expects(:bulk_store).with(ImportData).returns(true)
|
332
|
+
|
333
|
+
@index.import ImportData
|
334
|
+
end
|
335
|
+
|
336
|
+
end
|
337
|
+
|
338
|
+
context "with passed block" do
|
339
|
+
|
340
|
+
context "and plain collection" do
|
341
|
+
|
342
|
+
should "allow to manipulate the collection in the block" do
|
343
|
+
Tire::Index.any_instance.expects(:bulk_store).with([{ :id => 1, :title => 'ARTICLE' }])
|
344
|
+
|
345
|
+
|
346
|
+
@index.import [{ :id => 1, :title => 'Article' }] do |articles|
|
347
|
+
articles.map { |article| article.update :title => article[:title].upcase }
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
end
|
352
|
+
|
353
|
+
context "and object" do
|
354
|
+
|
355
|
+
should "call the passed block on every batch" do
|
356
|
+
Tire::Index.any_instance.expects(:bulk_store).with([1, 2])
|
357
|
+
Tire::Index.any_instance.expects(:bulk_store).with([3, 4])
|
358
|
+
|
359
|
+
runs = 0
|
360
|
+
@index.import ImportData, :paginate, :per_page => 2 do |documents|
|
361
|
+
runs += 1
|
362
|
+
# Don't forget to return the documents at the end of the block
|
363
|
+
documents
|
364
|
+
end
|
365
|
+
|
366
|
+
assert_equal 2, runs
|
367
|
+
end
|
368
|
+
|
369
|
+
should "allow to manipulate the documents in passed block" do
|
370
|
+
Tire::Index.any_instance.expects(:bulk_store).with([2, 3])
|
371
|
+
Tire::Index.any_instance.expects(:bulk_store).with([4, 5])
|
372
|
+
|
373
|
+
|
374
|
+
@index.import ImportData, :paginate, :per_page => 2 do |documents|
|
375
|
+
# Add 1 to every "document" and return them
|
376
|
+
documents.map { |d| d + 1 }
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
end
|
381
|
+
|
382
|
+
end
|
383
|
+
|
384
|
+
end
|
385
|
+
|
386
|
+
end
|
387
|
+
|
388
|
+
end
|
389
|
+
|
390
|
+
end
|