robsharp-sunspot_rails 1.1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/History.txt +40 -0
  2. data/LICENSE +18 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +256 -0
  5. data/Rakefile +27 -0
  6. data/TODO +8 -0
  7. data/VERSION.yml +4 -0
  8. data/dev_tasks/gemspec.rake +33 -0
  9. data/dev_tasks/rdoc.rake +24 -0
  10. data/dev_tasks/release.rake +4 -0
  11. data/dev_tasks/todo.rake +4 -0
  12. data/generators/sunspot/sunspot_generator.rb +9 -0
  13. data/generators/sunspot/templates/sunspot.yml +18 -0
  14. data/install.rb +1 -0
  15. data/lib/sunspot/rails.rb +58 -0
  16. data/lib/sunspot/rails/adapters.rb +160 -0
  17. data/lib/sunspot/rails/configuration.rb +272 -0
  18. data/lib/sunspot/rails/request_lifecycle.rb +31 -0
  19. data/lib/sunspot/rails/searchable.rb +464 -0
  20. data/lib/sunspot/rails/server.rb +173 -0
  21. data/lib/sunspot/rails/solr_logging.rb +58 -0
  22. data/lib/sunspot/rails/spec_helper.rb +19 -0
  23. data/lib/sunspot/rails/stub_session_proxy.rb +88 -0
  24. data/lib/sunspot/rails/tasks.rb +62 -0
  25. data/lib/sunspot/rails/version.rb +5 -0
  26. data/rails/init.rb +10 -0
  27. data/spec/configuration_spec.rb +102 -0
  28. data/spec/mock_app/app/controllers/application.rb +10 -0
  29. data/spec/mock_app/app/controllers/application_controller.rb +10 -0
  30. data/spec/mock_app/app/controllers/posts_controller.rb +6 -0
  31. data/spec/mock_app/app/models/author.rb +8 -0
  32. data/spec/mock_app/app/models/blog.rb +12 -0
  33. data/spec/mock_app/app/models/location.rb +2 -0
  34. data/spec/mock_app/app/models/photo_post.rb +2 -0
  35. data/spec/mock_app/app/models/post.rb +10 -0
  36. data/spec/mock_app/app/models/post_with_auto.rb +10 -0
  37. data/spec/mock_app/config/boot.rb +110 -0
  38. data/spec/mock_app/config/database.yml +4 -0
  39. data/spec/mock_app/config/environment.rb +42 -0
  40. data/spec/mock_app/config/environments/development.rb +27 -0
  41. data/spec/mock_app/config/environments/test.rb +27 -0
  42. data/spec/mock_app/config/initializers/new_rails_defaults.rb +19 -0
  43. data/spec/mock_app/config/initializers/session_store.rb +15 -0
  44. data/spec/mock_app/config/routes.rb +43 -0
  45. data/spec/mock_app/config/sunspot.yml +19 -0
  46. data/spec/mock_app/db/schema.rb +27 -0
  47. data/spec/model_lifecycle_spec.rb +63 -0
  48. data/spec/model_spec.rb +409 -0
  49. data/spec/request_lifecycle_spec.rb +52 -0
  50. data/spec/schema.rb +27 -0
  51. data/spec/server_spec.rb +36 -0
  52. data/spec/session_spec.rb +24 -0
  53. data/spec/spec_helper.rb +51 -0
  54. data/spec/stub_session_proxy_spec.rb +122 -0
  55. metadata +170 -0
