skalee-thinking-sphinx 1.3.14.1

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 (199) hide show
  1. data/LICENCE +20 -0
  2. data/README.textile +201 -0
  3. data/Rakefile +3 -0
  4. data/VERSION +1 -0
  5. data/contribute.rb +385 -0
  6. data/cucumber.yml +1 -0
  7. data/features/abstract_inheritance.feature +10 -0
  8. data/features/alternate_primary_key.feature +27 -0
  9. data/features/attribute_transformation.feature +22 -0
  10. data/features/attribute_updates.feature +51 -0
  11. data/features/deleting_instances.feature +67 -0
  12. data/features/direct_attributes.feature +11 -0
  13. data/features/excerpts.feature +13 -0
  14. data/features/extensible_delta_indexing.feature +9 -0
  15. data/features/facets.feature +82 -0
  16. data/features/facets_across_model.feature +29 -0
  17. data/features/handling_edits.feature +92 -0
  18. data/features/retry_stale_indexes.feature +24 -0
  19. data/features/searching_across_models.feature +20 -0
  20. data/features/searching_by_index.feature +40 -0
  21. data/features/searching_by_model.feature +175 -0
  22. data/features/searching_with_find_arguments.feature +56 -0
  23. data/features/sphinx_detection.feature +25 -0
  24. data/features/sphinx_scopes.feature +42 -0
  25. data/features/step_definitions/alpha_steps.rb +16 -0
  26. data/features/step_definitions/beta_steps.rb +7 -0
  27. data/features/step_definitions/common_steps.rb +188 -0
  28. data/features/step_definitions/extensible_delta_indexing_steps.rb +7 -0
  29. data/features/step_definitions/facet_steps.rb +96 -0
  30. data/features/step_definitions/find_arguments_steps.rb +36 -0
  31. data/features/step_definitions/gamma_steps.rb +15 -0
  32. data/features/step_definitions/scope_steps.rb +15 -0
  33. data/features/step_definitions/search_steps.rb +89 -0
  34. data/features/step_definitions/sphinx_steps.rb +35 -0
  35. data/features/sti_searching.feature +19 -0
  36. data/features/support/database.example.yml +3 -0
  37. data/features/support/db/.gitignore +1 -0
  38. data/features/support/db/fixtures/alphas.rb +10 -0
  39. data/features/support/db/fixtures/authors.rb +1 -0
  40. data/features/support/db/fixtures/betas.rb +10 -0
  41. data/features/support/db/fixtures/boxes.rb +9 -0
  42. data/features/support/db/fixtures/categories.rb +1 -0
  43. data/features/support/db/fixtures/cats.rb +3 -0
  44. data/features/support/db/fixtures/comments.rb +24 -0
  45. data/features/support/db/fixtures/developers.rb +29 -0
  46. data/features/support/db/fixtures/dogs.rb +3 -0
  47. data/features/support/db/fixtures/extensible_betas.rb +10 -0
  48. data/features/support/db/fixtures/foxes.rb +3 -0
  49. data/features/support/db/fixtures/gammas.rb +10 -0
  50. data/features/support/db/fixtures/music.rb +4 -0
  51. data/features/support/db/fixtures/people.rb +1001 -0
  52. data/features/support/db/fixtures/posts.rb +6 -0
  53. data/features/support/db/fixtures/robots.rb +14 -0
  54. data/features/support/db/fixtures/tags.rb +27 -0
  55. data/features/support/db/migrations/create_alphas.rb +8 -0
  56. data/features/support/db/migrations/create_animals.rb +5 -0
  57. data/features/support/db/migrations/create_authors.rb +3 -0
  58. data/features/support/db/migrations/create_authors_posts.rb +6 -0
  59. data/features/support/db/migrations/create_betas.rb +5 -0
  60. data/features/support/db/migrations/create_boxes.rb +5 -0
  61. data/features/support/db/migrations/create_categories.rb +3 -0
  62. data/features/support/db/migrations/create_comments.rb +10 -0
  63. data/features/support/db/migrations/create_developers.rb +9 -0
  64. data/features/support/db/migrations/create_extensible_betas.rb +5 -0
  65. data/features/support/db/migrations/create_gammas.rb +3 -0
  66. data/features/support/db/migrations/create_genres.rb +3 -0
  67. data/features/support/db/migrations/create_music.rb +6 -0
  68. data/features/support/db/migrations/create_people.rb +13 -0
  69. data/features/support/db/migrations/create_posts.rb +5 -0
  70. data/features/support/db/migrations/create_robots.rb +4 -0
  71. data/features/support/db/migrations/create_taggings.rb +5 -0
  72. data/features/support/db/migrations/create_tags.rb +4 -0
  73. data/features/support/env.rb +21 -0
  74. data/features/support/lib/generic_delta_handler.rb +8 -0
  75. data/features/support/models/alpha.rb +22 -0
  76. data/features/support/models/animal.rb +5 -0
  77. data/features/support/models/author.rb +3 -0
  78. data/features/support/models/beta.rb +8 -0
  79. data/features/support/models/box.rb +8 -0
  80. data/features/support/models/cat.rb +3 -0
  81. data/features/support/models/category.rb +4 -0
  82. data/features/support/models/comment.rb +10 -0
  83. data/features/support/models/developer.rb +16 -0
  84. data/features/support/models/dog.rb +3 -0
  85. data/features/support/models/extensible_beta.rb +9 -0
  86. data/features/support/models/fox.rb +5 -0
  87. data/features/support/models/gamma.rb +5 -0
  88. data/features/support/models/genre.rb +3 -0
  89. data/features/support/models/medium.rb +5 -0
  90. data/features/support/models/music.rb +8 -0
  91. data/features/support/models/person.rb +23 -0
  92. data/features/support/models/post.rb +21 -0
  93. data/features/support/models/robot.rb +12 -0
  94. data/features/support/models/tag.rb +3 -0
  95. data/features/support/models/tagging.rb +4 -0
  96. data/ginger_scenarios.rb +28 -0
  97. data/init.rb +5 -0
  98. data/install.rb +5 -0
  99. data/lib/cucumber/thinking_sphinx/external_world.rb +8 -0
  100. data/lib/cucumber/thinking_sphinx/internal_world.rb +126 -0
  101. data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
  102. data/lib/thinking_sphinx/active_record/attribute_updates.rb +19 -0
  103. data/lib/thinking_sphinx/active_record/delta.rb +47 -0
  104. data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
  105. data/lib/thinking_sphinx/active_record/scopes.rb +75 -0
  106. data/lib/thinking_sphinx/active_record.rb +348 -0
  107. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
  108. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
  109. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +143 -0
  110. data/lib/thinking_sphinx/association.rb +164 -0
  111. data/lib/thinking_sphinx/attribute.rb +362 -0
  112. data/lib/thinking_sphinx/auto_version.rb +22 -0
  113. data/lib/thinking_sphinx/class_facet.rb +15 -0
  114. data/lib/thinking_sphinx/configuration.rb +300 -0
  115. data/lib/thinking_sphinx/context.rb +68 -0
  116. data/lib/thinking_sphinx/core/array.rb +7 -0
  117. data/lib/thinking_sphinx/core/string.rb +15 -0
  118. data/lib/thinking_sphinx/deltas/default_delta.rb +62 -0
  119. data/lib/thinking_sphinx/deltas.rb +28 -0
  120. data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
  121. data/lib/thinking_sphinx/excerpter.rb +22 -0
  122. data/lib/thinking_sphinx/facet.rb +125 -0
  123. data/lib/thinking_sphinx/facet_search.rb +136 -0
  124. data/lib/thinking_sphinx/field.rb +82 -0
  125. data/lib/thinking_sphinx/index/builder.rb +296 -0
  126. data/lib/thinking_sphinx/index/faux_column.rb +110 -0
  127. data/lib/thinking_sphinx/index.rb +157 -0
  128. data/lib/thinking_sphinx/property.rb +162 -0
  129. data/lib/thinking_sphinx/rails_additions.rb +150 -0
  130. data/lib/thinking_sphinx/search.rb +769 -0
  131. data/lib/thinking_sphinx/search_methods.rb +439 -0
  132. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  133. data/lib/thinking_sphinx/source/sql.rb +130 -0
  134. data/lib/thinking_sphinx/source.rb +153 -0
  135. data/lib/thinking_sphinx/tasks.rb +131 -0
  136. data/lib/thinking_sphinx/test.rb +52 -0
  137. data/lib/thinking_sphinx.rb +225 -0
  138. data/rails/init.rb +16 -0
  139. data/recipes/thinking_sphinx.rb +3 -0
  140. data/spec/fixtures/data.sql +32 -0
  141. data/spec/fixtures/database.yml.default +3 -0
  142. data/spec/fixtures/models.rb +145 -0
  143. data/spec/fixtures/structure.sql +125 -0
  144. data/spec/spec_helper.rb +60 -0
  145. data/spec/sphinx_helper.rb +81 -0
  146. data/spec/thinking_sphinx/active_record/delta_spec.rb +128 -0
  147. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +55 -0
  148. data/spec/thinking_sphinx/active_record/scopes_spec.rb +177 -0
  149. data/spec/thinking_sphinx/active_record_spec.rb +622 -0
  150. data/spec/thinking_sphinx/association_spec.rb +239 -0
  151. data/spec/thinking_sphinx/attribute_spec.rb +570 -0
  152. data/spec/thinking_sphinx/auto_version_spec.rb +39 -0
  153. data/spec/thinking_sphinx/configuration_spec.rb +234 -0
  154. data/spec/thinking_sphinx/context_spec.rb +119 -0
  155. data/spec/thinking_sphinx/core/array_spec.rb +9 -0
  156. data/spec/thinking_sphinx/core/string_spec.rb +9 -0
  157. data/spec/thinking_sphinx/excerpter_spec.rb +57 -0
  158. data/spec/thinking_sphinx/facet_search_spec.rb +176 -0
  159. data/spec/thinking_sphinx/facet_spec.rb +333 -0
  160. data/spec/thinking_sphinx/field_spec.rb +154 -0
  161. data/spec/thinking_sphinx/index/builder_spec.rb +479 -0
  162. data/spec/thinking_sphinx/index/faux_column_spec.rb +30 -0
  163. data/spec/thinking_sphinx/index_spec.rb +183 -0
  164. data/spec/thinking_sphinx/rails_additions_spec.rb +203 -0
  165. data/spec/thinking_sphinx/search_methods_spec.rb +152 -0
  166. data/spec/thinking_sphinx/search_spec.rb +1181 -0
  167. data/spec/thinking_sphinx/source_spec.rb +235 -0
  168. data/spec/thinking_sphinx_spec.rb +204 -0
  169. data/tasks/distribution.rb +41 -0
  170. data/tasks/rails.rake +1 -0
  171. data/tasks/testing.rb +72 -0
  172. data/vendor/after_commit/.gitignore +1 -0
  173. data/vendor/after_commit/lib/after_commit/active_record.rb +122 -0
  174. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +168 -0
  175. data/vendor/after_commit/lib/after_commit/test_bypass.rb +30 -0
  176. data/vendor/after_commit/lib/after_commit.rb +70 -0
  177. data/vendor/riddle/lib/riddle/0.9.8.rb +1 -0
  178. data/vendor/riddle/lib/riddle/0.9.9/client/filter.rb +22 -0
  179. data/vendor/riddle/lib/riddle/0.9.9/client.rb +49 -0
  180. data/vendor/riddle/lib/riddle/0.9.9/configuration/searchd.rb +28 -0
  181. data/vendor/riddle/lib/riddle/0.9.9.rb +7 -0
  182. data/vendor/riddle/lib/riddle/auto_version.rb +11 -0
  183. data/vendor/riddle/lib/riddle/client/filter.rb +62 -0
  184. data/vendor/riddle/lib/riddle/client/message.rb +70 -0
  185. data/vendor/riddle/lib/riddle/client/response.rb +94 -0
  186. data/vendor/riddle/lib/riddle/client.rb +745 -0
  187. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +49 -0
  188. data/vendor/riddle/lib/riddle/configuration/index.rb +149 -0
  189. data/vendor/riddle/lib/riddle/configuration/indexer.rb +20 -0
  190. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
  191. data/vendor/riddle/lib/riddle/configuration/searchd.rb +28 -0
  192. data/vendor/riddle/lib/riddle/configuration/section.rb +43 -0
  193. data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
  194. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +53 -0
  195. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +29 -0
  196. data/vendor/riddle/lib/riddle/configuration.rb +33 -0
  197. data/vendor/riddle/lib/riddle/controller.rb +78 -0
  198. data/vendor/riddle/lib/riddle.rb +51 -0
  199. metadata +312 -0
