thinking-sphinx 1.2.13 → 1.4.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 (204) hide show
  1. data/README.textile +37 -4
  2. data/VERSION +1 -0
  3. data/features/abstract_inheritance.feature +10 -0
  4. data/features/alternate_primary_key.feature +1 -1
  5. data/features/attribute_updates.feature +49 -5
  6. data/features/deleting_instances.feature +3 -0
  7. data/features/excerpts.feature +8 -0
  8. data/features/facets.feature +15 -1
  9. data/features/facets_across_model.feature +2 -2
  10. data/features/field_sorting.feature +18 -0
  11. data/features/handling_edits.feature +1 -1
  12. data/features/searching_across_models.feature +2 -2
  13. data/features/searching_by_index.feature +40 -0
  14. data/features/searching_by_model.feature +1 -8
  15. data/features/sphinx_scopes.feature +33 -0
  16. data/features/step_definitions/alpha_steps.rb +14 -1
  17. data/features/step_definitions/beta_steps.rb +1 -1
  18. data/features/step_definitions/common_steps.rb +21 -2
  19. data/features/step_definitions/facet_steps.rb +4 -0
  20. data/features/step_definitions/scope_steps.rb +8 -0
  21. data/features/step_definitions/search_steps.rb +5 -0
  22. data/features/step_definitions/sphinx_steps.rb +8 -4
  23. data/features/sti_searching.feature +5 -0
  24. data/features/support/env.rb +7 -6
  25. data/features/{support → thinking_sphinx}/db/fixtures/betas.rb +1 -0
  26. data/features/{support → thinking_sphinx}/db/fixtures/comments.rb +1 -1
  27. data/features/{support → thinking_sphinx}/db/fixtures/developers.rb +2 -0
  28. data/features/thinking_sphinx/db/fixtures/foxes.rb +3 -0
  29. data/features/thinking_sphinx/db/fixtures/music.rb +4 -0
  30. data/features/{support → thinking_sphinx}/db/fixtures/people.rb +1 -1
  31. data/features/{support → thinking_sphinx}/db/fixtures/tags.rb +1 -1
  32. data/features/{support → thinking_sphinx}/db/migrations/create_alphas.rb +1 -0
  33. data/features/{support → thinking_sphinx}/db/migrations/create_developers.rb +0 -2
  34. data/features/thinking_sphinx/db/migrations/create_genres.rb +3 -0
  35. data/features/thinking_sphinx/db/migrations/create_music.rb +6 -0
  36. data/features/thinking_sphinx/models/alpha.rb +23 -0
  37. data/features/thinking_sphinx/models/andrew.rb +17 -0
  38. data/features/{support → thinking_sphinx}/models/beta.rb +1 -1
  39. data/features/{support → thinking_sphinx}/models/developer.rb +2 -2
  40. data/features/{support → thinking_sphinx}/models/extensible_beta.rb +1 -1
  41. data/features/thinking_sphinx/models/fox.rb +5 -0
  42. data/features/thinking_sphinx/models/genre.rb +3 -0
  43. data/features/thinking_sphinx/models/medium.rb +5 -0
  44. data/features/thinking_sphinx/models/music.rb +8 -0
  45. data/features/{support → thinking_sphinx}/models/person.rb +2 -1
  46. data/features/{support → thinking_sphinx}/models/post.rb +2 -1
  47. data/lib/cucumber/thinking_sphinx/external_world.rb +12 -0
  48. data/lib/cucumber/thinking_sphinx/internal_world.rb +13 -11
  49. data/lib/thinking_sphinx/active_record/attribute_updates.rb +17 -15
  50. data/lib/thinking_sphinx/active_record/delta.rb +0 -26
  51. data/lib/thinking_sphinx/active_record/has_many_association.rb +34 -11
  52. data/lib/thinking_sphinx/active_record/scopes.rb +46 -3
  53. data/lib/thinking_sphinx/active_record.rb +271 -193
  54. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +45 -9
  55. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +5 -1
  56. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +9 -1
  57. data/lib/thinking_sphinx/attribute.rb +67 -23
  58. data/lib/thinking_sphinx/auto_version.rb +24 -0
  59. data/lib/thinking_sphinx/bundled_search.rb +44 -0
  60. data/lib/thinking_sphinx/class_facet.rb +3 -2
  61. data/lib/thinking_sphinx/configuration.rb +78 -64
  62. data/lib/thinking_sphinx/context.rb +76 -0
  63. data/lib/thinking_sphinx/deltas/default_delta.rb +14 -20
  64. data/lib/thinking_sphinx/deltas.rb +0 -2
  65. data/lib/thinking_sphinx/deploy/capistrano.rb +1 -1
  66. data/lib/thinking_sphinx/excerpter.rb +1 -1
  67. data/lib/thinking_sphinx/facet.rb +6 -5
  68. data/lib/thinking_sphinx/facet_search.rb +54 -24
  69. data/lib/thinking_sphinx/field.rb +2 -4
  70. data/lib/thinking_sphinx/index/builder.rb +36 -20
  71. data/lib/thinking_sphinx/index/faux_column.rb +8 -0
  72. data/lib/thinking_sphinx/index.rb +77 -19
  73. data/lib/thinking_sphinx/join.rb +37 -0
  74. data/lib/thinking_sphinx/property.rb +9 -2
  75. data/lib/thinking_sphinx/rails_additions.rb +4 -4
  76. data/lib/thinking_sphinx/search.rb +212 -66
  77. data/lib/thinking_sphinx/search_methods.rb +22 -4
  78. data/lib/thinking_sphinx/source/internal_properties.rb +2 -2
  79. data/lib/thinking_sphinx/source/sql.rb +5 -3
  80. data/lib/thinking_sphinx/source.rb +21 -12
  81. data/lib/thinking_sphinx/tasks.rb +26 -58
  82. data/lib/thinking_sphinx/test.rb +55 -0
  83. data/lib/thinking_sphinx.rb +70 -38
  84. data/rails/init.rb +4 -2
  85. data/spec/{lib/thinking_sphinx → thinking_sphinx}/active_record/delta_spec.rb +6 -8
  86. data/spec/{lib/thinking_sphinx → thinking_sphinx}/active_record/has_many_association_spec.rb +26 -3
  87. data/spec/thinking_sphinx/active_record/scopes_spec.rb +176 -0
  88. data/spec/thinking_sphinx/active_record_spec.rb +618 -0
  89. data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +134 -0
  90. data/spec/{lib/thinking_sphinx → thinking_sphinx}/association_spec.rb +1 -1
  91. data/spec/{lib/thinking_sphinx → thinking_sphinx}/attribute_spec.rb +87 -46
  92. data/spec/thinking_sphinx/auto_version_spec.rb +47 -0
  93. data/spec/{lib/thinking_sphinx → thinking_sphinx}/configuration_spec.rb +73 -63
  94. data/spec/thinking_sphinx/context_spec.rb +127 -0
  95. data/spec/{lib/thinking_sphinx → thinking_sphinx}/core/array_spec.rb +1 -1
  96. data/spec/{lib/thinking_sphinx → thinking_sphinx}/core/string_spec.rb +1 -1
  97. data/spec/{lib/thinking_sphinx → thinking_sphinx}/excerpter_spec.rb +1 -9
  98. data/spec/{lib/thinking_sphinx → thinking_sphinx}/facet_search_spec.rb +76 -82
  99. data/spec/{lib/thinking_sphinx → thinking_sphinx}/facet_spec.rb +5 -5
  100. data/spec/{lib/thinking_sphinx → thinking_sphinx}/field_spec.rb +1 -42
  101. data/spec/{lib/thinking_sphinx → thinking_sphinx}/index/builder_spec.rb +71 -31
  102. data/spec/{lib/thinking_sphinx → thinking_sphinx}/index/faux_column_spec.rb +8 -2
  103. data/spec/thinking_sphinx/index_spec.rb +183 -0
  104. data/spec/{lib/thinking_sphinx → thinking_sphinx}/rails_additions_spec.rb +5 -5
  105. data/spec/{lib/thinking_sphinx → thinking_sphinx}/search_methods_spec.rb +5 -1
  106. data/spec/{lib/thinking_sphinx → thinking_sphinx}/search_spec.rb +183 -31
  107. data/spec/{lib/thinking_sphinx → thinking_sphinx}/source_spec.rb +18 -2
  108. data/spec/thinking_sphinx/test_spec.rb +20 -0
  109. data/spec/thinking_sphinx_spec.rb +204 -0
  110. data/tasks/distribution.rb +7 -26
  111. data/tasks/testing.rb +32 -20
  112. metadata +488 -147
  113. data/VERSION.yml +0 -5
  114. data/features/datetime_deltas.feature +0 -66
  115. data/features/delayed_delta_indexing.feature +0 -37
  116. data/features/step_definitions/datetime_delta_steps.rb +0 -15
  117. data/features/step_definitions/delayed_delta_indexing_steps.rb +0 -7
  118. data/features/support/database.yml +0 -5
  119. data/features/support/db/active_record.rb +0 -40
  120. data/features/support/db/database.yml +0 -5
  121. data/features/support/db/fixtures/delayed_betas.rb +0 -10
  122. data/features/support/db/fixtures/thetas.rb +0 -10
  123. data/features/support/db/migrations/create_delayed_betas.rb +0 -17
  124. data/features/support/db/migrations/create_thetas.rb +0 -5
  125. data/features/support/db/mysql.rb +0 -3
  126. data/features/support/db/postgresql.rb +0 -3
  127. data/features/support/models/alpha.rb +0 -10
  128. data/features/support/models/delayed_beta.rb +0 -7
  129. data/features/support/models/theta.rb +0 -7
  130. data/features/support/post_database.rb +0 -43
  131. data/lib/thinking_sphinx/deltas/datetime_delta.rb +0 -50
  132. data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +0 -24
  133. data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +0 -27
  134. data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +0 -26
  135. data/lib/thinking_sphinx/deltas/delayed_delta.rb +0 -30
  136. data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +0 -96
  137. data/spec/lib/thinking_sphinx/active_record_spec.rb +0 -353
  138. data/spec/lib/thinking_sphinx/deltas/job_spec.rb +0 -32
  139. data/spec/lib/thinking_sphinx/index_spec.rb +0 -45
  140. data/spec/lib/thinking_sphinx_spec.rb +0 -162
  141. data/vendor/after_commit/LICENSE +0 -20
  142. data/vendor/after_commit/README +0 -16
  143. data/vendor/after_commit/Rakefile +0 -22
  144. data/vendor/after_commit/init.rb +0 -8
  145. data/vendor/after_commit/lib/after_commit/active_record.rb +0 -114
  146. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +0 -103
  147. data/vendor/after_commit/lib/after_commit.rb +0 -45
  148. data/vendor/after_commit/test/after_commit_test.rb +0 -53
  149. data/vendor/delayed_job/lib/delayed/job.rb +0 -251
  150. data/vendor/delayed_job/lib/delayed/message_sending.rb +0 -7
  151. data/vendor/delayed_job/lib/delayed/performable_method.rb +0 -55
  152. data/vendor/delayed_job/lib/delayed/worker.rb +0 -54
  153. data/vendor/riddle/lib/riddle/client/filter.rb +0 -53
  154. data/vendor/riddle/lib/riddle/client/message.rb +0 -66
  155. data/vendor/riddle/lib/riddle/client/response.rb +0 -84
  156. data/vendor/riddle/lib/riddle/client.rb +0 -635
  157. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +0 -48
  158. data/vendor/riddle/lib/riddle/configuration/index.rb +0 -142
  159. data/vendor/riddle/lib/riddle/configuration/indexer.rb +0 -19
  160. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +0 -17
  161. data/vendor/riddle/lib/riddle/configuration/searchd.rb +0 -25
  162. data/vendor/riddle/lib/riddle/configuration/section.rb +0 -43
  163. data/vendor/riddle/lib/riddle/configuration/source.rb +0 -23
  164. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +0 -34
  165. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +0 -28
  166. data/vendor/riddle/lib/riddle/configuration.rb +0 -33
  167. data/vendor/riddle/lib/riddle/controller.rb +0 -53
  168. data/vendor/riddle/lib/riddle.rb +0 -30
  169. data/features/{support → thinking_sphinx}/database.example.yml +0 -0
  170. data/features/{support → thinking_sphinx}/db/fixtures/alphas.rb +0 -0
  171. data/features/{support → thinking_sphinx}/db/fixtures/authors.rb +0 -0
  172. data/features/{support → thinking_sphinx}/db/fixtures/boxes.rb +0 -0
  173. data/features/{support → thinking_sphinx}/db/fixtures/categories.rb +0 -0
  174. data/features/{support → thinking_sphinx}/db/fixtures/cats.rb +0 -0
  175. data/features/{support → thinking_sphinx}/db/fixtures/dogs.rb +0 -0
  176. data/features/{support → thinking_sphinx}/db/fixtures/extensible_betas.rb +0 -0
  177. data/features/{support → thinking_sphinx}/db/fixtures/gammas.rb +0 -0
  178. data/features/{support → thinking_sphinx}/db/fixtures/posts.rb +0 -0
  179. data/features/{support → thinking_sphinx}/db/fixtures/robots.rb +0 -0
  180. data/features/{support → thinking_sphinx}/db/migrations/create_animals.rb +0 -0
  181. data/features/{support → thinking_sphinx}/db/migrations/create_authors.rb +0 -0
  182. data/features/{support → thinking_sphinx}/db/migrations/create_authors_posts.rb +0 -0
  183. data/features/{support → thinking_sphinx}/db/migrations/create_betas.rb +0 -0
  184. data/features/{support → thinking_sphinx}/db/migrations/create_boxes.rb +0 -0
  185. data/features/{support → thinking_sphinx}/db/migrations/create_categories.rb +0 -0
  186. data/features/{support → thinking_sphinx}/db/migrations/create_comments.rb +0 -0
  187. data/features/{support → thinking_sphinx}/db/migrations/create_extensible_betas.rb +0 -0
  188. data/features/{support → thinking_sphinx}/db/migrations/create_gammas.rb +0 -0
  189. data/features/{support → thinking_sphinx}/db/migrations/create_people.rb +0 -0
  190. data/features/{support → thinking_sphinx}/db/migrations/create_posts.rb +0 -0
  191. data/features/{support → thinking_sphinx}/db/migrations/create_robots.rb +0 -0
  192. data/features/{support → thinking_sphinx}/db/migrations/create_taggings.rb +0 -0
  193. data/features/{support → thinking_sphinx}/db/migrations/create_tags.rb +0 -0
  194. data/features/{support → thinking_sphinx}/models/animal.rb +0 -0
  195. data/features/{support → thinking_sphinx}/models/author.rb +0 -0
  196. data/features/{support → thinking_sphinx}/models/box.rb +0 -0
  197. data/features/{support → thinking_sphinx}/models/cat.rb +0 -0
  198. data/features/{support → thinking_sphinx}/models/category.rb +0 -0
  199. data/features/{support → thinking_sphinx}/models/comment.rb +3 -3
  200. /data/features/{support → thinking_sphinx}/models/dog.rb +0 -0
  201. /data/features/{support → thinking_sphinx}/models/gamma.rb +0 -0
  202. /data/features/{support → thinking_sphinx}/models/robot.rb +0 -0
  203. /data/features/{support → thinking_sphinx}/models/tag.rb +0 -0
  204. /data/features/{support → thinking_sphinx}/models/tagging.rb +0 -0
