thinking-sphinx 2.0.5 → 2.0.6

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 (70) hide show
  1. data/README.textile +7 -1
  2. data/features/searching_by_model.feature +24 -30
  3. data/features/step_definitions/common_steps.rb +5 -5
  4. data/features/thinking_sphinx/db/.gitignore +1 -0
  5. data/features/thinking_sphinx/db/fixtures/post_keywords.txt +1 -0
  6. data/spec/fixtures/data.sql +32 -0
  7. data/spec/fixtures/database.yml.default +3 -0
  8. data/spec/fixtures/models.rb +161 -0
  9. data/spec/fixtures/structure.sql +146 -0
  10. data/spec/spec_helper.rb +62 -0
  11. data/spec/sphinx_helper.rb +61 -0
  12. data/spec/support/rails.rb +18 -0
  13. data/spec/thinking_sphinx/active_record/delta_spec.rb +24 -24
  14. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +27 -0
  15. data/spec/thinking_sphinx/active_record/scopes_spec.rb +25 -25
  16. data/spec/thinking_sphinx/active_record_spec.rb +108 -107
  17. data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +38 -38
  18. data/spec/thinking_sphinx/association_spec.rb +69 -35
  19. data/spec/thinking_sphinx/context_spec.rb +61 -64
  20. data/spec/thinking_sphinx/search_spec.rb +7 -0
  21. data/spec/thinking_sphinx_spec.rb +47 -46
  22. metadata +49 -141
  23. data/VERSION +0 -1
  24. data/lib/cucumber/thinking_sphinx/external_world.rb +0 -12
  25. data/lib/cucumber/thinking_sphinx/internal_world.rb +0 -127
  26. data/lib/cucumber/thinking_sphinx/sql_logger.rb +0 -20
  27. data/lib/thinking-sphinx.rb +0 -1
  28. data/lib/thinking_sphinx.rb +0 -301
  29. data/lib/thinking_sphinx/action_controller.rb +0 -31
  30. data/lib/thinking_sphinx/active_record.rb +0 -384
  31. data/lib/thinking_sphinx/active_record/attribute_updates.rb +0 -52
  32. data/lib/thinking_sphinx/active_record/delta.rb +0 -65
  33. data/lib/thinking_sphinx/active_record/has_many_association.rb +0 -36
  34. data/lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb +0 -21
  35. data/lib/thinking_sphinx/active_record/log_subscriber.rb +0 -61
  36. data/lib/thinking_sphinx/active_record/scopes.rb +0 -93
  37. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +0 -87
  38. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +0 -62
  39. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +0 -157
  40. data/lib/thinking_sphinx/association.rb +0 -219
  41. data/lib/thinking_sphinx/attribute.rb +0 -396
  42. data/lib/thinking_sphinx/auto_version.rb +0 -38
  43. data/lib/thinking_sphinx/bundled_search.rb +0 -44
  44. data/lib/thinking_sphinx/class_facet.rb +0 -20
  45. data/lib/thinking_sphinx/configuration.rb +0 -339
  46. data/lib/thinking_sphinx/context.rb +0 -76
  47. data/lib/thinking_sphinx/core/string.rb +0 -15
  48. data/lib/thinking_sphinx/deltas.rb +0 -28
  49. data/lib/thinking_sphinx/deltas/default_delta.rb +0 -62
  50. data/lib/thinking_sphinx/deploy/capistrano.rb +0 -101
  51. data/lib/thinking_sphinx/excerpter.rb +0 -23
  52. data/lib/thinking_sphinx/facet.rb +0 -128
  53. data/lib/thinking_sphinx/facet_search.rb +0 -170
  54. data/lib/thinking_sphinx/field.rb +0 -98
  55. data/lib/thinking_sphinx/index.rb +0 -157
  56. data/lib/thinking_sphinx/index/builder.rb +0 -312
  57. data/lib/thinking_sphinx/index/faux_column.rb +0 -118
  58. data/lib/thinking_sphinx/join.rb +0 -37
  59. data/lib/thinking_sphinx/property.rb +0 -185
  60. data/lib/thinking_sphinx/railtie.rb +0 -46
  61. data/lib/thinking_sphinx/search.rb +0 -972
  62. data/lib/thinking_sphinx/search_methods.rb +0 -439
  63. data/lib/thinking_sphinx/sinatra.rb +0 -7
  64. data/lib/thinking_sphinx/source.rb +0 -194
  65. data/lib/thinking_sphinx/source/internal_properties.rb +0 -51
  66. data/lib/thinking_sphinx/source/sql.rb +0 -157
  67. data/lib/thinking_sphinx/tasks.rb +0 -130
  68. data/lib/thinking_sphinx/test.rb +0 -55
  69. data/tasks/distribution.rb +0 -33
  70. data/tasks/testing.rb +0 -80
