tanker 1.0.0 → 1.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/spec/tanker_spec.rb CHANGED
@@ -2,51 +2,184 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
2
 
3
3
  describe Tanker do
4
4
 
5
- it 'sets configuration' do
6
- conf = {:url => 'http://api.indextank.com'}
7
- Tanker.configuration = conf
5
+ describe "configuration" do
8
6
 
9
- Tanker.configuration.should == conf
10
- end
7
+ it 'sets configuration' do
8
+ conf = {:url => 'http://api.indextank.com', :pagination_backend => :will_paginate}
9
+ Tanker.configuration = conf
11
10
 
12
- it 'checks for configuration when the module is included' do
13
- Tanker.configuration = nil
11
+ Tanker.configuration.should == conf
12
+ end
14
13
 
15
- lambda {
16
- Dummy.send(:include, Tanker)
17
- }.should raise_error(Tanker::NotConfigured)
18
- end
14
+ it 'adds default values to configuration on set if needed' do
15
+ conf = {:url => 'http://api.indextank.com'}
16
+ Tanker.configuration = conf
17
+ Tanker.configuration.should == conf.merge(:pagination_backend => :will_paginate)
18
+ end
19
19
 
20
- it 'should requiquire a block when seting up tanker model' do
21
- Tanker.configuration = {:url => 'http://api.indextank.com'}
22
- Dummy.send(:include, Tanker)
23
- lambda {
24
- Dummy.send(:tankit, 'dummy index')
25
- }.should raise_error(Tanker::NoBlockGiven)
26
- end
20
+ it 'checks for configuration when the module is included' do
21
+ Tanker.configuration = nil
27
22
 
28
- it 'should set indexable fields' do
29
- Tanker.configuration = {:url => 'http://api.indextank.com'}
30
- Dummy.send(:include, Tanker)
31
- Dummy.send(:tankit, 'dummy index') do
32
- indexes :field
23
+ lambda {
24
+ Class.new.send(:include, Tanker)
25
+ }.should raise_error(Tanker::NotConfigured)
26
+ end
27
+
28
+ it 'should not add model to .included_in if not configured' do
29
+ Tanker.configuration = nil
30
+ begin
31
+ dummy_class = Class.new
32
+ dummy_class.send(:include, Tanker)
33
+ rescue Tanker::NotConfigured => e
34
+ Tanker.included_in.should_not include dummy_class
35
+ end
33
36
  end
34
37
 
35
- dummy_instance = Dummy.new
36
- dummy_instance.tanker_config.indexes.any? {|field, block| field == :field }.should == true
37
38
  end
38
39
 