@@ -0,0 +1,409 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe 'ActiveRecord mixin' do
4
+ describe 'index()' do
5
+ before :each do
6
+ @post = Post.create!
7
+ @post.index
8
+ end
9
+
10
+ it 'should not commit the model' do
11
+ Post.search.results.should be_empty
12
+ end
13
+
14
+ it 'should index the model' do
15
+ Sunspot.commit
16
+ Post.search.results.should == [@post]
17
+ end
18
+ end
19
+
20
+ describe 'single table inheritence' do
21
+ before :each do
22
+ @post = PhotoPost.create!
23
+ end
24
+
25
+ it 'should not break auto-indexing' do
26
+ @post.title = 'Title'
27
+ lambda { @post.save! }.should_not raise_error
28
+ end
29
+ end
30
+
31
+ describe 'index!()' do
32
+ before :each do
33
+ @post = Post.create!
34
+ @post.index!
35
+ end
36
+
37
+ it 'should immediately index and commit' do
38
+ Post.search.results.should == [@post]
39
+ end
40
+ end
41
+
42
+ describe 'remove_from_index()' do
43
+ before :each do
44
+ @post = Post.create!
45
+ @post.index!
46
+ @post.remove_from_index
47
+ end
48
+
49
+ it 'should not commit immediately' do
50
+ Post.search.results.should == [@post]
51
+ end
52
+
53
+ it 'should remove the model from the index' do
54
+ Sunspot.commit
55
+ Post.search.results.should be_empty
56
+ end
57
+ end
58
+
59
+ describe 'remove_from_index!()' do
60
+ before :each do
61
+ @post = Post.create!
62
+ @post.index!
63
+ @post.remove_from_index!
64
+ end
65
+
66
+ it 'should immediately remove the model and commit' do
67
+ Post.search.results.should be_empty
68
+ end
69
+ end
70
+
71
+ describe 'remove_all_from_index' do
72
+ before :each do
73
+ @posts = Array.new(10) { Post.create! }.each { |post| Sunspot.index(post) }
74
+ Sunspot.commit
75
+ Post.remove_all_from_index
76
+ end
77
+
78
+ it 'should not commit immediately' do
79
+ Post.search.results.to_set.should == @posts.to_set
80
+ end
81
+
82
+ it 'should remove all instances from the index' do
83
+ Sunspot.commit
84
+ Post.search.results.should be_empty
85
+ end
86
+ end
87
+
88
+ describe 'remove_all_from_index!' do
89
+ before :each do
90
+ Array.new(10) { Post.create! }.each { |post| Sunspot.index(post) }
91
+ Sunspot.commit
92
+ Post.remove_all_from_index!
93
+ end
94
+
95
+ it 'should remove all instances from the index and commit immediately' do
96
+ Post.search.results.should be_empty
97
+ end
98
+ end
99
+
100
+ describe 'search()' do
101
+ before :each do
102
+ @post = Post.create!(:title => 'Test Post')
103
+ @post.index!
104
+ end
105
+
106
+ it 'should return results specified by search' do
107
+ Post.search do
108
+ with :title, 'Test Post'
109
+ end.results.should == [@post]
110
+ end
111
+
112
+ it 'should not return results excluded by search' do
113
+ Post.search do
114
+ with :title, 'Bogus Post'
115
+ end.results.should be_empty
116
+ end
117
+
118
+ it 'should find ActiveRecord objects with an integer, not a string' do
119
+ Post.should_receive(:all).with(hash_including(:conditions => { "id" => [@post.id.to_i] })).and_return([@post])
120
+ Post.search do
121
+ with :title, 'Test Post'
122
+ end.results.should == [@post]
123
+ end
124
+
125
+ it 'should use the include option on the data accessor when specified' do
126
+ Post.should_receive(:find).with(anything(), hash_including(:include => [:blog])).and_return([@post])
127
+ Post.search do
128
+ with :title, 'Test Post'
129
+ data_accessor_for(Post).include = [:blog]
130
+ end.results.should == [@post]
131
+ end
132
+
133
+ it 'should pass :include option from search call to data accessor' do
134
+ Post.should_receive(:find).with(anything(), hash_including(:include => [:blog])).and_return([@post])
135
+ Post.search(:include => [:blog]) do
136
+ with :title, 'Test Post'
137
+ end.results.should == [@post]
138
+ end
139
+
140
+ it 'should use the select option from search call to data accessor' do
141
+ Post.should_receive(:find).with(anything(), hash_including(:select => 'title, published_at')).and_return([@post])
142
+ Post.search(:select => 'title, published_at') do
143
+ with :title, 'Test Post'
144
+ end.results.should == [@post]
145
+ end
146
+
147
+ it 'should not allow bogus options to search' do
148
+ lambda { Post.search(:bogus => :option) }.should raise_error(ArgumentError)
149
+ end
150
+
151
+ it 'should use the select option on the data accessor when specified' do
152
+ Post.should_receive(:find).with(anything(), hash_including(:select => 'title, published_at')).and_return([@post])
153
+ Post.search do
154
+ with :title, 'Test Post'
155
+ data_accessor_for(Post).select = [:title, :published_at]
156
+ end.results.should == [@post]
157
+ end
158
+
159
+ it 'should not use the select option on the data accessor when not specified' do
160
+ Post.should_receive(:find).with(anything(), hash_not_including(:select)).and_return([@post])
161
+ Post.search do
162
+ with :title, 'Test Post'
163
+ end.results.should == [@post]
164
+ end
165
+
166
+ it 'should gracefully handle nonexistent records' do
167
+ post2 = Post.create!(:title => 'Test Post')
168
+ post2.index!
169
+ post2.destroy
170
+ Post.search do
171
+ with :title, 'Test Post'
172
+ end.results.should == [@post]
173
+ end
174
+
175
+ it 'should use an ActiveRecord object for coordinates' do
176
+ post = Post.new(:title => 'Test Post')
177
+ post.location = Location.create!(:lat => 40.0, :lng => -70.0)
178
+ post.save
179
+ post.index!
180
+ Post.search { near([40.0, -70.0], :distance => 1) }.results.should == [post]
181
+ end
182
+
183
+ end
184
+
185
+ describe 'search_ids()' do
186
+ before :each do
187
+ @posts = Array.new(2) { Post.create! }.each { |post| post.index }
188
+ Sunspot.commit
189
+ end
190
+
191
+ it 'should return IDs' do
192
+ Post.search_ids.to_set.should == @posts.map { |post| post.id }.to_set
193
+ end
194
+ end
195
+
196
+ describe 'searchable?()' do
197
+ it 'should not be true for models that have not been configured for search' do
198
+ Location.should_not be_searchable
199
+ end
200
+
201
+ it 'should be true for models that have been configured for search' do
202
+ Post.should be_searchable
203
+ end
204
+ end
205
+
206
+ describe 'index_orphans()' do
207
+ before :each do
208
+ @posts = Array.new(2) { Post.create }.each { |post| post.index }
209
+ Sunspot.commit
210
+ @posts.first.destroy
211
+ end
212
+
213
+ it 'should return IDs of objects that are in the index but not the database' do
214
+ Post.index_orphans.should == [@posts.first.id]
215
+ end
216
+ end
217
+
218
+ describe 'clean_index_orphans()' do
219
+ before :each do
220
+ @posts = Array.new(2) { Post.create }.each { |post| post.index }
221
+ Sunspot.commit
222
+ @posts.first.destroy
223
+ end
224
+
225
+ it 'should remove orphans from the index' do
226
+ Post.clean_index_orphans
227
+ Sunspot.commit
228
+ Post.search.results.should == [@posts.last]
229
+ end
230
+ end
231
+
232
+ describe 'reindex()' do
233
+ before :each do
234
+ @posts = Array.new(2) { Post.create }
235
+ end
236
+
237
+ it 'should index all instances' do
238
+ Post.reindex(:batch_size => nil)
239
+ Sunspot.commit
240
+ Post.search.results.to_set.should == @posts.to_set
241
+ end
242
+
243
+ it 'should remove all currently indexed instances' do
244
+ old_post = Post.create!
245
+ old_post.index!
246
+ old_post.destroy
247
+ Post.reindex
248
+ Sunspot.commit
249
+ Post.search.results.to_set.should == @posts.to_set
250
+ end
251
+
252
+ end
253
+
254
+ describe 'reindex() with real data' do
255
+ before :each do
256
+ @posts = Array.new(2) { Post.create }
257
+ end
258
+
259
+ it 'should index all instances' do
260
+ Post.reindex(:batch_size => nil)
261
+ Sunspot.commit
262
+ Post.search.results.to_set.should == @posts.to_set
263
+ end
264
+
265
+ it 'should remove all currently indexed instances' do
266
+ old_post = Post.create!
267
+ old_post.index!
268
+ old_post.destroy
269
+ Post.reindex
270
+ Sunspot.commit
271
+ Post.search.results.to_set.should == @posts.to_set
272
+ end
273
+
274
+ describe "using batch sizes" do
275
+ it 'should index with a specified batch size' do
276
+ Post.reindex(:batch_size => 1)
277
+ Sunspot.commit
278
+ Post.search.results.to_set.should == @posts.to_set
279
+ end
280
+ end
281
+ end
282
+
283
+
284
+
285
+ describe "reindex()" do
286
+
287
+ before(:each) do
288
+ @posts = Array.new(10) { Post.create }
289
+ end
290
+
291
+ describe "when not using batches" do
292
+
293
+ it "should select all if the batch_size is nil" do
294
+ Post.should_receive(:all).with(:include => []).and_return([])
295
+ Post.reindex(:batch_size => nil)
296
+ end
297
+
298
+ it "should search for models with includes" do
299
+ Post.should_receive(:all).with(:include => :author).and_return([])
300
+ Post.reindex(:batch_size => nil, :include => :author)
301
+ end
302
+
303
+ end
304
+
305
+ describe "when using batches" do
306
+
307
+ it "should use the default options" do
308
+ Post.should_receive(:all).with do |params|
309
+ params[:limit].should == 500
310
+ params[:include].should == []
311
+ params[:conditions].should == ['posts.id > ?', 0]
312
+ params[:order].should == 'id'
313
+ end.and_return(@posts)
314
+ Post.reindex
315
+ end
316
+
317
+ it "should set the conditions using the overridden table attributes" do
318
+ @posts = Array.new(10) { Author.create }
319
+ Author.should_receive(:all).with do |params|
320
+ params[:conditions].should == ['writers.writer_id > ?', 0]
321
+ params[:order].should == 'writer_id'
322
+ end.and_return(@posts)
323
+ Author.reindex
324
+ end
325
+
326
+ it "should count the number of records to index" do
327
+ Post.should_receive(:count).and_return(10)
328
+ Post.reindex
329
+ end
330
+
331
+ it "should override the batch_size" do
332
+ Post.should_receive(:all).with do |params|
333
+ params[:limit].should == 20
334
+ @posts
335
+ end.and_return(@posts)
336
+ Post.reindex(:batch_size => 20)
337
+ end
338
+
339
+ it "should set the include option" do
340
+ Post.should_receive(:all).with do |params|
341
+ params[:include].should == [{:author => :address}]
342
+ @posts
343
+ end.and_return(@posts)
344
+ Post.reindex(:include => [{:author => :address}])
345
+ end
346
+
347
+ it "should set the include option from the searchable options" do
348
+ @blogs = Array.new(10) { Blog.create }
349
+ Blog.should_receive(:all).with do |params|
350
+ params[:include].should == [{ :posts => :author }, :comments]
351
+ @blogs
352
+ end.and_return(@blogs)
353
+ Blog.reindex
354
+ end
355
+
356
+ it "should commit after indexing each batch" do
357
+ Sunspot.should_receive(:commit).twice
358
+ Post.reindex(:batch_size => 5)
359
+ end
360
+
361
+ it "should commit after indexing everything" do
362
+ Sunspot.should_receive(:commit).once
363
+ Post.reindex(:batch_commit => false)
364
+ end
365
+
366
+ end
367
+ end
368
+
369
+ describe "more_like_this()" do
370
+ before(:each) do
371
+ @posts = [
372
+ Post.create!(:title => 'Post123', :body => "one two three"),
373
+ Post.create!(:title => 'Post345', :body => "three four five"),
374
+ Post.create!(:title => 'Post456', :body => "four five six"),
375
+ Post.create!(:title => 'Post234', :body => "two three four"),
376
+ ]
377
+ @posts_with_auto = [
378
+ PostWithAuto.create!(:body => "one two three"),
379
+ PostWithAuto.create!(:body => "four five six")
380
+ ]
381
+ @posts.each { |p| p.index! }
382
+ end
383
+
384
+ it "should return results" do
385
+ @posts.first.more_like_this.results.should == [@posts[3], @posts[1]]
386
+ end
387
+
388
+ it "should return results for specified classes" do
389
+ @posts.first.more_like_this(Post, PostWithAuto).results.to_set.should ==
390
+ Set[@posts_with_auto[0], @posts[1], @posts[3]]
391
+ end
392
+ end
393
+
394
+ describe 'more_like_this_ids()' do
395
+ before :each do
396
+ @posts = [
397
+ Post.create!(:title => 'Post123', :body => "one two three"),
398
+ Post.create!(:title => 'Post345', :body => "three four five"),
399
+ Post.create!(:title => 'Post456', :body => "four five six"),
400
+ Post.create!(:title => 'Post234', :body => "two three four"),
401
+ ]
402
+ @posts.each { |p| p.index! }
403
+ end
404
+
405
+ it 'should return IDs' do
406
+ @posts.first.more_like_this_ids.to_set.should == [@posts[3], @posts[1]].map { |post| post.id }.to_set
407
+ end
408
+ end
409
+ end
@@ -0,0 +1,52 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe 'request lifecycle', :type => :controller do
4
+ before(:each) do
5
+ Sunspot::Rails.configuration = @configuration = Sunspot::Rails::Configuration.new
6
+ end
7
+
8
+ after(:each) do
9
+ Sunspot::Rails.configuration = nil
10
+ end
11
+ controller_name :posts
12
+
13
+ it 'should automatically commit after each action if specified' do
14
+ @configuration.user_configuration = { 'auto_commit_after_request' => true }
15
+ Sunspot.should_receive(:commit_if_dirty)
16
+ post :create, :post => { :title => 'Test 1' }
17
+ end
18
+
19
+ it 'should not commit, if configuration is set to false' do
20
+ @configuration.user_configuration = { 'auto_commit_after_request' => false }
21
+ Sunspot.should_not_receive(:commit_if_dirty)
22
+ post :create, :post => { :title => 'Test 1' }
23
+ end
24
+
25
+ it 'should commit if configuration is not specified' do
26
+ @configuration.user_configuration = {}
27
+ Sunspot.should_receive(:commit_if_dirty)
28
+ post :create, :post => { :title => 'Test 1' }
29
+ end
30
+
31
+ ### auto_commit_if_delete_dirty
32
+
33
+ it 'should automatically commit after each delete if specified' do
34
+ @configuration.user_configuration = { 'auto_commit_after_request' => false,
35
+ 'auto_commit_after_delete_request' => true }
36
+ Sunspot.should_receive(:commit_if_delete_dirty)
37
+ post :create, :post => { :title => 'Test 1' }
38
+ end
39
+
40
+ it 'should not automatically commit on delete if configuration is set to false' do
41
+ @configuration.user_configuration = { 'auto_commit_after_request' => false,
42
+ 'auto_commit_after_delete_request' => false }
43
+ Sunspot.should_not_receive(:commit_if_delete_dirty)
44
+ post :create, :post => { :title => 'Test 1' }
45
+ end
46
+
47
+ it 'should not automatically commit on delete if configuration is not specified' do
48
+ @configuration.user_configuration = { 'auto_commit_after_request' => false }
49
+ Sunspot.should_not_receive(:commit_if_delete_dirty)
50
+ post :create, :post => { :title => 'Test 1' }
51
+ end
52
+ end