hariton-thinking-sphinx 1.2.7.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 (93) hide show
  1. data/LICENCE +20 -0
  2. data/README.textile +156 -0
  3. data/VERSION.yml +4 -0
  4. data/lib/thinking_sphinx.rb +210 -0
  5. data/lib/thinking_sphinx/active_record.rb +298 -0
  6. data/lib/thinking_sphinx/active_record/attribute_updates.rb +48 -0
  7. data/lib/thinking_sphinx/active_record/delta.rb +87 -0
  8. data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
  9. data/lib/thinking_sphinx/active_record/scopes.rb +39 -0
  10. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
  11. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
  12. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +136 -0
  13. data/lib/thinking_sphinx/association.rb +164 -0
  14. data/lib/thinking_sphinx/attribute.rb +329 -0
  15. data/lib/thinking_sphinx/class_facet.rb +15 -0
  16. data/lib/thinking_sphinx/configuration.rb +282 -0
  17. data/lib/thinking_sphinx/core/string.rb +15 -0
  18. data/lib/thinking_sphinx/deltas.rb +30 -0
  19. data/lib/thinking_sphinx/deltas/datetime_delta.rb +50 -0
  20. data/lib/thinking_sphinx/deltas/default_delta.rb +68 -0
  21. data/lib/thinking_sphinx/deltas/delayed_delta.rb +30 -0
  22. data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +24 -0
  23. data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +27 -0
  24. data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +26 -0
  25. data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
  26. data/lib/thinking_sphinx/excerpter.rb +22 -0
  27. data/lib/thinking_sphinx/facet.rb +108 -0
  28. data/lib/thinking_sphinx/facet_search.rb +134 -0
  29. data/lib/thinking_sphinx/field.rb +82 -0
  30. data/lib/thinking_sphinx/index.rb +99 -0
  31. data/lib/thinking_sphinx/index/builder.rb +287 -0
  32. data/lib/thinking_sphinx/index/faux_column.rb +110 -0
  33. data/lib/thinking_sphinx/property.rb +160 -0
  34. data/lib/thinking_sphinx/rails_additions.rb +150 -0
  35. data/lib/thinking_sphinx/search.rb +671 -0
  36. data/lib/thinking_sphinx/search_methods.rb +421 -0
  37. data/lib/thinking_sphinx/source.rb +150 -0
  38. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  39. data/lib/thinking_sphinx/source/sql.rb +128 -0
  40. data/lib/thinking_sphinx/tasks.rb +165 -0
  41. data/rails/init.rb +14 -0
  42. data/spec/lib/thinking_sphinx/active_record/delta_spec.rb +136 -0
  43. data/spec/lib/thinking_sphinx/active_record/has_many_association_spec.rb +53 -0
  44. data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +96 -0
  45. data/spec/lib/thinking_sphinx/active_record_spec.rb +354 -0
  46. data/spec/lib/thinking_sphinx/association_spec.rb +246 -0
  47. data/spec/lib/thinking_sphinx/attribute_spec.rb +465 -0
  48. data/spec/lib/thinking_sphinx/configuration_spec.rb +268 -0
  49. data/spec/lib/thinking_sphinx/core/string_spec.rb +9 -0
  50. data/spec/lib/thinking_sphinx/excerpter_spec.rb +49 -0
  51. data/spec/lib/thinking_sphinx/facet_search_spec.rb +176 -0
  52. data/spec/lib/thinking_sphinx/facet_spec.rb +302 -0
  53. data/spec/lib/thinking_sphinx/field_spec.rb +154 -0
  54. data/spec/lib/thinking_sphinx/index/builder_spec.rb +355 -0
  55. data/spec/lib/thinking_sphinx/index/faux_column_spec.rb +30 -0
  56. data/spec/lib/thinking_sphinx/index_spec.rb +45 -0
  57. data/spec/lib/thinking_sphinx/rails_additions_spec.rb +203 -0
  58. data/spec/lib/thinking_sphinx/search_methods_spec.rb +152 -0
  59. data/spec/lib/thinking_sphinx/search_spec.rb +993 -0
  60. data/spec/lib/thinking_sphinx/source_spec.rb +217 -0
  61. data/spec/lib/thinking_sphinx_spec.rb +161 -0
  62. data/tasks/distribution.rb +49 -0
  63. data/tasks/rails.rake +1 -0
  64. data/tasks/testing.rb +78 -0
  65. data/vendor/after_commit/LICENSE +20 -0
  66. data/vendor/after_commit/README +16 -0
  67. data/vendor/after_commit/Rakefile +22 -0
  68. data/vendor/after_commit/init.rb +8 -0
  69. data/vendor/after_commit/lib/after_commit.rb +45 -0
  70. data/vendor/after_commit/lib/after_commit/active_record.rb +114 -0
  71. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +103 -0
  72. data/vendor/after_commit/test/after_commit_test.rb +53 -0
  73. data/vendor/delayed_job/lib/delayed/job.rb +251 -0
  74. data/vendor/delayed_job/lib/delayed/message_sending.rb +7 -0
  75. data/vendor/delayed_job/lib/delayed/performable_method.rb +55 -0
  76. data/vendor/delayed_job/lib/delayed/worker.rb +54 -0
  77. data/vendor/riddle/lib/riddle.rb +30 -0
  78. data/vendor/riddle/lib/riddle/client.rb +719 -0
  79. data/vendor/riddle/lib/riddle/client/filter.rb +53 -0
  80. data/vendor/riddle/lib/riddle/client/message.rb +70 -0
  81. data/vendor/riddle/lib/riddle/client/response.rb +94 -0
  82. data/vendor/riddle/lib/riddle/configuration.rb +33 -0
  83. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +49 -0
  84. data/vendor/riddle/lib/riddle/configuration/index.rb +146 -0
  85. data/vendor/riddle/lib/riddle/configuration/indexer.rb +19 -0
  86. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
  87. data/vendor/riddle/lib/riddle/configuration/searchd.rb +46 -0
  88. data/vendor/riddle/lib/riddle/configuration/section.rb +43 -0
  89. data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
  90. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +39 -0
  91. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +28 -0
  92. data/vendor/riddle/lib/riddle/controller.rb +54 -0
  93. metadata +169 -0