39
- it 'should allow blocks for indexable field data' do
40
- Tanker.configuration = {:url => 'http://api.indextank.com'}
41
- Dummy.send(:include, Tanker)
42
- Dummy.send(:tankit, 'dummy index') do
43
- indexes :class_name do
44
- self.class.name
40
+ describe ".tankit" do
41
+
42
+ before :each do
43
+ Tanker.configuration = {:url => 'http://api.indextank.com'}
44
+ @dummy_class = Class.new do
45
+ include Tanker
46
+ end
47
+ end
48
+
49
+ after :each do
50
+ Tanker.instance_variable_set(:@included_in, Tanker.included_in - [@dummy_class])
51
+ end
52
+
53
+ it 'should require a block when setting up tanker model' do
54
+ lambda {
55
+ @dummy_class.send(:tankit, 'dummy index')
56
+ }.should raise_error(Tanker::NoBlockGiven)
57
+ end
58
+
59
+ it 'should set indexable fields' do
60
+ @dummy_class.send(:tankit, 'dummy index') do
61
+ indexes :field
62
+ end
63
+
64
+ dummy_instance = @dummy_class.new
65
+ dummy_instance.tanker_config.indexes.any? {|field, block| field == :field }.should == true
66
+ end
67
+
68
+ it 'should allow blocks for indexable field data' do
69
+ @dummy_class.send(:tankit, 'dummy index') do
70
+ indexes :class_name do
71
+ self.class.name
72
+ end
73
+ end
74
+
75
+ dummy_instance = @dummy_class.new
76
+ dummy_instance.tanker_config.indexes.any? {|field, block| field == :class_name }.should == true
77
+ end
78
+
79
+ it 'should overwrite the previous index name if provided' do
80
+ @dummy_class.send(:tankit, 'first index') do
81
+ end
82
+ @dummy_class.send(:tankit, 'second index') do
83
+ end
84
+
85
+ dummy_instance = @dummy_class.new
86
+ dummy_instance.tanker_config.index_name.should == 'second index'
87
+ end
88
+
89
+ it 'should keep the previous index name if not provided' do
90
+ @dummy_class.send(:tankit, 'dummy index') do
91
+ end
92
+ @dummy_class.send(:tankit) do
93
+ end
94
+
95
+ dummy_instance = @dummy_class.new
96
+ dummy_instance.tanker_config.index_name.should == 'dummy index'
97
+ end
98
+
99
+ it 'should keep previously indexed fields' do
100
+ @dummy_class.send(:tankit, 'dummy index') do
101
+ indexes :something
102
+ end
103
+ @dummy_class.send(:tankit, 'dummy index') do
104
+ indexes :something_else
105
+ end
106
+
107
+ dummy_instance = @dummy_class.new
108
+ Hash[*dummy_instance.tanker_config.indexes.flatten].keys.should == [:something, :something_else]
109
+ end
110
+
111
+ it 'should overwrite previously indexed fields if re-indexed' do
112
+ @dummy_class.send(:tankit, 'dummy index') do
113
+ indexes :something do
114
+ "first"
115
+ end
116
+ end
117
+ @dummy_class.send(:tankit, 'dummy index') do
118
+ indexes :something do
119
+ "second"
120
+ end
121
+ end
122
+
123
+ dummy_instance = @dummy_class.new
124
+ dummy_instance.stub!(:id => 1)
125
+ dummy_instance.tanker_index_data[:something].should == "second"
126
+ end
127
+
128
+ it 'should merge with previously defined variables' do
129
+ @dummy_class.send(:tankit, 'dummy index') do
130
+ variables do
131
+ {
132
+ 0 => 3.1415927,
133
+ 1 => 2.7182818
134
+ }
135
+ end
136
+ end
137
+ @dummy_class.send(:tankit, 'dummy index') do
138
+ variables do
139
+ {
140
+ 0 => 1.618034
141
+ }
142
+ end
143
+ end
144
+
145
+ dummy_instance = @dummy_class.new
146
+ dummy_instance.tanker_index_options[:variables].should == { 0 => 1.618034, 1 => 2.7182818 }
147
+ end
148
+
149
+ it 'should allow setting of __type by supplying :as option' do
150
+ @dummy_class.send(:tankit, 'dummy index', { :as => 'MySpecialModel' }) do
45
151
  end
152
+
153
+ dummy_instance = @dummy_class.new
154
+ dummy_instance.stub!(:id => 1)
155
+ dummy_instance.tanker_index_data[:__type].should == 'MySpecialModel'
46
156
  end
47
157
 
48
- dummy_instance = Dummy.new
49
- dummy_instance.tanker_config.indexes.any? {|field, block| field == :class_name }.should == true
158
+ it "can be initially defined in one module and extended in the including class" do
159
+ dummy_module = Module.new do
160
+ def self.included(base)
161
+ base.send :include, Tanker
162
+
163
+ base.tankit 'dummy index' do
164
+ indexes :name
165
+ end
166
+ end
167
+ end
168
+
169
+ dummy_class = Class.new do
170
+ include dummy_module
171
+
172
+ tankit 'another index' do
173
+ indexes :email
174
+ end
175
+ end
176
+
177
+ dummy_instance = dummy_class.new
178
+ dummy_instance.tanker_config.index_name.should == 'another index'
179
+ Hash[*dummy_instance.tanker_config.indexes.flatten].keys.should == [:name, :email]
180
+
181
+ Tanker.instance_variable_set(:@included_in, Tanker.included_in - [dummy_class])
182
+ end
50
183
  end