@@ -93,25 +93,25 @@ module ThinkingSphinx
93
93
 
94
94
  separator = all_ints? || all_datetimes? || @crc ? ',' : ' '
95
95
 
96
- clause = @columns.collect { |column|
97
- part = column_with_prefix(column)
96
+ clause = columns_with_prefixes.collect { |column|
98
97
  case type
99
98
  when :string
100
- adapter.convert_nulls(part)
99
+ adapter.convert_nulls(column)
101
100
  when :datetime
102
- adapter.cast_to_datetime(part)
101
+ adapter.cast_to_datetime(column)
103
102
  when :multi
104
- part = adapter.cast_to_datetime(part) if is_many_datetimes?
105
- part = adapter.convert_nulls(part, '0') if is_many_ints?
106
- part
103
+ column = adapter.cast_to_datetime(column) if is_many_datetimes?
104
+ column = adapter.convert_nulls(column, '0') if is_many_ints?
105
+ column
107
106
  else
108
- part
107
+ column
109
108
  end
110
109
  }.join(', ')
111
110
 
112
111
  clause = adapter.crc(clause) if @crc
113
112
  clause = adapter.concatenate(clause, separator) if concat_ws?
114
113
  clause = adapter.group_concatenate(clause, separator) if is_many?
114
+ clause = adapter.downcase(clause) if insensitive?
115
115
 
116
116
  "#{clause} AS #{quote_column(unique_name)}"
117
117
  end
@@ -123,7 +123,8 @@ module ThinkingSphinx
123
123
  :string => :sql_attr_str2ordinal,
124
124
  :float => :sql_attr_float,
125
125
  :boolean => :sql_attr_bool,
126
- :integer => :sql_attr_uint
126
+ :integer => :sql_attr_uint,
127
+ :bigint => :sql_attr_bigint
127
128
  }[type]