@@ -0,0 +1,53 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe 'ThinkingSphinx::ActiveRecord::HasManyAssociation' do
4
+ describe "search method" do
5
+ before :each do
6
+ Friendship.stub_method(:search => true)
7
+
8
+ @person = Person.find(:first)
9
+ @index = Friendship.sphinx_indexes.first
10
+ end
11
+
12
+ it "should raise an error if the required attribute doesn't exist" do
13
+ @index.stub_method(:attributes => [])
14
+
15
+ lambda { @person.friendships.search "test" }.should raise_error(RuntimeError)
16
+
17
+ @index.unstub_method(:attributes)
18
+ end
19
+
20
+ it "should add a filter for the attribute into a normal search call" do
21
+ @person.friendships.search "test"
22
+
23
+ Friendship.should have_received(:search).with(
24
+ "test", :with => {:person_id => @person.id}
25
+ )
26
+ end
27
+ end
28
+
29
+ describe "search method for has_many :through" do
30
+ before :each do
31
+ Person.stub_method(:search => true)
32
+
33
+ @person = Person.find(:first)
34
+ @index = Person.sphinx_indexes.first
35
+ end
36
+
37
+ it "should raise an error if the required attribute doesn't exist" do
38
+ @index.stub_method(:attributes => [])
39
+
40
+ lambda { @person.friends.search "test" }.should raise_error(RuntimeError)
41
+
42
+ @index.unstub_method(:attributes)
43
+ end
44
+
45
+ it "should add a filter for the attribute into a normal search call" do
46
+ @person.friends.search "test"
47
+
48
+ Person.should have_received(:search).with(
49
+ "test", :with => {:friendly_ids => @person.id}
50
+ )
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::ActiveRecord::Scopes do
4
+ after :each do
5
+ Alpha.remove_sphinx_scopes
6
+ end
7
+
8
+ it "should be included into models with indexes" do
9
+ Alpha.included_modules.should include(ThinkingSphinx::ActiveRecord::Scopes)
10
+ end
11
+
12
+ it "should not be included into models without indexes" do
13
+ Gamma.included_modules.should_not include(
14
+ ThinkingSphinx::ActiveRecord::Scopes
15
+ )
16
+ end
17
+
18
+ describe '.sphinx_scope' do
19
+ before :each do
20
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
21
+ end
22
+
23
+ it "should define a method on the model" do
24
+ Alpha.should respond_to(:by_name)
25
+ end
26
+ end
27
+
28
+ describe '.sphinx_scopes' do
29
+ before :each do
30
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
31
+ end
32
+
33
+ it "should return an array of defined scope names as symbols" do
34
+ Alpha.sphinx_scopes.should == [:by_name]
35
+ end
36
+ end
37
+
38
+ describe '.remove_sphinx_scopes' do
39
+ before :each do
40
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
41
+ Alpha.remove_sphinx_scopes
42
+ end
43
+
44
+ it "should remove sphinx scope methods" do
45
+ Alpha.should_not respond_to(:by_name)
46
+ end
47
+
48
+ it "should empty the list of sphinx scopes" do
49
+ Alpha.sphinx_scopes.should be_empty
50
+ end
51
+ end
52
+
53
+ describe '.example_scope' do
54
+ before :each do
55
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
56
+ Alpha.sphinx_scope(:by_foo) { |foo| {:conditions => {:foo => foo}} }
57
+ Alpha.sphinx_scope(:with_betas) { {:classes => [Beta]} }
58
+ end
59
+
60
+ it "should return a ThinkingSphinx::Search object" do
61
+ Alpha.by_name('foo').should be_a(ThinkingSphinx::Search)
62
+ end
63
+
64
+ it "should set the classes option" do
65
+ Alpha.by_name('foo').options[:classes].should == [Alpha]
66
+ end
67
+
68
+ it "should be able to be called on a ThinkingSphinx::Search object" do
69
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
70
+ lambda {
71
+ search.by_name('foo')
72
+ }.should_not raise_error
73
+ end
74
+
75
+ it "should return the search object it gets called upon" do
76
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
77
+ search.by_name('foo').should == search
78
+ end
79
+
80
+ it "should apply the scope options to the underlying search object" do
81
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
82
+ search.by_name('foo').options[:conditions].should == {:name => 'foo'}
83
+ end
84
+
85
+ it "should combine hash option scopes such as :conditions" do
86
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
87
+ search.by_name('foo').by_foo('bar').options[:conditions].
88
+ should == {:name => 'foo', :foo => 'bar'}
89
+ end
90
+
91
+ it "should combine array option scopes such as :classes" do
92
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
93
+ search.with_betas.options[:classes].should == [Alpha, Beta]
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,354 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe "ThinkingSphinx::ActiveRecord" do
4
+ describe "define_index method" do
5
+ before :each do
6
+ module ::TestModule
7
+ class TestModel < ActiveRecord::Base; end
8
+ end
9
+
10
+ TestModule::TestModel.stub_methods(
11
+ :before_save => true,
12
+ :after_commit => true,
13
+ :after_destroy => true
14
+ )
15
+
16
+ @index = ThinkingSphinx::Index.stub_instance(:delta? => false)
17
+ ThinkingSphinx::Index::Builder.stub_method(:generate => @index)
18
+ end
19
+
20
+ after :each do
21
+ # Remove the class so we can redefine it
22
+ TestModule.send(:remove_const, :TestModel)
23
+
24
+ ThinkingSphinx.indexed_models.delete "TestModule::TestModel"
25
+ end
26
+
27
+ it "should do nothing if indexes are disabled" do
28
+ ThinkingSphinx.stub_method(:define_indexes? => false)
29
+
30
+ TestModule::TestModel.define_index {}
31
+ ThinkingSphinx::Index.should_not have_received(:new)
32
+
33
+ ThinkingSphinx.unstub_method(:define_indexes?)
34
+ end
35
+
36
+ it "should add a new index to the model" do
37
+ TestModule::TestModel.define_index {}
38
+
39
+ TestModule::TestModel.sphinx_indexes.length.should == 1
40
+ end
41
+
42
+ it "should add to ThinkingSphinx.indexed_models if the model doesn't already exist in the array" do
43
+ TestModule::TestModel.define_index do; end
44
+
45
+ ThinkingSphinx.indexed_models.should include("TestModule::TestModel")
46
+ end
47
+
48
+ it "shouldn't add to ThinkingSphinx.indexed_models if the model already exists in the array" do
49
+ TestModule::TestModel.define_index do; end
50
+
51
+ ThinkingSphinx.indexed_models.select { |model|
52
+ model == "TestModule::TestModel"
53
+ }.length.should == 1
54
+
55
+ TestModule::TestModel.define_index do; end
56
+
57
+ ThinkingSphinx.indexed_models.select { |model|
58
+ model == "TestModule::TestModel"
59
+ }.length.should == 1
60
+ end
61
+
62
+ it "should add before_save and after_commit hooks to the model if delta indexing is enabled" do
63
+ @index.stub_method(:delta? => true)
64
+
65
+ TestModule::TestModel.define_index do; end
66
+
67
+ TestModule::TestModel.should have_received(:before_save).with(:toggle_delta)
68
+ TestModule::TestModel.should have_received(:after_commit).with(:index_delta)
69
+ end
70
+
71
+ it "should not add before_save and after_commit hooks to the model if delta indexing is disabled" do
72
+ TestModule::TestModel.define_index do; end
73
+
74
+ TestModule::TestModel.should_not have_received(:before_save).with(:toggle_delta)
75
+ TestModule::TestModel.should_not have_received(:after_commit).with(:index_delta)
76
+ end
77
+
78
+ it "should add an after_destroy hook with delta indexing enabled" do
79
+ @index.stub_method(:delta? => true)
80
+
81
+ TestModule::TestModel.define_index do; end
82
+
83
+ TestModule::TestModel.should have_received(:after_destroy).with(:toggle_deleted)
84
+ end
85
+
86
+ it "should add an after_destroy hook with delta indexing disabled" do
87
+ TestModule::TestModel.define_index do; end
88
+
89
+ TestModule::TestModel.should have_received(:after_destroy).with(:toggle_deleted)
90
+ end
91
+
92
+ it "should return the new index" do
93
+ TestModule::TestModel.define_index.should == @index
94
+ end
95
+
96
+ it "should die quietly if there is a database error" do
97
+ ThinkingSphinx::Index::Builder.stub_method_to_raise(:generate => Mysql::Error)
98
+
99
+ lambda {
100
+ TestModule::TestModel.define_index
101
+ }.should_not raise_error
102
+ end
103
+
104
+ it "should die noisily if there is a non-database error" do
105
+ ThinkingSphinx::Index::Builder.stub_method_to_raise(:generate => StandardError)
106
+
107
+ lambda {
108
+ TestModule::TestModel.define_index
109
+ }.should raise_error
110
+ end
111
+ end
112
+
113
+ describe "index methods" do
114
+ before(:all) do
115
+ @person = Person.find(:first)
116
+ end
117
+
118
+ describe "in_both_indexes?" do
119
+ it "should return true if in core and delta indexes" do
120
+ @person.should_receive(:in_core_index?).and_return(true)
121
+ @person.should_receive(:in_delta_index?).and_return(true)
122
+ @person.in_both_indexes?.should be_true
123
+ end
124
+
125
+ it "should return false if in one index and not the other" do
126
+ @person.should_receive(:in_core_index?).and_return(true)
127
+ @person.should_receive(:in_delta_index?).and_return(false)
128
+ @person.in_both_indexes?.should be_false
129
+ end
130
+ end
131
+
132
+ describe "in_core_index?" do
133
+ it "should call in_index? with core" do
134
+ @person.should_receive(:in_index?).with('core')
135
+ @person.in_core_index?
136
+ end
137
+ end
138
+
139
+ describe "in_delta_index?" do
140
+ it "should call in_index? with delta" do
141
+ @person.should_receive(:in_index?).with('delta')
142
+ @person.in_delta_index?
143
+ end
144
+ end
145
+
146
+ describe "in_index?" do
147
+ it "should return true if in the specified index" do
148
+ @person.should_receive(:sphinx_document_id).and_return(1)
149
+ @person.should_receive(:sphinx_index_name).and_return('person_core')
150
+ Person.should_receive(:search_for_id).with(1, 'person_core').and_return(true)
151
+
152
+ @person.in_index?('core').should be_true
153
+ end
154
+ end
155
+ end
156
+
157
+ describe "source_of_sphinx_index method" do
158
+ it "should return self if model defines an index" do
159
+ Person.source_of_sphinx_index.should == Person
160
+ end
161
+
162
+ it "should return the parent if model inherits an index" do
163
+ Admin::Person.source_of_sphinx_index.should == Person
164
+ end
165
+ end
166
+
167
+ describe "to_crc32 method" do
168
+ it "should return an integer" do
169
+ Person.to_crc32.should be_a_kind_of(Integer)
170
+ end
171
+ end
172
+
173
+ describe "to_crc32s method" do
174
+ it "should return an array" do
175
+ Person.to_crc32s.should be_a_kind_of(Array)
176
+ end
177
+ end
178
+
179
+ describe "toggle_deleted method" do
180
+ before :each do
181
+ ThinkingSphinx.stub_method(:sphinx_running? => true)
182
+
183
+ @configuration = ThinkingSphinx::Configuration.instance
184
+ @configuration.stub_methods(
185
+ :address => "an address",
186
+ :port => 123
187
+ )
188
+ @client = Riddle::Client.new
189
+ @client.stub!(:update => true)
190
+ @person = Person.find(:first)
191
+
192
+ Riddle::Client.stub_method(:new => @client)
193
+ Person.sphinx_indexes.each { |index| index.stub_method(:delta? => false) }
194
+ @person.stub_method(:in_core_index? => true)
195
+ end
196
+
197
+ it "should create a client using the Configuration's address and port" do
198
+ @person.toggle_deleted
199
+
200
+ Riddle::Client.should have_received(:new).with(
201
+ @configuration.address, @configuration.port
202
+ )
203
+ end
204
+
205
+ it "should update the core index's deleted flag if in core index" do
206
+ @client.should_receive(:update).with(
207
+ "person_core", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
208
+ )
209
+
210
+ @person.toggle_deleted
211
+ end
212
+
213
+ it "shouldn't update the core index's deleted flag if the record isn't in it" do
214
+ @person.stub_method(:in_core_index? => false)
215
+ @client.should_not_receive(:update).with(
216
+ "person_core", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
217
+ )
218
+
219
+ @person.toggle_deleted
220
+ end
221
+
222
+ it "shouldn't attempt to update the deleted flag if sphinx isn't running" do
223
+ ThinkingSphinx.stub_method(:sphinx_running? => false)
224
+ @client.should_not_receive(:update)
225
+
226
+ @person.toggle_deleted
227
+
228
+ @person.should_not have_received(:in_core_index?)
229
+ end
230
+
231
+ it "should update the delta index's deleted flag if delta indexes are enabled and the instance's delta is true" do
232
+ ThinkingSphinx.stub_method(:deltas_enabled? => true)
233
+ Person.sphinx_indexes.each { |index| index.stub_method(:delta? => true) }
234
+ @person.delta = true
235
+ @client.should_receive(:update).with(
236
+ "person_delta", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
237
+ )
238
+
239
+ @person.toggle_deleted
240
+ end
241
+
242
+ it "should not update the delta index's deleted flag if delta indexes are enabled and the instance's delta is false" do
243
+ ThinkingSphinx.stub_method(:deltas_enabled? => true)
244
+ Person.sphinx_indexes.each { |index| index.stub_method(:delta? => true) }
245
+ @person.delta = false
246
+ @client.should_not_receive(:update).with(
247
+ "person_delta", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
248
+ )
249
+
250
+ @person.toggle_deleted
251
+ end
252
+
253
+ it "should not update the delta index's deleted flag if delta indexes are enabled and the instance's delta is equivalent to false" do
254
+ ThinkingSphinx.stub_method(:deltas_enabled? => true)
255
+ Person.sphinx_indexes.each { |index| index.stub_method(:delta? => true) }
256
+ @person.delta = 0
257
+ @client.should_not_receive(:update).with(
258
+ "person_delta", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
259
+ )
260
+
261
+ @person.toggle_deleted
262
+ end
263
+
264
+ it "shouldn't update the delta index if delta indexes are disabled" do
265
+ ThinkingSphinx.stub_method(:deltas_enabled? => true)
266
+ @client.should_not_receive(:update).with(
267
+ "person_delta", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
268
+ )
269
+
270
+ @person.toggle_deleted
271
+ end
272
+
273
+ it "should not update the delta index if delta indexing is disabled" do
274
+ ThinkingSphinx.stub_method(:deltas_enabled? => false)
275
+ Person.sphinx_indexes.each { |index| index.stub_method(:delta? => true) }
276
+ @person.delta = true
277
+ @client.should_not_receive(:update).with(
278
+ "person_delta", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
279
+ )
280
+
281
+ @person.toggle_deleted
282
+ end
283
+
284
+ it "should not update either index if updates are disabled" do
285
+ ThinkingSphinx.stub_methods(
286
+ :updates_enabled? => false,
287
+ :deltas_enabled => true
288
+ )
289
+ Person.sphinx_indexes.each { |index| index.stub_method(:delta? => true) }
290
+ @person.delta = true
291
+ @client.should_not_receive(:update)
292
+
293
+ @person.toggle_deleted
294
+ end
295
+ end
296
+
297
+ describe "sphinx_indexes in the inheritance chain (STI)" do
298
+ it "should hand defined indexes on a class down to its child classes" do
299
+ Child.sphinx_indexes.should include(*Person.sphinx_indexes)
300
+ end
301
+
302
+ it "should allow associations to other STI models" do
303
+ source = Child.sphinx_indexes.last.sources.first
304
+ sql = source.to_riddle_for_core(0, 0).sql_query
305
+ sql.gsub!('$start', '0').gsub!('$end', '100')
306
+ lambda {
307
+ Child.connection.execute(sql)
308
+ }.should_not raise_error(ActiveRecord::StatementInvalid)
309
+ end
310
+ end
311
+
312
+ it "should return the sphinx document id as expected" do
313
+ person = Person.find(:first)
314
+ model_count = ThinkingSphinx.indexed_models.length
315
+ offset = ThinkingSphinx.indexed_models.index("Person")
316
+
317
+ (person.id * model_count + offset).should == person.sphinx_document_id
318
+
319
+ alpha = Alpha.find(:first)
320
+ offset = ThinkingSphinx.indexed_models.index("Alpha")
321
+
322
+ (alpha.id * model_count + offset).should == alpha.sphinx_document_id
323
+
324
+ beta = Beta.find(:first)
325
+ offset = ThinkingSphinx.indexed_models.index("Beta")
326
+
327
+ (beta.id * model_count + offset).should == beta.sphinx_document_id
328
+ end
329
+
330
+ describe '#primary_key_for_sphinx' do
331
+ before :each do
332
+ @person = Person.find(:first)
333
+ end
334
+
335
+ after :each do
336
+ Person.set_sphinx_primary_key nil
337
+ end
338
+
339
+ it "should return the id by default" do
340
+ @person.primary_key_for_sphinx.should == @person.id
341
+ end
342
+
343
+ it "should use the sphinx primary key to determine the value" do
344
+ Person.set_sphinx_primary_key :first_name
345
+ @person.primary_key_for_sphinx.should == @person.first_name
346
+ end
347
+
348
+ it "should not use accessor methods but the attributes hash" do
349
+ id = @person.id
350
+ @person.stub!(:id => 'unique_hash')
351
+ @person.primary_key_for_sphinx.should == id
352
+ end
353
+ end
354
+ end