51
184
 
52
185
  describe 'tanker instance' do
@@ -63,8 +196,10 @@ describe Tanker do
63
196
  {
64
197
  "matches" => 1,
65
198
  "results" => [{
66
- "docid" => Person.new.it_doc_id,
67
- "name" => 'pedro'
199
+ "docid" => Person.new.it_doc_id,
200
+ "name" => 'pedro',
201
+ "__type" => 'Person',
202
+ "__id" => '1'
68
203
  }],
69
204
  "search_time" => 1
70
205
  }
@@ -82,10 +217,38 @@ describe Tanker do
82
217
  collection.current_page.should == 1
83
218
  end
84
219
 
220
+ it 'should handle string and integer ids in search results' do
221
+ Person.tanker_index.should_receive(:search).and_return(
222
+ {
223
+ "matches" => 2,
224
+ "results" => [{
225
+ "docid" => 'Person mystring1d',
226
+ "name" => 'pedro',
227
+ "__type" => 'Person',
228
+ "__id" => 'mystring1d'
229
+ },{
230
+ "docid" => 'Person 1',
231
+ "name" => 'jaun',
232
+ "__type" => 'Person',
233
+ "__id" => '1'
234
+ }],
235
+ "search_time" => 1
236
+ }
237
+ )
238
+
239
+ Person.should_receive(:find).with(['mystring1d', '1']).and_return(
240
+ [Person.new, Person.new]
241
+ )
242
+
243
+ collection = Person.search_tank('hey!')
244
+ collection.class.should == WillPaginate::Collection
245
+ collection.total_entries.should == 2
246
+ end
247
+
85
248
  it 'should be able to use multi-value query phrases' do
86
249
  Person.tanker_index.should_receive(:search).with(
87
- "__any:(hey! location_id:(1) location_id:(2)) __type:(Person)",
88
- {:start => 0, :len => 10}
250
+ 'name:(hey! location_id:(1) location_id:(2)) OR last_name:(hey! location_id:(1) location_id:(2)) __type:("Person")',
251
+ anything
89
252
  ).and_return({'results' => [], 'matches' => 0})
90
253
 
91
254
  collection = Person.search_tank('hey!', :conditions => {:location_id => [1,2]})
@@ -93,11 +256,8 @@ describe Tanker do
93
256
 
94
257
  it 'should be able to use filter_functions' do
95
258
  Person.tanker_index.should_receive(:search).with(
96
- "__any:(hey!) __type:(Person)",
97
- { :start => 0,
98
- :len => 10,
99
- :filter_function2 => "0:10,20:40"
100
- }
259
+ anything,
260
+ hash_including(:filter_function2 => "0:10,20:40")
101
261
  ).and_return({'results' => [], 'matches' => 0})
102
262
 