128
129
  end
129
130
 
@@ -179,8 +180,12 @@ module ThinkingSphinx
179
180
  def live_value(instance)
180
181
  object = instance
181
182
  column = @columns.first
182
- column.__stack.each { |method| object = object.send(method) }
183
- object.send(column.__name)
183
+ column.__stack.each { |method|
184
+ object = object.send(method)
185
+ return sphinx_value(nil) if object.nil?
186
+ }
187
+
188
+ sphinx_value object.send(column.__name)
184
189
  end
185
190
 
186
191
  def all_ints?
@@ -297,19 +302,11 @@ WHERE #{@source.index.delta_object.clause(model, true)})
297
302
  is_many? && all_strings?
298
303
  end
299
304
 
300
- def type_from_database
301
- klass = @associations.values.flatten.first ?
302
- @associations.values.flatten.first.reflection.klass : @model
303
-
304
- column = klass.columns.detect { |col|
305
- @columns.collect { |c| c.__name.to_s }.include? col.name
306
- }
307
- column.nil? ? nil : column.type
308
- end
309
-
310
305
  def translated_type_from_database
311
306
  case type_from_db = type_from_database
312
- when :datetime, :string, :float, :boolean, :integer
307
+ when :integer
308
+ integer_type_from_db
309
+ when :datetime, :string, :float, :boolean
313
310
  type_from_db