@@ -1,38 +0,0 @@
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/
9
- require 'riddle/1.10'
10
- when /2.0.\d/
11
- require 'riddle/2.0.1'
12
- else
13
- documentation_link = %Q{
14
- For more information, read the documentation:
15
- http://freelancing-god.github.com/ts/en/advanced_config.html
16
- }
17
-
18
- if version.nil? || version.empty?
19
- STDERR.puts %Q{
20
- Sphinx cannot be found on your system. You may need to configure the following
21
- settings in your config/sphinx.yml file:
22
- * bin_path
23
- * searchd_binary_name
24
- * indexer_binary_name
25
-
26
- #{documentation_link}
27
- }
28
- else
29
- STDERR.puts %Q{
30
- Unsupported version: #{version}
31
-
32
- #{documentation_link}
33
- }
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,44 +0,0 @@
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
@@ -1,20 +0,0 @@
1
- module ThinkingSphinx
2
- class ClassFacet < ThinkingSphinx::Facet
3
- def name
4
- :class
5
- end
6
-
7
- def attribute_name
8
- Riddle.loaded_version.to_i < 2 ? 'class_crc' : 'sphinx_internal_class'
9
- end
10
-
11
- def value(object, attribute_hash)
12
- if Riddle.loaded_version.to_i < 2
13
- crc = attribute_hash['class_crc']
14
- ThinkingSphinx::Configuration.instance.models_by_crc[crc]
15
- else
16
- attribute_hash['sphinx_internal_class']
17
- end
18
- end
19
- end
20
- end
@@ -1,339 +0,0 @@
1
- require 'erb'
2
- require 'singleton'
3
-
4
- module ThinkingSphinx
5
- # This class both keeps track of the configuration settings for Sphinx and
6
- # also generates the resulting file for Sphinx to use.
7
- #
8
- # Here are the default settings, relative to Rails.root where relevant:
9
- #
10
- # config file:: config/#{environment}.sphinx.conf
11
- # searchd log file:: log/searchd.log
12
- # query log file:: log/searchd.query.log
13
- # pid file:: log/searchd.#{environment}.pid
14
- # searchd files:: db/sphinx/#{environment}/
15
- # address:: 127.0.0.1
16
- # port:: 9312
17
- # allow star:: false
18
- # min prefix length:: 1
19
- # min infix length:: 1
20
- # mem limit:: 64M
21
- # max matches:: 1000
22
- # morphology:: nil
23
- # charset type:: utf-8
24
- # charset table:: nil
25
- # ignore chars:: nil
26
- # html strip:: false
27
- # html remove elements:: ''
28
- # searchd_binary_name:: searchd
29
- # indexer_binary_name:: indexer
30
- #
31
- # If you want to change these settings, create a YAML file at
32
- # config/sphinx.yml with settings for each environment, in a similar
33
- # fashion to database.yml - using the following keys: config_file,
34
- # searchd_log_file, query_log_file, pid_file, searchd_file_path, port,
35
- # allow_star, enable_star, min_prefix_len, min_infix_len, mem_limit,
36
- # max_matches, morphology, charset_type, charset_table, ignore_chars,
37
- # html_strip, html_remove_elements, delayed_job_priority,
38
- # searchd_binary_name, indexer_binary_name.
39
- #
40
- # I think you've got the idea.
41
- #
42
- # Each setting in the YAML file is optional - so only put in the ones you
43
- # want to change.
44
- #
45
- # Keep in mind, if for some particular reason you're using a version of
46
- # Sphinx older than 0.9.8 r871 (that's prior to the proper 0.9.8 release),
47
- # don't set allow_star to true.
48
- #
49
- class Configuration
50
- include Singleton
51
-
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 )
56
-
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 )
65
-
66
- CustomOptions = %w( disable_range )
67
-
68
- attr_accessor :searchd_file_path, :allow_star, :database_yml_file,
69
- :app_root, :model_directories, :delayed_job_priority, :indexed_models
70
-
71
- attr_accessor :source_options, :index_options
72
- attr_accessor :version
73
-
74
- attr_reader :environment, :configuration, :controller
75
-
76
- @@environment = nil
77
-
78
- # Load in the configuration settings - this will look for config/sphinx.yml
79
- # and parse it according to the current environment.
80
- #
81
- def initialize(app_root = Dir.pwd)
82
- self.reset
83
- end
84
-
85
- def self.configure(&block)
86
- yield instance
87
- instance.reset(instance.app_root)
88
- end
89
-
90
- def reset(custom_app_root=nil)
91
- if custom_app_root
92
- self.app_root = custom_app_root
93
- else
94
- self.app_root = Merb.root if defined?(Merb)
95
- self.app_root = Sinatra::Application.root if defined?(Sinatra)
96
- self.app_root = Rails.root if defined?(Rails)
97
- self.app_root ||= app_root
98
- end
99
-
100
- @configuration = Riddle::Configuration.new
101
- @configuration.searchd.pid_file = "#{self.app_root}/log/searchd.#{environment}.pid"
102
- @configuration.searchd.log = "#{self.app_root}/log/searchd.log"
103
- @configuration.searchd.query_log = "#{self.app_root}/log/searchd.query.log"
104
-
105
- @controller = Riddle::Controller.new @configuration,
106
- "#{self.app_root}/config/#{environment}.sphinx.conf"
107
-
108
- self.address = "127.0.0.1"
109
- self.port = 9312
110
- self.database_yml_file = "#{self.app_root}/config/database.yml"
111
- self.searchd_file_path = "#{self.app_root}/db/sphinx/#{environment}"
112
- self.allow_star = false
113
- self.model_directories = ["#{app_root}/app/models/"] +
114
- Dir.glob("#{app_root}/vendor/plugins/*/app/models/")
115
- self.delayed_job_priority = 0
116
- self.indexed_models = []
117
-
118
- self.source_options = {}
119
- self.index_options = {
120
- :charset_type => "utf-8"
121
- }
122
-
123
- self.version = nil
124
- parse_config
125
- self.version ||= @controller.sphinx_version
126
-
127
- self
128
- end
129
-
130
- def self.environment
131
- if @@environment.nil?
132
- ThinkingSphinx.mutex.synchronize do
133
- @@environment ||= if defined?(Merb)
134
- Merb.environment
135
- elsif defined?(Rails)
136
- Rails.env
137
- elsif defined?(Sinatra)
138
- Sinatra::Application.environment.to_s
139
- else
140
- ENV['RAILS_ENV'] || 'development'
141
- end
142
- end
143
- end
144
-
145
- @@environment
146
- end
147
-
148
- def self.reset_environment
149
- ThinkingSphinx.mutex.synchronize do
150
- @@environment = nil
151
- end
152
- end
153
-
154
- def environment
155
- self.class.environment
156
- end
157
-
158
- def generate
159
- @configuration.indexes.clear
160
-
161
- ThinkingSphinx.context.indexed_models.each do |model|
162
- model = model.constantize
163
- model.define_indexes
164
- @configuration.indexes.concat model.to_riddle
165
-
166
- enforce_common_attribute_types
167
- end
168
- end
169
-
170
- # Generate the config file for Sphinx by using all the settings defined and
171
- # looping through all the models with indexes to build the relevant
172
- # indexer and searchd configuration, and sources and indexes details.
173
- #
174
- def build(file_path=nil)
175
- file_path ||= "#{self.config_file}"
176
-
177
- generate
178
-
179
- open(file_path, "w") do |file|
180
- file.write @configuration.render
181
- end
182
- end
183
-
184
- def address
185
- @address
186
- end
187
-
188
- def address=(address)
189
- @address = address
190
- @configuration.searchd.address = address
191
- end
192
-
193
- def port
194
- @port
195
- end
196
-
197
- def port=(port)
198
- @port = port
199
- @configuration.searchd.port = port
200
- end
201
-
202
- def pid_file
203
- @configuration.searchd.pid_file
204
- end
205
-
206
- def pid_file=(pid_file)
207
- @configuration.searchd.pid_file = pid_file
208
- end
209
-
210
- def searchd_log_file
211
- @configuration.searchd.log
212
- end
213
-
214
- def searchd_log_file=(file)
215
- @configuration.searchd.log = file
216
- end
217
-
218
- def query_log_file
219
- @configuration.searchd.query_log
220
- end
221
-
222
- def query_log_file=(file)
223
- @configuration.searchd.query_log = file
224
- end
225
-
226
- def config_file
227
- @controller.path
228
- end
229
-
230
- def config_file=(file)
231
- @controller.path = file
232
- end
233
-
234
- def bin_path
235
- @controller.bin_path
236
- end
237
-
238
- def bin_path=(path)
239
- @controller.bin_path = path
240
- end
241
-
242
- def searchd_binary_name
243
- @controller.searchd_binary_name
244
- end
245
-
246
- def searchd_binary_name=(name)
247
- @controller.searchd_binary_name = name
248
- end
249
-
250
- def indexer_binary_name
251
- @controller.indexer_binary_name
252
- end
253
-
254
- def indexer_binary_name=(name)
255
- @controller.indexer_binary_name = name
256
- end
257
-
258
- attr_accessor :timeout
259
-
260
- def client
261
- client = Riddle::Client.new address, port,
262
- configuration.searchd.client_key
263
- client.max_matches = configuration.searchd.max_matches || 1000
264
- client.timeout = timeout || 0
265
- client
266
- end
267
-
268
- def models_by_crc
269
- @models_by_crc ||= begin
270
- ThinkingSphinx.context.indexed_models.inject({}) do |hash, model|
271
- hash[model.constantize.to_crc32] = model
272
- model.constantize.descendants.each { |subclass|
273
- hash[subclass.to_crc32] = subclass.name
274
- }
275
- hash
276
- end
277
- end
278
- end
279
-
280
- private
281
-
282
- # Parse the config/sphinx.yml file - if it exists - then use the attribute
283
- # accessors to set the appropriate values. Nothing too clever.
284
- #
285
- def parse_config
286
- path = "#{app_root}/config/sphinx.yml"
287
- return unless File.exists?(path)
288
-
289
- conf = YAML::load(ERB.new(IO.read(path)).result)[environment]
290
-
291
- conf.each do |key,value|
292
- self.send("#{key}=", value) if self.respond_to?("#{key}=")
293
-
294
- set_sphinx_setting self.source_options, key, value, SourceOptions
295
- set_sphinx_setting self.index_options, key, value, IndexOptions
296
- set_sphinx_setting self.index_options, key, value, CustomOptions
297
- set_sphinx_setting @configuration.searchd, key, value
298
- set_sphinx_setting @configuration.indexer, key, value
299
- end unless conf.nil?
300
-
301
- self.bin_path += '/' unless self.bin_path.blank?
302
-
303
- if self.allow_star
304
- self.index_options[:enable_star] = true
305
- self.index_options[:min_prefix_len] = 1
306
- end
307
- end
308
-
309
- def set_sphinx_setting(object, key, value, allowed = {})
310
- if object.is_a?(Hash)
311
- object[key.to_sym] = value if allowed.include?(key.to_s)
312
- else
313
- object.send("#{key}=", value) if object.respond_to?("#{key}")
314
- send("#{key}=", value) if self.respond_to?("#{key}")
315
- end
316
- end
317
-
318
- def enforce_common_attribute_types
319
- sql_indexes = configuration.indexes.reject { |index|
320
- index.is_a? Riddle::Configuration::DistributedIndex
321
- }
322
-
323
- return unless sql_indexes.any? { |index|
324
- index.sources.any? { |source|
325
- source.sql_attr_bigint.include? :sphinx_internal_id
326
- }
327
- }
328
-
329
- sql_indexes.each { |index|
330
- index.sources.each { |source|
331
- next if source.sql_attr_bigint.include? :sphinx_internal_id
332
-
333
- source.sql_attr_bigint << :sphinx_internal_id
334
- source.sql_attr_uint.delete :sphinx_internal_id
335
- }
336
- }
337
- end
338
- end
339
- end
@@ -1,76 +0,0 @@
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
- ActiveRecord::Base.descendants.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(:descendants).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