103
263
  collection = Person.search_tank('hey!',
@@ -107,11 +267,8 @@ describe Tanker do
107
267
  end
108
268
  it 'should be able to use filter_docvars' do
109
269
  Person.tanker_index.should_receive(:search).with(
110
- "__any:(hey!) __type:(Person)",
111
- { :start => 0,
112
- :len => 10,
113
- :filter_docvar3 => "*:7,80:100"
114
- }
270
+ anything,
271
+ hash_including(:filter_docvar3 => "*:7,80:100")
115
272
  ).and_return({'results' => [], 'matches' => 0})
116
273
 
117
274
  collection = Person.search_tank('hey!',
@@ -127,12 +284,16 @@ describe Tanker do
127
284
  {
128
285
  "matches" => 2,
129
286
  "results" => [{
130
- "docid" => 'Dog 7',
131
- "name" => 'fido'
287
+ "docid" => 'Dog 7',
288
+ "name" => 'fido',
289
+ "__type" => 'Dog',
290
+ "__id" => '7'
132
291
  },
133
292
  {
134
- "docid" => 'Cat 9',
135
- "name" => 'fluffy'
293
+ "docid" => 'Cat 9',
294
+ "name" => 'fluffy',
295
+ "__type" => 'Cat',
296
+ "__id" => '9'
136
297
  }],
137
298
  "search_time" => 1
138
299
  }
@@ -153,6 +314,82 @@ describe Tanker do
153
314
  collection.current_page.should == 1
154
315
  end
155
316
 
317
+ it 'should be able to search for modularized model classes' do
318
+ Foo::Bar.tanker_index.
319
+ should_receive(:search).
320
+ with(/__type:\(.*"Foo Bar".*\)/, anything).
321
+ and_return({
322
+ "results" => [{
323
+ "docid" => 'Foo::Bar 42',
324
+ "__type" => 'Foo::Bar',
325
+ "__id" => '42'
326
+ }]
327
+ })
328
+
329
+ Foo::Bar.should_receive(:find).and_return([stub(:id => 42)])
330
+
331
+ Foo::Bar.search_tank('bar')
332
+ end
333
+
334
+ it 'should be able to perform a search without pagination' do
335
+ Person.tanker_index.should_receive(:search).and_return(
336
+ {
337
+ "matches" => 2,
338
+ "results" => [{
339
+ "docid" => 'Person 1',
340
+ "name" => 'pedro',
341
+ "__type" => 'Person',
342
+ "__id" => '1'
343
+ },{
344
+ "docid" => 'Person 2',
345
+ "name" => 'jaun',
346
+ "__type" => 'Person',
347
+ "__id" => '2'
348
+ }],
349
+ "search_time" => 1
350
+ }
351
+ )
352
+
353
+ Person.should_receive(:find).with(['1', '2']).and_return(
354
+ [Person.new, Person.new]
355
+ )
356
+
357
+ collection = Person.search_tank('hey!', :paginate => false)
358
+ collection.class.should == Array
359
+ collection.size.should == 2
360
+ end
361
+
362
+ it 'should be able to perform a search with pagination settings in :paginate option' do
363
+ Person.tanker_index.should_receive(:search).and_return(
364
+ {
365
+ "matches" => 2,
366
+ "results" => [{
367
+ "docid" => 'Person 1',
368
+ "name" => 'pedro',
369
+ "__type" => 'Person',
370
+ "__id" => '1'
371
+ },{
372
+ "docid" => 'Person 2',
373
+ "name" => 'jaun',
374
+ "__type" => 'Person',
375
+ "__id" => '2'
376
+ }],
377
+ "search_time" => 1
378
+ }
379
+ )
380
+
381
+ Person.should_receive(:find).with(['1', '2']).and_return(
382
+ [Person.new, Person.new]
383
+ )
384
+
385
+ collection = Person.search_tank('hey!', :paginate => { :page => 2, :per_page => 1 })
386
+ collection.class.should == WillPaginate::Collection
387
+ collection.total_entries.should == 2
388
+ collection.total_pages.should == 2
389
+ collection.per_page.should == 1
390
+ collection.current_page.should == 2
391
+ end
392
+
156
393
  it 'should be able to update the index' do
157
394
  person = Person.new(:name => 'Name', :last_name => 'Last Name')
158
395
 
@@ -161,6 +398,7 @@ describe Tanker do
161
398
  {
162
399
  :__any => "#{$frozen_moment.to_i} . Last Name . Name",
163
400
  :__type => 'Person',
401
+ :__id => 1,
164
402
  :name => 'Name',
165
403
  :last_name => 'Last Name',
166
404
  :timestamp => $frozen_moment.to_i
@@ -186,6 +424,7 @@ describe Tanker do
186
424
  :fields => {
187
425
  :__any => "#{$frozen_moment.to_i} . Last Name . Name",
188
426
  :__type => 'Person',
427
+ :__id => 1,
189
428
  :name => 'Name',
190
429
  :last_name => 'Last Name',
191
430
  :timestamp => $frozen_moment.to_i
@@ -209,5 +448,96 @@ describe Tanker do
209
448
  person.delete_tank_indexes
210
449
  end
211
450
 
451
+ describe 'snippets' do
452
+ it 'should not call find method but instead create new instances the models matched the search with the snippetted fields as snippet_ attributes' do
453
+ Person.tanker_index.should_receive(:search).and_return(
454
+ {
455
+ "matches" => 1,
456
+ "results" => [{
457
+ "docid" => Person.new.it_doc_id,
458
+ 'snippet_name' => 'ped...',
459
+ "__type" => 'Person',
460
+ "__id" => '1'
461
+ }],
462
+ "search_time" => 1
463
+ })
464
+
465
+ collection = Person.search_tank('hey!', :snippets => [:name])
466
+ collection[0].name_snippet.should == 'ped...'
467
+ end
468
+ end
469
+
470
+ describe 'fetch' do
471
+ it 'should not call find method but instead create new instances the models matched the search with the fetched fields as attributes' do
472
+ Person.tanker_index.should_receive(:search).and_return(
473
+ {
474
+ "matches" => 1,
475
+ "results" => [{
476
+ "docid" => Person.new.it_doc_id,
477
+ 'name' => 'Osama',
478
+ "__type" => 'Person',
479
+ "__id" => '1'
480
+ }],
481
+ "search_time" => 1
482
+ })
483
+
484
+ collection = Person.search_tank('terrorist', :fetch => [:name])
485
+ collection[0].name.should == 'Osama'
486
+ end
487
+ end
488
+ end
489
+
490
+ describe "Kaminari support" do
491
+
492
+ before :all do
493
+ Tanker.configuration = {:url => 'http://api.indextank.com', :pagination_backend => :kaminari}
494
+ end
495
+
496
+ after :all do
497
+ Tanker.configuration = {}
498
+ end
499
+
500
+ it 'should raise error message if Kaminari gem is not required' do
501
+ Person.tanker_index.should_receive(:search).and_return(
502
+ {
503
+ "matches" => 1,
504
+ "results" => [{
505
+ "docid" => Person.new.it_doc_id,
506
+ "name" => 'pedro',
507
+ "__type" => 'Person',
508
+ "__id" => '1'
509
+ }],
510
+ "search_time" => 1
511
+ }
512
+ )
513
+ Person.should_receive(:find).and_return([Person.new])
514
+
515
+ lambda { Person.search_tank('test') }.should raise_error(Tanker::BadConfiguration)
516
+ end
517
+
518
+ it 'should be able to return Kaminari compatible array for a search' do
519
+ require 'kaminari'
520
+ Person.tanker_index.should_receive(:search).and_return(
521
+ {
522
+ "matches" => 1,
523
+ "results" => [{
524
+ "docid" => Person.new.it_doc_id,
525
+ "name" => 'pedro',
526
+ "__type" => 'Person',
527
+ "__id" => '1'
528
+ }],
529
+ "search_time" => 1
530
+ }
531
+ )
532
+
533
+ Person.should_receive(:find).and_return([Person.new])
534
+
535
+ array = Person.search_tank('hey!')
536
+ array.class.should == Tanker::KaminariPaginatedArray
537
+ array.total_count.should == 1
538
+ array.num_pages.should == 1
539
+ array.limit_value.should == 10
540
+ array.current_page.should == 1
541
+ end
212
542
  end
213
543
  end
@@ -1,23 +1,32 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
2
 
3
- class Dummy
4
- include Tanker
3
+ describe Tanker::Utilities do
5
4
 
6
- tankit 'dummy index' do
7
- indexes :name
8
- end
5
+ before(:each) do
6
+
7
+ @included_in = Tanker.instance_variable_get :@included_in
8
+ Tanker.instance_variable_set :@included_in, []
9
9
 
10
- end
10
+ class Dummy
11
+ include Tanker
11
12
 
13
+ tankit 'dummy index' do
14
+ indexes :name
15
+ end
12
16
 
13
- describe Tanker::Utilities do
17
+ end
18
+ end
19
+
20
+ after(:each) do
21
+ Tanker.instance_variable_set :@included_in, @included_in
22
+ end
14
23
 
15
24
  it "should get the models where Tanker module was included" do
16
- (Tanker::Utilities.get_model_classes - [Dummy, Person, Dog, Cat]).should == []
25
+ (Tanker::Utilities.get_model_classes - [Dummy]).should == []
17
26
  end
18
27
 
19
28
  it "should get the available indexes" do
20
- Tanker::Utilities.get_available_indexes.should == ["people", "animals", "dummy index"]
29
+ Tanker::Utilities.get_available_indexes.should == ["dummy index"]
21
30
  end
22
31
 
23
32
  end
data/tanker.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{tanker}
8
- s.version = "1.0.0"
8
+ s.version = "1.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["@kidpollo", "Jack Danger Canty"]
12
- s.date = %q{2011-04-02}
11
+ s.authors = [%q{@kidpollo}, %q{Jack Danger Canty}]
12
+ s.date = %q{2011-06-06}
13
13
  s.description = %q{IndexTank is a great search indexing service, this gem tries to make any orm keep in sync with indextank with ease}
14
14
  s.email = %q{kidpollo@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -27,19 +27,23 @@ Gem::Specification.new do |s|
27
27
  "lib/indextank_client.rb",
28
28
  "lib/tanker.rb",
29
29
  "lib/tanker/configuration.rb",
30
+ "lib/tanker/paginated_array.rb",
30
31
  "lib/tanker/railtie.rb",
31
32
  "lib/tanker/tasks/tanker.rake",
32
33
  "lib/tanker/utilities.rb",
34
+ "spec/integration_spec.rb",
35
+ "spec/integration_spec_conf.rb.example",
33
36
  "spec/spec_helper.rb",
34
37
  "spec/tanker_spec.rb",
35
38
  "spec/utilities_spec.rb",
36
39
  "tanker.gemspec"
37
40
  ]
38
41
  s.homepage = %q{http://github.com/kidpollo/tanker}
39
- s.require_paths = ["lib"]
40
- s.rubygems_version = %q{1.7.1}
42
+ s.require_paths = [%q{lib}]
43
+ s.rubygems_version = %q{1.8.5}
41
44
  s.summary = %q{IndexTank integration to your favorite orm}
42
45
  s.test_files = [
46
+ "spec/integration_spec.rb",
43
47
  "spec/spec_helper.rb",
44
48
  "spec/tanker_spec.rb",
45
49
  "spec/utilities_spec.rb"
@@ -50,14 +54,20 @@ Gem::Specification.new do |s|
50
54
 
51
55
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
56
  s.add_runtime_dependency(%q<jeweler>, [">= 0"])
57
+ s.add_runtime_dependency(%q<json>, [">= 1.5.1"])
53
58
  s.add_runtime_dependency(%q<will_paginate>, [">= 2.3.15"])
59
+ s.add_runtime_dependency(%q<kaminari>, [">= 0"])
54
60
  else
55
61
  s.add_dependency(%q<jeweler>, [">= 0"])
62
+ s.add_dependency(%q<json>, [">= 1.5.1"])
56
63
  s.add_dependency(%q<will_paginate>, [">= 2.3.15"])
64
+ s.add_dependency(%q<kaminari>, [">= 0"])
57
65
  end
58
66
  else
59
67
  s.add_dependency(%q<jeweler>, [">= 0"])
68
+ s.add_dependency(%q<json>, [">= 1.5.1"])
60
69
  s.add_dependency(%q<will_paginate>, [">= 2.3.15"])
70
+ s.add_dependency(%q<kaminari>, [">= 0"])
61
71
  end
62
72
  end
63
73