314
311
  when :decimal
315
312
  :float
@@ -327,6 +324,32 @@ block:
327
324
  end
328
325
  end
329
326
 
327
+ def type_from_database
328
+ column = column_from_db
329
+ column.nil? ? nil : column.type
330
+ end
331
+
332
+ def integer_type_from_db
333
+ column = column_from_db
334
+ return nil if column.nil?
335
+
336
+ case column.sql_type
337
+ when adapter.bigint_pattern
338
+ :bigint
339
+ else
340
+ :integer
341
+ end
342
+ end
343
+
344
+ def column_from_db
345
+ klass = @associations.values.flatten.first ?
346
+ @associations.values.flatten.first.reflection.klass : @model
347
+
348
+ klass.columns.detect { |col|
349
+ @columns.collect { |c| c.__name.to_s }.include? col.name
350
+ }
351
+ end
352
+
330
353
  def all_of_type?(*column_types)
331
354
  @columns.all? { |col|
332
355
  klasses = @associations[col].empty? ? [@model] :
@@ -337,5 +360,26 @@ block:
337
360
  }
338
361
  }
339
362
  end
363
+
364
+ def sphinx_value(value)
365
+ case value
366
+ when TrueClass
367
+ 1
368
+ when FalseClass, NilClass
369
+ 0
370
+ when Time
371
+ value.to_i
372
+ when Date
373
+ value.to_time.to_i
374
+ when String
375
+ value.to_crc32
376
+ else
377
+ value
378
+ end
379
+ end
380
+
381
+ def insensitive?
382
+ @sortable == :insensitive
383
+ end
340
384
  end