@@ -0,0 +1,622 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::ActiveRecord do
4
+ before :each do
5
+ @existing_alpha_indexes = Alpha.sphinx_indexes.clone
6
+ @existing_beta_indexes = Beta.sphinx_indexes.clone
7
+
8
+ Alpha.send :defined_indexes=, false
9
+ Beta.send :defined_indexes=, false
10
+
11
+ Alpha.sphinx_indexes.clear
12
+ Beta.sphinx_indexes.clear
13
+ end
14
+
15
+ after :each do
16
+ Alpha.sphinx_indexes.replace @existing_alpha_indexes
17
+ Beta.sphinx_indexes.replace @existing_beta_indexes
18
+
19
+ Alpha.send :defined_indexes=, true
20
+ Beta.send :defined_indexes=, true
21
+
22
+ Alpha.sphinx_index_blocks.clear
23
+ Beta.sphinx_index_blocks.clear
24
+ end
25
+
26
+ describe '.define_index' do
27
+ it "should do nothing if indexes are disabled" do
28
+ ThinkingSphinx.define_indexes = false
29
+ ThinkingSphinx::Index.should_not_receive(:new)
30
+
31
+ Alpha.define_index { }
32
+ Alpha.define_indexes
33
+
34
+ ThinkingSphinx.define_indexes = true
35
+ end
36
+
37
+ it "should not evaluate the index block automatically" do
38
+ lambda {
39
+ Alpha.define_index { raise StandardError }
40
+ }.should_not raise_error
41
+ end
42
+
43
+ it "should add the model to the context collection" do
44
+ Alpha.define_index { indexes :name }
45
+
46
+ ThinkingSphinx.context.indexed_models.should include("Alpha")
47
+ end
48
+
49
+ it "should die quietly if there is a database error" do
50
+ ThinkingSphinx::Index::Builder.stub(:generate) { raise Mysql::Error }
51
+ Alpha.define_index { indexes :name }
52
+
53
+ lambda {
54
+ Alpha.define_indexes
55
+ }.should_not raise_error
56
+ end
57
+
58
+ it "should die noisily if there is a non-database error" do
59
+ ThinkingSphinx::Index::Builder.stub(:generate) { raise StandardError }
60
+ Alpha.define_index { indexes :name }
61
+
62
+ lambda {
63
+ Alpha.define_indexes
64
+ }.should raise_error
65
+ end
66
+
67
+ it "should set the index's name using the parameter if provided" do
68
+ Alpha.define_index('custom') { indexes :name }
69
+ Alpha.define_indexes
70
+
71
+ Alpha.sphinx_indexes.first.name.should == 'custom'
72
+ end
73
+
74
+ context 'callbacks' do
75
+ it "should add a before_validation callback to define_indexes" do
76
+ Alpha.should_receive(:before_validation).with(:define_indexes)
77
+
78
+ Alpha.define_index { }
79
+ end
80
+
81
+ it "should not add a before_validation callback twice" do
82
+ Alpha.should_receive(:before_validation).with(:define_indexes).once
83
+
84
+ Alpha.define_index { }
85
+ Alpha.define_index { }
86
+ end
87
+
88
+ it "should add a before_destroy callback to define_indexes" do
89
+ Alpha.should_receive(:before_destroy).with(:define_indexes)
90
+
91
+ Alpha.define_index { }
92
+ end
93
+
94
+ it "should not add a before_destroy callback twice" do
95
+ Alpha.should_receive(:before_destroy).with(:define_indexes).once
96
+
97
+ Alpha.define_index { }
98
+ Alpha.define_index { }
99
+ end
100
+
101
+ it "should add a toggle_deleted callback when defined" do
102
+ Alpha.should_receive(:after_destroy).with(:toggle_deleted)
103
+
104
+ Alpha.define_index { indexes :name }
105
+ Alpha.define_indexes
106
+ end
107
+
108
+ it "should not add toggle_deleted callback more than once" do
109
+ Alpha.should_receive(:after_destroy).with(:toggle_deleted).once
110
+
111
+ Alpha.define_index { indexes :name }
112
+ Alpha.define_index { indexes :name }
113
+ Alpha.define_indexes
114
+ end
115
+
116
+ it "should add a update_attribute_values callback when defined" do
117
+ Alpha.should_receive(:after_commit).with(:update_attribute_values)
118
+
119
+ Alpha.define_index { indexes :name }
120
+ Alpha.define_indexes
121
+ end
122
+
123
+ it "should not add update_attribute_values callback more than once" do
124
+ Alpha.should_receive(:after_commit).with(:update_attribute_values).once
125
+
126
+ Alpha.define_index { indexes :name }
127
+ Alpha.define_index { indexes :name }
128
+ Alpha.define_indexes
129
+ end
130
+
131
+ it "should add a toggle_delta callback if deltas are enabled" do
132
+ Beta.should_receive(:before_save).with(:toggle_delta)
133
+
134
+ Beta.define_index {
135
+ indexes :name
136
+ set_property :delta => true
137
+ }
138
+ Beta.define_indexes
139
+ end
140
+
141
+ it "should not add a toggle_delta callback if deltas are disabled" do
142
+ Alpha.should_not_receive(:before_save).with(:toggle_delta)
143
+
144
+ Alpha.define_index { indexes :name }
145
+ Alpha.define_indexes
146
+ end
147
+
148
+ it "should add the toggle_delta callback if deltas are disabled in other indexes" do
149
+ Beta.should_receive(:before_save).with(:toggle_delta).once
150
+
151
+ Beta.define_index { indexes :name }
152
+ Beta.define_index {
153
+ indexes :name
154
+ set_property :delta => true
155
+ }
156
+ Beta.define_indexes
157
+ end
158
+
159
+ it "should only add the toggle_delta callback once" do
160
+ Beta.should_receive(:before_save).with(:toggle_delta).once
161
+
162
+ Beta.define_index {
163
+ indexes :name
164
+ set_property :delta => true
165
+ }
166
+ Beta.define_index {
167
+ indexes :name
168
+ set_property :delta => true
169
+ }
170
+ Beta.define_indexes
171
+ end
172
+
173
+ it "should add an index_delta callback if deltas are enabled" do
174
+ Beta.stub!(:after_commit => true)
175
+ Beta.should_receive(:after_commit).with(:index_delta)
176
+
177
+ Beta.define_index {
178
+ indexes :name
179
+ set_property :delta => true
180
+ }
181
+ Beta.define_indexes
182
+ end
183
+
184
+ it "should not add an index_delta callback if deltas are disabled" do
185
+ Alpha.should_not_receive(:after_commit).with(:index_delta)
186
+
187
+ Alpha.define_index { indexes :name }
188
+ Alpha.define_indexes
189
+ end
190
+
191
+ it "should add the index_delta callback if deltas are disabled in other indexes" do
192
+ Beta.stub!(:after_commit => true)
193
+ Beta.should_receive(:after_commit).with(:index_delta).once
194
+
195
+ Beta.define_index { indexes :name }
196
+ Beta.define_index {
197
+ indexes :name
198
+ set_property :delta => true
199
+ }
200
+ Beta.define_indexes
201
+ end
202
+
203
+ it "should only add the index_delta callback once" do
204
+ Beta.stub!(:after_commit => true)
205
+ Beta.should_receive(:after_commit).with(:index_delta).once
206
+
207
+ Beta.define_index {
208
+ indexes :name
209
+ set_property :delta => true
210
+ }
211
+ Beta.define_index {
212
+ indexes :name
213
+ set_property :delta => true
214
+ }
215
+ Beta.define_indexes
216
+ end
217
+ end
218
+ end
219
+
220
+ describe '.define_indexes' do
221
+ it "should process define_index blocks" do
222
+ Beta.define_index { indexes :name }
223
+ Beta.sphinx_indexes.length.should == 0
224
+
225
+ Beta.define_indexes
226
+ Beta.sphinx_indexes.length.should == 1
227
+ end
228
+
229
+ it "should not re-add indexes" do
230
+ Beta.define_index { indexes :name }
231
+ Beta.define_indexes
232
+ Beta.define_indexes
233
+
234
+ Beta.sphinx_indexes.length.should == 1
235
+ end
236
+ end
237
+
238
+ describe "index methods" do
239
+ before(:all) do
240
+ @person = Person.find(:first)
241
+ end
242
+
243
+ describe "in_both_indexes?" do
244
+ it "should return true if in core and delta indexes" do
245
+ @person.should_receive(:in_core_index?).and_return(true)
246
+ @person.should_receive(:in_delta_index?).and_return(true)
247
+ @person.in_both_indexes?.should be_true
248
+ end
249
+
250
+ it "should return false if in one index and not the other" do
251
+ @person.should_receive(:in_core_index?).and_return(true)
252
+ @person.should_receive(:in_delta_index?).and_return(false)
253
+ @person.in_both_indexes?.should be_false
254
+ end
255
+ end
256
+
257
+ describe "in_core_index?" do
258
+ it "should call in_index? with core" do
259
+ @person.should_receive(:in_index?).with('core')
260
+ @person.in_core_index?
261
+ end
262
+ end
263
+
264
+ describe "in_delta_index?" do
265
+ it "should call in_index? with delta" do
266
+ @person.should_receive(:in_index?).with('delta')
267
+ @person.in_delta_index?
268
+ end
269
+ end
270
+
271
+ describe "in_index?" do
272
+ it "should return true if in the specified index" do
273
+ @person.should_receive(:sphinx_document_id).and_return(1)
274
+ @person.should_receive(:sphinx_index_name).and_return('person_core')
275
+ Person.should_receive(:search_for_id).with(1, 'person_core').and_return(true)
276
+
277
+ @person.in_index?('core').should be_true
278
+ end
279
+ end
280
+ end
281
+
282
+ describe '.source_of_sphinx_index' do
283
+ it "should return self if model defines an index" do
284
+ Person.source_of_sphinx_index.should == Person
285
+ end
286
+
287
+ it "should return the parent if model inherits an index" do
288
+ Admin::Person.source_of_sphinx_index.should == Person
289
+ end
290
+ end
291
+
292
+ describe '.to_crc32' do
293
+ it "should return an integer" do
294
+ Person.to_crc32.should be_a_kind_of(Integer)
295
+ end
296
+ end
297
+
298
+ describe '.to_crc32s' do
299
+ it "should return an array" do
300
+ Person.to_crc32s.should be_a_kind_of(Array)
301
+ end
302
+ end
303
+
304
+ describe "toggle_deleted method" do
305
+ before :each do
306
+ ThinkingSphinx.stub!(:sphinx_running? => true)
307
+
308
+ @configuration = ThinkingSphinx::Configuration.instance
309
+ @configuration.stub!(
310
+ :address => "an address",
311
+ :port => 123
312
+ )
313
+ @client = Riddle::Client.new
314
+ @client.stub!(:update => true)
315
+ @person = Person.find(:first)
316
+
317
+ @configuration.stub!(:client => @client)
318
+ Person.sphinx_indexes.each { |index| index.stub!(:delta? => false) }
319
+ Person.stub!(:search_for_id => true)
320
+ end
321
+
322
+ it "should update the core index's deleted flag if in core index" do
323
+ @client.should_receive(:update).with(
324
+ "person_core", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
325
+ )
326
+
327
+ @person.toggle_deleted
328
+ end
329
+
330
+ it "shouldn't update the core index's deleted flag if the record isn't in it" do
331
+ Person.stub!(:search_for_id => false)
332
+ @client.should_not_receive(:update).with(
333
+ "person_core", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
334
+ )
335
+
336
+ @person.toggle_deleted
337
+ end
338
+
339
+ it "shouldn't attempt to update the deleted flag if sphinx isn't running" do
340
+ ThinkingSphinx.stub!(:sphinx_running? => false)
341
+ @client.should_not_receive(:update)
342
+ Person.should_not_receive(:search_for_id)
343
+
344
+ @person.toggle_deleted
345
+ end
346
+
347
+ it "should update the delta index's deleted flag if delta indexes are enabled and the instance's delta is true" do
348
+ ThinkingSphinx.deltas_enabled = true
349
+ Person.sphinx_indexes.each { |index| index.stub!(:delta? => true) }
350
+ @person.delta = true
351
+ @client.should_receive(:update).with(
352
+ "person_delta", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
353
+ )
354
+
355
+ @person.toggle_deleted
356
+ end
357
+
358
+ it "should not update the delta index's deleted flag if delta indexes are enabled and the instance's delta is false" do
359
+ ThinkingSphinx.deltas_enabled = true
360
+ Person.sphinx_indexes.each { |index| index.stub!(:delta? => true) }
361
+ @person.delta = false
362
+ @client.should_not_receive(:update).with(
363
+ "person_delta", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
364
+ )
365
+
366
+ @person.toggle_deleted
367
+ end
368
+
369
+ 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
370
+ ThinkingSphinx.deltas_enabled = true
371
+ Person.sphinx_indexes.each { |index| index.stub!(:delta? => true) }
372
+ @person.delta = 0
373
+ @client.should_not_receive(:update).with(
374
+ "person_delta", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
375
+ )
376
+
377
+ @person.toggle_deleted
378
+ end
379
+
380
+ it "shouldn't update the delta index if delta indexes are disabled" do
381
+ ThinkingSphinx.deltas_enabled = true
382
+ @client.should_not_receive(:update).with(
383
+ "person_delta", ["sphinx_deleted"], {@person.sphinx_document_id => [1]}
384
+ )
385
+
386
+ @person.toggle_deleted
387
+ end
388
+
389
+ it "should not update either index if updates are disabled" do
390
+ ThinkingSphinx.updates_enabled = false
391
+ ThinkingSphinx.deltas_enabled = true
392
+ Person.sphinx_indexes.each { |index| index.stub!(:delta? => true) }
393
+ @person.delta = true
394
+ @client.should_not_receive(:update)
395
+
396
+ @person.toggle_deleted
397
+ end
398
+ end
399
+
400
+ describe "sphinx_indexes in the inheritance chain (STI)" do
401
+ it "should hand defined indexes on a class down to its child classes" do
402
+ Child.sphinx_indexes.should include(*Person.sphinx_indexes)
403
+ end
404
+
405
+ it "should allow associations to other STI models" do
406
+ source = Child.sphinx_indexes.last.sources.first
407
+ sql = source.to_riddle_for_core(0, 0).sql_query
408
+ sql.gsub!('$start', '0').gsub!('$end', '100')
409
+ lambda {
410
+ Child.connection.execute(sql)
411
+ }.should_not raise_error(ActiveRecord::StatementInvalid)
412
+ end
413
+ end
414
+
415
+ describe '#sphinx_document_id' do
416
+ before :each do
417
+ Alpha.define_index { indexes :name }
418
+ Beta.define_index { indexes :name }
419
+ end
420
+
421
+ it "should return values with the expected offset" do
422
+ person = Person.find(:first)
423
+ model_count = ThinkingSphinx.context.indexed_models.length
424
+ Person.stub!(:sphinx_offset => 3)
425
+
426
+ (person.id * model_count + 3).should == person.sphinx_document_id
427
+ end
428
+ end
429
+
430
+ describe '#primary_key_for_sphinx' do
431
+ before :each do
432
+ @person = Person.find(:first)
433
+ end
434
+
435
+ after :each do
436
+ Person.set_sphinx_primary_key nil
437
+ end
438
+
439
+ it "should return the id by default" do
440
+ @person.primary_key_for_sphinx.should == @person.id
441
+ end
442
+
443
+ it "should use the sphinx primary key to determine the value" do
444
+ Person.set_sphinx_primary_key :first_name
445
+ @person.primary_key_for_sphinx.should == @person.first_name
446
+ end
447
+
448
+ it "should not use accessor methods but the attributes hash" do
449
+ id = @person.id
450
+ @person.stub!(:id => 'unique_hash')
451
+ @person.primary_key_for_sphinx.should == id
452
+ end
453
+ end
454
+
455
+ describe '.sphinx_index_names' do
456
+ it "should return the core index" do
457
+ Alpha.define_index { indexes :name }
458
+ Alpha.define_indexes
459
+ Alpha.sphinx_index_names.should == ['alpha_core']
460
+ end
461
+
462
+ it "should return the delta index if enabled" do
463
+ Beta.define_index {
464
+ indexes :name
465
+ set_property :delta => true
466
+ }
467
+ Beta.define_indexes
468
+
469
+ Beta.sphinx_index_names.should == ['beta_core', 'beta_delta']
470
+ end
471
+
472
+ it "should return the superclass with an index definition" do
473
+ Parent.sphinx_index_names.should == ['person_core', 'person_delta']
474
+ end
475
+ end
476
+
477
+ describe '.indexed_by_sphinx?' do
478
+ it "should return true if there is at least one index on the model" do
479
+ Alpha.define_index { indexes :name }
480
+ Alpha.define_indexes
481
+
482
+ Alpha.should be_indexed_by_sphinx
483
+ end
484
+
485
+ it "should return false if there are no indexes on the model" do
486
+ Gamma.should_not be_indexed_by_sphinx
487
+ end
488
+ end
489
+
490
+ describe '.delta_indexed_by_sphinx?' do
491
+ it "should return true if there is at least one delta index on the model" do
492
+ Beta.define_index {
493
+ indexes :name
494
+ set_property :delta => true
495
+ }
496
+ Beta.define_indexes
497
+
498
+ Beta.should be_delta_indexed_by_sphinx
499
+ end
500
+
501
+ it "should return false if there are no delta indexes on the model" do
502
+ Alpha.define_index { indexes :name }
503
+ Alpha.define_indexes
504
+
505
+ Alpha.should_not be_delta_indexed_by_sphinx
506
+ end
507
+ end
508
+
509
+ describe '.delete_in_index' do
510
+ before :each do
511
+ @client = stub('client')
512
+ ThinkingSphinx.stub!(:sphinx_running? => true)
513
+ ThinkingSphinx::Configuration.instance.stub!(:client => @client)
514
+ Alpha.stub!(:search_for_id => true)
515
+ end
516
+
517
+ it "should not update if the document isn't in the given index" do
518
+ Alpha.stub!(:search_for_id => false)
519
+ @client.should_not_receive(:update)
520
+
521
+ Alpha.delete_in_index('alpha_core', 42)
522
+ end
523
+
524
+ it "should direct the update to the supplied index" do
525
+ @client.should_receive(:update) do |index, attributes, values|
526
+ index.should == 'custom_index_core'
527
+ end
528
+
529
+ Alpha.delete_in_index('custom_index_core', 42)
530
+ end
531
+
532
+ it "should set the sphinx_deleted flag to true" do
533
+ @client.should_receive(:update) do |index, attributes, values|
534
+ attributes.should == ['sphinx_deleted']
535
+ values.should == {42 => [1]}
536
+ end
537
+
538
+ Alpha.delete_in_index('alpha_core', 42)
539
+ end
540
+ end
541
+
542
+ describe '.core_index_names' do
543
+ it "should return each index's core name" do
544
+ Alpha.define_index { indexes :name }
545
+ Alpha.define_index { indexes :name }
546
+ Alpha.define_indexes
547
+ Alpha.sphinx_indexes.first.name = 'foo'
548
+ Alpha.sphinx_indexes.last.name = 'bar'
549
+
550
+ Alpha.core_index_names.should == ['foo_core', 'bar_core']
551
+ end
552
+ end
553
+
554
+ describe '.delta_index_names' do
555
+ it "should return index delta names, for indexes with deltas enabled" do
556
+ Alpha.define_index { indexes :name }
557
+ Alpha.define_index { indexes :name }
558
+ Alpha.define_indexes
559
+ Alpha.sphinx_indexes.first.name = 'foo'
560
+ Alpha.sphinx_indexes.first.delta_object = stub('delta')
561
+ Alpha.sphinx_indexes.last.name = 'bar'
562
+
563
+ Alpha.delta_index_names.should == ['foo_delta']
564
+ end
565
+ end
566
+
567
+ describe '.sphinx_offset' do
568
+ before :each do
569
+ @context = ThinkingSphinx.context
570
+ end
571
+
572
+ it "should return the index of the model's name in all known indexed models" do
573
+ @context.stub!(:indexed_models => ['Alpha', 'Beta'])
574
+
575
+ Alpha.sphinx_offset.should == 0
576
+ Beta.sphinx_offset.should == 1
577
+ end
578
+
579
+ it "should ignore classes that have indexed superclasses" do
580
+ @context.stub!(:indexed_models => ['Alpha', 'Parent', 'Person'])
581
+
582
+ Person.sphinx_offset.should == 1
583
+ end
584
+
585
+ it "should respect first known indexed parents" do
586
+ @context.stub!(:indexed_models => ['Alpha', 'Parent', 'Person'])
587
+
588
+ Parent.sphinx_offset.should == 1
589
+ end
590
+ end
591
+
592
+ describe '.has_sphinx_indexes?' do
593
+ it "should return true if there are sphinx indexes defined" do
594
+ Alpha.sphinx_indexes.replace [stub('index')]
595
+ Alpha.sphinx_index_blocks.replace []
596
+
597
+ Alpha.should have_sphinx_indexes
598
+ end
599
+
600
+ it "should return true if there are sphinx index blocks defined" do
601
+ Alpha.sphinx_indexes.replace []
602
+ Alpha.sphinx_index_blocks.replace [stub('lambda')]
603
+
604
+ Alpha.should have_sphinx_indexes
605
+ end
606
+
607
+ it "should return false if there are no sphinx indexes or blocks" do
608
+ Alpha.sphinx_indexes.clear
609
+ Alpha.sphinx_index_blocks.clear
610
+
611
+ Alpha.should_not have_sphinx_indexes
612
+ end
613
+ end
614
+
615
+ describe '.reset_subclasses' do
616
+ it "should reset the stored context" do
617
+ ThinkingSphinx.should_receive(:reset_context!)
618
+
619
+ ActiveRecord::Base.reset_subclasses
620
+ end
621
+ end
622
+ end