341
- end
385
+ end
@@ -0,0 +1,24 @@
1
+ module ThinkingSphinx
2
+ class AutoVersion
3
+ def self.detect
4
+ version = ThinkingSphinx::Configuration.instance.version
5
+ case version
6
+ when '0.9.8', '0.9.9'
7
+ require "riddle/#{version}"
8
+ when '1.10-beta'
9
+ require 'riddle/1.10'
10
+ else
11
+ STDERR.puts %Q{
12
+ Sphinx cannot be found on your system. You may need to configure the following
13
+ settings in your config/sphinx.yml file:
14
+ * bin_path
15
+ * searchd_binary_name
16
+ * indexer_binary_name
17
+
18
+ For more information, read the documentation:
19
+ http://freelancing-god.github.com/ts/en/advanced_config.html
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,44 @@
1
+ module ThinkingSphinx
2
+ class BundledSearch
3
+ attr_reader :client
4
+
5
+ def initialize
6
+ @searches = []
7
+ end
8
+
9
+ def search(*args)
10
+ @searches << ThinkingSphinx.search(*args)
11
+ @searches.last.append_to client
12
+ end
13
+
14
+ def search_for_ids(*args)
15
+ @searches << ThinkingSphinx.search_for_ids(*args)
16
+ @searches.last.append_to client
17
+ end
18
+
19
+ def searches
20
+ populate
21
+ @searches
22
+ end
23
+
24
+ private
25
+
26
+ def client
27
+ @client ||= ThinkingSphinx::Configuration.instance.client
28
+ end
29
+
30
+ def populated?
31
+ @populated
32
+ end
33
+
34
+ def populate
35
+ return if populated?
36
+
37
+ @populated = true
38
+
39
+ client.run.each_with_index do |results, index|
40
+ searches[index].populate_from_queue results
41
+ end
42
+ end
43
+ end
44
+ end
@@ -8,8 +8,9 @@ module ThinkingSphinx
8
8
  "class_crc"
9
9
  end
10
10
 
11
- def value(object, attribute_value)
12
- object.class.name
11
+ def value(object, attribute_hash)
12
+ crc = attribute_hash['class_crc']
13
+ ThinkingSphinx::Configuration.instance.models_by_crc[crc]
13
14
  end
14
15
  end
15
16
  end
@@ -13,7 +13,7 @@ module ThinkingSphinx
13
13
  # pid file:: log/searchd.#{environment}.pid
14
14
  # searchd files:: db/sphinx/#{environment}/
15
15
  # address:: 127.0.0.1
16
- # port:: 3312
16
+ # port:: 9312
17
17
  # allow star:: false
18
18
  # min prefix length:: 1
19
19
  # min infix length:: 1
@@ -49,25 +49,29 @@ module ThinkingSphinx
49
49
  class Configuration
50
50
  include Singleton
51
51
 
52
- SourceOptions = %w( mysql_connect_flags sql_range_step sql_query_pre
53
- sql_query_post sql_ranged_throttle sql_query_post_index )
52
+ SourceOptions = %w( mysql_connect_flags mysql_ssl_cert mysql_ssl_key
53
+ mysql_ssl_ca sql_range_step sql_query_pre sql_query_post
54
+ sql_query_killlist sql_ranged_throttle sql_query_post_index unpack_zlib
55
+ unpack_mysqlcompress unpack_mysqlcompress_maxsize )
54
56
 
55
- IndexOptions = %w( charset_table charset_type docinfo enable_star
56
- exceptions html_index_attrs html_remove_elements html_strip ignore_chars
57
- min_infix_len min_prefix_len min_word_len mlock morphology ngram_chars
58
- ngram_len phrase_boundary phrase_boundary_step preopen stopwords
59
- wordforms )
57
+ IndexOptions = %w( blend_chars charset_table charset_type charset_dictpath
58
+ docinfo enable_star exceptions expand_keywords hitless_words
59
+ html_index_attrs html_remove_elements html_strip index_exact_words
60
+ ignore_chars inplace_docinfo_gap inplace_enable inplace_hit_gap
61
+ inplace_reloc_factor inplace_write_factor min_infix_len min_prefix_len
62
+ min_stemming_len min_word_len mlock morphology ngram_chars ngram_len
63
+ ondisk_dict overshort_step phrase_boundary phrase_boundary_step preopen
64
+ stopwords stopwords_step wordforms )
60
65
 
61
66
  CustomOptions = %w( disable_range )
62
67
 
63
- attr_accessor :config_file, :searchd_log_file, :query_log_file,
64
- :pid_file, :searchd_file_path, :address, :port, :allow_star,
65
- :database_yml_file, :app_root, :bin_path, :model_directories,
66
- :delayed_job_priority, :searchd_binary_name, :indexer_binary_name
68
+ attr_accessor :searchd_file_path, :allow_star, :database_yml_file,
69
+ :app_root, :model_directories, :delayed_job_priority, :indexed_models
67
70
 
68
71
  attr_accessor :source_options, :index_options
72
+ attr_accessor :version
69
73
 
70
- attr_reader :environment, :configuration
74
+ attr_reader :environment, :configuration, :controller
71
75
 
72
76
  # Load in the configuration settings - this will look for config/sphinx.yml
73
77
  # and parse it according to the current environment.
@@ -91,60 +95,64 @@ module ThinkingSphinx
91
95
  end
92
96
 
93
97
  @configuration = Riddle::Configuration.new
94
- @configuration.searchd.address = "127.0.0.1"
95
- @configuration.searchd.port = 3312
96
98
  @configuration.searchd.pid_file = "#{self.app_root}/log/searchd.#{environment}.pid"
97
99
  @configuration.searchd.log = "#{self.app_root}/log/searchd.log"
98
100
  @configuration.searchd.query_log = "#{self.app_root}/log/searchd.query.log"
99
101
 
102
+ @controller = Riddle::Controller.new @configuration,
103
+ "#{self.app_root}/config/#{environment}.sphinx.conf"
104
+
105
+ self.address = "127.0.0.1"
106
+ self.port = 9312
100
107
  self.database_yml_file = "#{self.app_root}/config/database.yml"
101
- self.config_file = "#{self.app_root}/config/#{environment}.sphinx.conf"
102
108
  self.searchd_file_path = "#{self.app_root}/db/sphinx/#{environment}"
103
109
  self.allow_star = false
104
- self.bin_path = ""
105
110
  self.model_directories = ["#{app_root}/app/models/"] +
106
111
  Dir.glob("#{app_root}/vendor/plugins/*/app/models/")
107
112
  self.delayed_job_priority = 0
113
+ self.indexed_models = []
108
114
 
109
115
  self.source_options = {}
110
116
  self.index_options = {
111
117
  :charset_type => "utf-8"
112
118
  }
113
119
 
114
- self.searchd_binary_name = "searchd"
115
- self.indexer_binary_name = "indexer"
116
-
120
+ self.version = nil
117
121
  parse_config
122
+ self.version ||= @controller.sphinx_version
118
123
 
119
124
  self
120
125
  end
121
126
 
122
127
  def self.environment
123
- @@environment ||= (
124
- defined?(Merb) ? Merb.environment : ENV['RAILS_ENV']
125
- ) || "development"
128
+ Thread.current[:thinking_sphinx_environment] ||= begin
129
+ if defined?(Merb)
130
+ Merb.environment
131
+ elsif defined?(RAILS_ENV)
132
+ RAILS_ENV
133
+ else
134
+ ENV['RAILS_ENV'] || 'development'
135
+ end
136
+ end
126
137
  end
127
138
 
128
139
  def environment
129
140
  self.class.environment
130
141
  end
131
142
 
132
- def controller
133
- @controller ||= Riddle::Controller.new(@configuration, self.config_file)
134
- end
135
-
136
143
  # Generate the config file for Sphinx by using all the settings defined and
137
144
  # looping through all the models with indexes to build the relevant
138
145
  # indexer and searchd configuration, and sources and indexes details.
139
146
  #
140
147
  def build(file_path=nil)
141
- load_models
142
148
  file_path ||= "#{self.config_file}"
143
149
 
144
150
  @configuration.indexes.clear
145
151
 
146
- ThinkingSphinx.indexed_models.each_with_index do |model, model_index|
147
- @configuration.indexes.concat model.constantize.to_riddle(model_index)
152
+ ThinkingSphinx.context.indexed_models.each do |model|
153
+ model = model.constantize
154
+ model.define_indexes
155
+ @configuration.indexes.concat model.to_riddle
148
156
  end
149
157
 
150
158
  open(file_path, "w") do |file|
@@ -152,50 +160,21 @@ module ThinkingSphinx
152
160
  end
153
161
  end
154
162
 
155
- # Make sure all models are loaded - without reloading any that
156
- # ActiveRecord::Base is already aware of (otherwise we start to hit some
157
- # messy dependencies issues).
158
- #
159
- def load_models
160
- return if defined?(Rails) &&
161
- Rails::VERSION::STRING.to_f > 2.1 &&
162
- Rails.configuration.cache_classes
163
-
164
- self.model_directories.each do |base|
165
- Dir["#{base}**/*.rb"].each do |file|
166
- model_name = file.gsub(/^#{base}([\w_\/\\]+)\.rb/, '\1')
167
-
168
- next if model_name.nil?
169
- next if ::ActiveRecord::Base.send(:subclasses).detect { |model|
170
- model.name == model_name
171
- }
172
-
173
- begin
174
- model_name.camelize.constantize
175
- rescue LoadError
176
- model_name.gsub!(/.*[\/\\]/, '').nil? ? next : retry
177
- rescue NameError
178
- next
179
- rescue StandardError
180
- puts "Warning: Error loading #{file}"
181
- end
182
- end
183
- end
184
- end
185
-
186
163
  def address
187
- @configuration.searchd.address
164
+ @address
188
165
  end
189
166
 
190
167
  def address=(address)
168
+ @address = address
191
169
  @configuration.searchd.address = address
192
170
  end
193
171
 
194
172
  def port
195
- @configuration.searchd.port
173
+ @port
196
174
  end
197
175
 
198
176
  def port=(port)
177
+ @port = port
199
178
  @configuration.searchd.port = port
200
179
  end
201
180
 
@@ -223,15 +202,50 @@ module ThinkingSphinx
223
202
  @configuration.searchd.query_log = file
224
203
  end
225
204
 
205
+ def config_file
206
+ @controller.path
207
+ end
208
+
209
+ def config_file=(file)
210
+ @controller.path = file
211
+ end
212
+
213
+ def bin_path
214
+ @controller.bin_path
215
+ end
216
+
217
+ def bin_path=(path)
218
+ @controller.bin_path = path
219
+ end
220
+
221
+ def searchd_binary_name
222
+ @controller.searchd_binary_name
223
+ end
224
+
225
+ def searchd_binary_name=(name)
226
+ @controller.searchd_binary_name = name
227
+ end
228
+
229
+ def indexer_binary_name
230
+ @controller.indexer_binary_name
231
+ end
232
+
233
+ def indexer_binary_name=(name)
234
+ @controller.indexer_binary_name = name
235
+ end
236
+
237
+ attr_accessor :timeout
238
+
226
239
  def client
227
240
  client = Riddle::Client.new address, port
228
241
  client.max_matches = configuration.searchd.max_matches || 1000
242
+ client.timeout = timeout || 0
229
243
  client
230
244
  end
231
245
 
232
246
  def models_by_crc
233
247
  @models_by_crc ||= begin
234
- ThinkingSphinx.indexed_models.inject({}) do |hash, model|
248
+ ThinkingSphinx.context.indexed_models.inject({}) do |hash, model|
235
249
  hash[model.constantize.to_crc32] = model
236
250
  Object.subclasses_of(model.constantize).each { |subclass|
237
251
  hash[subclass.to_crc32] = subclass.name
@@ -0,0 +1,76 @@
1
+ class ThinkingSphinx::Context
2
+ attr_reader :indexed_models
3
+
4
+ def initialize(*models)
5
+ @indexed_models = []
6
+ end
7
+
8
+ def prepare
9
+ ThinkingSphinx::Configuration.instance.indexed_models.each do |model|
10
+ add_indexed_model model
11
+ end
12
+
13
+ return unless indexed_models.empty?
14
+
15
+ load_models
16
+ add_indexed_models
17
+ end
18
+
19
+ def define_indexes
20
+ indexed_models.each { |model|
21
+ model.constantize.define_indexes
22
+ }
23
+ end
24
+
25
+ def add_indexed_model(model)
26
+ model = model.name if model.is_a?(Class)
27
+
28
+ indexed_models << model
29
+ indexed_models.uniq!
30
+ indexed_models.sort!
31
+ end
32
+
33
+ def superclass_indexed_models
34
+ klasses = indexed_models.collect { |name| name.constantize }
35
+ klasses.reject { |klass|
36
+ klass.superclass.ancestors.any? { |ancestor| klasses.include?(ancestor) }
37
+ }.collect { |klass| klass.name }
38
+ end
39
+
40
+ private
41
+
42
+ def add_indexed_models
43
+ Object.subclasses_of(ActiveRecord::Base).each do |klass|
44
+ add_indexed_model klass if klass.has_sphinx_indexes?
45
+ end
46
+ end
47
+
48
+ # Make sure all models are loaded - without reloading any that
49
+ # ActiveRecord::Base is already aware of (otherwise we start to hit some
50
+ # messy dependencies issues).
51
+ #
52
+ def load_models
53
+ ThinkingSphinx::Configuration.instance.model_directories.each do |base|
54
+ Dir["#{base}**/*.rb"].each do |file|
55
+ model_name = file.gsub(/^#{base}([\w_\/\\]+)\.rb/, '\1')
56
+
57
+ next if model_name.nil?
58
+ next if ::ActiveRecord::Base.send(:subclasses).detect { |model|
59
+ model.name == model_name.camelize
60
+ }
61
+
62
+ begin
63
+ model_name.camelize.constantize
64
+ rescue LoadError
65
+ model_name.gsub!(/.*[\/\\]/, '').nil? ? next : retry
66
+ rescue NameError
67
+ next
68
+ rescue StandardError => err
69
+ STDERR.puts "Warning: Error loading #{file}:"
70
+ STDERR.puts err.message
71
+ STDERR.puts err.backtrace.join("\n"), ''
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -13,18 +13,8 @@ module ThinkingSphinx
13
13
  ThinkingSphinx.deltas_enabled?
14
14
  return true if instance && !toggled(instance)
15
15
 
16
- config = ThinkingSphinx::Configuration.instance
17
- client = Riddle::Client.new config.address, config.port
18
- rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
19
-
20
- output = `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file} #{rotate} #{delta_index_name model}`
21
- puts(output) unless ThinkingSphinx.suppress_delta_output?
22
-
23
- client.update(
24
- core_index_name(model),
25
- ['sphinx_deleted'],
26
- {instance.sphinx_document_id => [1]}
27
- ) if instance && ThinkingSphinx.sphinx_running? && instance.in_both_indexes?
16
+ update_delta_indexes model
17
+ delete_from_core model, instance if instance
28
18
 
29
19
  true
30
20
  end
@@ -48,17 +38,21 @@ module ThinkingSphinx
48
38
  " = #{adapter.boolean(toggled)}"
49
39
  end
50
40
 
51
- protected
41
+ private
52
42
 
53
- def core_index_name(model)
54
- "#{model.source_of_sphinx_index.name.underscore.tr(':/\\', '_')}_core"
43
+ def update_delta_indexes(model)
44
+ config = ThinkingSphinx::Configuration.instance
45
+ rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
46
+
47
+ output = `#{config.bin_path}#{config.indexer_binary_name} --config "#{config.config_file}" #{rotate} #{model.delta_index_names.join(' ')}`
48
+ puts(output) unless ThinkingSphinx.suppress_delta_output?
55
49
  end
56
50
 
57
- def delta_index_name(model)
58
- "#{model.source_of_sphinx_index.name.underscore.tr(':/\\', '_')}_delta"
59
- end
60
-
61
- private
51
+ def delete_from_core(model, instance)
52
+ model.core_index_names.each do |index_name|
53
+ model.delete_in_index index_name, instance.sphinx_document_id
54
+ end
55
+ end
62
56
 
63
57
  def adapter
64
58
  @adapter = @index.model.sphinx_database_adapter
@@ -1,6 +1,4 @@
1
1
  require 'thinking_sphinx/deltas/default_delta'
2
- require 'thinking_sphinx/deltas/delayed_delta'
3
- require 'thinking_sphinx/deltas/datetime_delta'
4
2
 
5
3
  module ThinkingSphinx
6
4
  module Deltas
@@ -93,7 +93,7 @@ DESC
93
93
  rails_env = fetch(:rails_env, "production")
94
94
  rake = fetch(:rake, "rake")
95
95
  tasks.each do |t|
96
- run "cd #{current_path}; #{rake} RAILS_ENV=#{rails_env} #{t}"
96
+ run "if [ -d #{release_path} ]; then cd #{release_path}; else cd #{current_path}; fi; #{rake} RAILS_ENV=#{rails_env} #{t}"
97
97
  end
98
98
  end
99
99
  end
@@ -14,7 +14,7 @@ module ThinkingSphinx
14
14
  end
15
15
 
16
16
  def method_missing(method, *args, &block)
17
- string = CGI::escapeHTML @instance.send(method, *args, &block).to_s
17
+ string = @instance.send(method, *args, &block).to_s
18
18
 
19
19
  @search.excerpt_for(string, @instance.class)
20
20
  end
@@ -71,7 +71,12 @@ module ThinkingSphinx
71
71
  @property.is_a?(Field) ? :string : @property.type
72
72
  end
73
73
 
74
- def value(object, attribute_value)
74
+ def float?
75
+ @property.type == :float
76
+ end
77
+
78
+ def value(object, attribute_hash)
79
+ attribute_value = attribute_hash['@groupby']
75
80
  return translate(object, attribute_value) if translate? || float?
76
81
 
77
82
  case @property.type
@@ -117,9 +122,5 @@ module ThinkingSphinx
117
122
  def column
118
123
  @property.columns.first
119
124
  end
120
-
121
- def float?
122
- @property.type == :float
123
- end
124
125
  end
125
126
  end