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.
- data/README.textile +7 -1
- data/features/searching_by_model.feature +24 -30
- data/features/step_definitions/common_steps.rb +5 -5
- data/features/thinking_sphinx/db/.gitignore +1 -0
- data/features/thinking_sphinx/db/fixtures/post_keywords.txt +1 -0
- data/spec/fixtures/data.sql +32 -0
- data/spec/fixtures/database.yml.default +3 -0
- data/spec/fixtures/models.rb +161 -0
- data/spec/fixtures/structure.sql +146 -0
- data/spec/spec_helper.rb +62 -0
- data/spec/sphinx_helper.rb +61 -0
- data/spec/support/rails.rb +18 -0
- data/spec/thinking_sphinx/active_record/delta_spec.rb +24 -24
- data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +27 -0
- data/spec/thinking_sphinx/active_record/scopes_spec.rb +25 -25
- data/spec/thinking_sphinx/active_record_spec.rb +108 -107
- data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +38 -38
- data/spec/thinking_sphinx/association_spec.rb +69 -35
- data/spec/thinking_sphinx/context_spec.rb +61 -64
- data/spec/thinking_sphinx/search_spec.rb +7 -0
- data/spec/thinking_sphinx_spec.rb +47 -46
- metadata +49 -141
- data/VERSION +0 -1
- data/lib/cucumber/thinking_sphinx/external_world.rb +0 -12
- data/lib/cucumber/thinking_sphinx/internal_world.rb +0 -127
- data/lib/cucumber/thinking_sphinx/sql_logger.rb +0 -20
- data/lib/thinking-sphinx.rb +0 -1
- data/lib/thinking_sphinx.rb +0 -301
- data/lib/thinking_sphinx/action_controller.rb +0 -31
- data/lib/thinking_sphinx/active_record.rb +0 -384
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +0 -52
- data/lib/thinking_sphinx/active_record/delta.rb +0 -65
- data/lib/thinking_sphinx/active_record/has_many_association.rb +0 -36
- data/lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb +0 -21
- data/lib/thinking_sphinx/active_record/log_subscriber.rb +0 -61
- data/lib/thinking_sphinx/active_record/scopes.rb +0 -93
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +0 -87
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +0 -62
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +0 -157
- data/lib/thinking_sphinx/association.rb +0 -219
- data/lib/thinking_sphinx/attribute.rb +0 -396
- data/lib/thinking_sphinx/auto_version.rb +0 -38
- data/lib/thinking_sphinx/bundled_search.rb +0 -44
- data/lib/thinking_sphinx/class_facet.rb +0 -20
- data/lib/thinking_sphinx/configuration.rb +0 -339
- data/lib/thinking_sphinx/context.rb +0 -76
- data/lib/thinking_sphinx/core/string.rb +0 -15
- data/lib/thinking_sphinx/deltas.rb +0 -28
- data/lib/thinking_sphinx/deltas/default_delta.rb +0 -62
- data/lib/thinking_sphinx/deploy/capistrano.rb +0 -101
- data/lib/thinking_sphinx/excerpter.rb +0 -23
- data/lib/thinking_sphinx/facet.rb +0 -128
- data/lib/thinking_sphinx/facet_search.rb +0 -170
- data/lib/thinking_sphinx/field.rb +0 -98
- data/lib/thinking_sphinx/index.rb +0 -157
- data/lib/thinking_sphinx/index/builder.rb +0 -312
- data/lib/thinking_sphinx/index/faux_column.rb +0 -118
- data/lib/thinking_sphinx/join.rb +0 -37
- data/lib/thinking_sphinx/property.rb +0 -185
- data/lib/thinking_sphinx/railtie.rb +0 -46
- data/lib/thinking_sphinx/search.rb +0 -972
- data/lib/thinking_sphinx/search_methods.rb +0 -439
- data/lib/thinking_sphinx/sinatra.rb +0 -7
- data/lib/thinking_sphinx/source.rb +0 -194
- data/lib/thinking_sphinx/source/internal_properties.rb +0 -51
- data/lib/thinking_sphinx/source/sql.rb +0 -157
- data/lib/thinking_sphinx/tasks.rb +0 -130
- data/lib/thinking_sphinx/test.rb +0 -55
- data/tasks/distribution.rb +0 -33
- data/tasks/testing.rb +0 -80
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.0.5
|
@@ -1,127 +0,0 @@
|
|
1
|
-
require 'cucumber/thinking_sphinx/sql_logger'
|
2
|
-
|
3
|
-
module Cucumber
|
4
|
-
module ThinkingSphinx
|
5
|
-
class InternalWorld
|
6
|
-
attr_accessor :temporary_directory, :migrations_directory,
|
7
|
-
:models_directory, :fixtures_directory, :database_file
|
8
|
-
attr_accessor :adapter, :database, :username,
|
9
|
-
:password, :host
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
pwd = Dir.pwd
|
13
|
-
@temporary_directory = "#{pwd}/tmp"
|
14
|
-
@migrations_directory = "#{pwd}/features/thinking_sphinx/db/migrations"
|
15
|
-
@models_directory = "#{pwd}/features/thinking_sphinx/models"
|
16
|
-
@fixtures_directory = "#{pwd}/features/thinking_sphinx/db/fixtures"
|
17
|
-
@database_file = "#{pwd}/features/thinking_sphinx/database.yml"
|
18
|
-
|
19
|
-
@adapter = ENV['DATABASE'] || 'mysql'
|
20
|
-
@database = 'thinking_sphinx'
|
21
|
-
@username = 'thinking_sphinx'
|
22
|
-
# @password = 'thinking_sphinx'
|
23
|
-
@host = 'localhost'
|
24
|
-
end
|
25
|
-
|
26
|
-
def setup
|
27
|
-
make_temporary_directory
|
28
|
-
|
29
|
-
configure_cleanup
|
30
|
-
configure_thinking_sphinx
|
31
|
-
configure_active_record
|
32
|
-
|
33
|
-
prepare_data
|
34
|
-
setup_sphinx
|
35
|
-
|
36
|
-
self
|
37
|
-
end
|
38
|
-
|
39
|
-
def configure_database
|
40
|
-
ActiveRecord::Base.establish_connection database_settings
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
def config
|
47
|
-
@config ||= ::ThinkingSphinx::Configuration.instance
|
48
|
-
end
|
49
|
-
|
50
|
-
def make_temporary_directory
|
51
|
-
FileUtils.mkdir_p temporary_directory
|
52
|
-
Dir["#{temporary_directory}/*"].each do |file|
|
53
|
-
FileUtils.rm_rf file
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def configure_thinking_sphinx
|
58
|
-
config.config_file = "#{temporary_directory}/sphinx.conf"
|
59
|
-
config.searchd_log_file = "#{temporary_directory}/searchd.log"
|
60
|
-
config.query_log_file = "#{temporary_directory}/searchd.query.log"
|
61
|
-
config.pid_file = "#{temporary_directory}/searchd.pid"
|
62
|
-
config.searchd_file_path = "#{temporary_directory}/indexes/"
|
63
|
-
|
64
|
-
::ThinkingSphinx.suppress_delta_output = true
|
65
|
-
end
|
66
|
-
|
67
|
-
def configure_cleanup
|
68
|
-
Kernel.at_exit do
|
69
|
-
::ThinkingSphinx::Configuration.instance.controller.stop
|
70
|
-
sleep(0.5) # Ensure Sphinx has shut down completely
|
71
|
-
::ThinkingSphinx::ActiveRecord::LogSubscriber.logger.close
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def yaml_database_settings
|
76
|
-
return {} unless File.exist?(@database_file)
|
77
|
-
|
78
|
-
YAML.load open(@database_file)
|
79
|
-
end
|
80
|
-
|
81
|
-
def database_settings
|
82
|
-
{
|
83
|
-
'adapter' => @adapter,
|
84
|
-
'database' => @database,
|
85
|
-
'username' => @username,
|
86
|
-
'password' => @password,
|
87
|
-
'host' => @host
|
88
|
-
}.merge yaml_database_settings
|
89
|
-
end
|
90
|
-
|
91
|
-
def configure_active_record
|
92
|
-
::ThinkingSphinx::ActiveRecord::LogSubscriber.logger = Logger.new(
|
93
|
-
open("#{temporary_directory}/active_record.log", "a")
|
94
|
-
)
|
95
|
-
|
96
|
-
ActiveRecord::Base.connection.class.send(
|
97
|
-
:include, Cucumber::ThinkingSphinx::SqlLogger
|
98
|
-
)
|
99
|
-
end
|
100
|
-
|
101
|
-
def prepare_data
|
102
|
-
::ThinkingSphinx.deltas_enabled = false
|
103
|
-
|
104
|
-
load_files migrations_directory
|
105
|
-
load_files models_directory
|
106
|
-
load_files fixtures_directory
|
107
|
-
|
108
|
-
::ThinkingSphinx.deltas_enabled = true
|
109
|
-
end
|
110
|
-
|
111
|
-
def load_files(path)
|
112
|
-
files = Dir["#{path}/*.rb"].sort!
|
113
|
-
files.each do |file|
|
114
|
-
require file.gsub(/\.rb$/, '')
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def setup_sphinx
|
119
|
-
FileUtils.mkdir_p config.searchd_file_path
|
120
|
-
|
121
|
-
config.build
|
122
|
-
config.controller.index
|
123
|
-
config.controller.start
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Cucumber
|
2
|
-
module ThinkingSphinx
|
3
|
-
module SqlLogger
|
4
|
-
def self.included(base)
|
5
|
-
base.send :alias_method_chain, :execute, :query_record
|
6
|
-
end
|
7
|
-
|
8
|
-
IGNORED_SQL = [
|
9
|
-
/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/,
|
10
|
-
/^SELECT @@ROWCOUNT/, /^SHOW FIELDS/
|
11
|
-
]
|
12
|
-
|
13
|
-
def execute_with_query_record(sql, name = nil, &block)
|
14
|
-
$queries_executed ||= []
|
15
|
-
$queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r }
|
16
|
-
execute_without_query_record(sql, name, &block)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/thinking-sphinx.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'thinking_sphinx'
|
data/lib/thinking_sphinx.rb
DELETED
@@ -1,301 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
require 'active_record'
|
3
|
-
require 'yaml'
|
4
|
-
require 'riddle'
|
5
|
-
|
6
|
-
require 'thinking_sphinx/auto_version'
|
7
|
-
require 'thinking_sphinx/core/string'
|
8
|
-
require 'thinking_sphinx/property'
|
9
|
-
require 'thinking_sphinx/active_record'
|
10
|
-
require 'thinking_sphinx/association'
|
11
|
-
require 'thinking_sphinx/attribute'
|
12
|
-
require 'thinking_sphinx/bundled_search'
|
13
|
-
require 'thinking_sphinx/configuration'
|
14
|
-
require 'thinking_sphinx/context'
|
15
|
-
require 'thinking_sphinx/excerpter'
|
16
|
-
require 'thinking_sphinx/facet'
|
17
|
-
require 'thinking_sphinx/class_facet'
|
18
|
-
require 'thinking_sphinx/facet_search'
|
19
|
-
require 'thinking_sphinx/field'
|
20
|
-
require 'thinking_sphinx/index'
|
21
|
-
require 'thinking_sphinx/join'
|
22
|
-
require 'thinking_sphinx/source'
|
23
|
-
require 'thinking_sphinx/search'
|
24
|
-
require 'thinking_sphinx/search_methods'
|
25
|
-
require 'thinking_sphinx/deltas'
|
26
|
-
|
27
|
-
require 'thinking_sphinx/adapters/abstract_adapter'
|
28
|
-
require 'thinking_sphinx/adapters/mysql_adapter'
|
29
|
-
require 'thinking_sphinx/adapters/postgresql_adapter'
|
30
|
-
|
31
|
-
require 'thinking_sphinx/railtie' if defined?(Rails)
|
32
|
-
|
33
|
-
module ThinkingSphinx
|
34
|
-
mattr_accessor :database_adapter
|
35
|
-
|
36
|
-
# A ConnectionError will get thrown when a connection to Sphinx can't be
|
37
|
-
# made.
|
38
|
-
class ConnectionError < StandardError
|
39
|
-
end
|
40
|
-
|
41
|
-
# A StaleIdsException is thrown by Collection.instances_from_matches if there
|
42
|
-
# are records in Sphinx but not in the database, so the search can be retried.
|
43
|
-
class StaleIdsException < StandardError
|
44
|
-
attr_accessor :ids
|
45
|
-
def initialize(ids)
|
46
|
-
self.ids = ids
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# A SphinxError occurs when Sphinx responds with an error due to problematic
|
51
|
-
# queries or indexes.
|
52
|
-
class SphinxError < RuntimeError
|
53
|
-
attr_accessor :results
|
54
|
-
def initialize(message = nil, results = nil)
|
55
|
-
super(message)
|
56
|
-
self.results = results
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# The current version of Thinking Sphinx.
|
61
|
-
#
|
62
|
-
# @return [String] The version number as a string
|
63
|
-
#
|
64
|
-
def self.version
|
65
|
-
open(File.join(File.dirname(__FILE__), '../VERSION')) { |f|
|
66
|
-
f.read.strip
|
67
|
-
}
|
68
|
-
end
|
69
|
-
|
70
|
-
# The collection of indexed models. Keep in mind that Rails lazily loads
|
71
|
-
# its classes, so this may not actually be populated with _all_ the models
|
72
|
-
# that have Sphinx indexes.
|
73
|
-
@@sphinx_mutex = Mutex.new
|
74
|
-
@@context = nil
|
75
|
-
@@define_indexes = true
|
76
|
-
@@deltas_enabled = nil
|
77
|
-
@@updates_enabled = nil
|
78
|
-
@@suppress_delta_output = false
|
79
|
-
@@remote_sphinx = false
|
80
|
-
@@use_group_by_shortcut = nil
|
81
|
-
|
82
|
-
def self.mutex
|
83
|
-
@@sphinx_mutex
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.context
|
87
|
-
if @@context.nil?
|
88
|
-
mutex.synchronize do
|
89
|
-
if @@context.nil?
|
90
|
-
@@context = ThinkingSphinx::Context.new
|
91
|
-
@@context.prepare
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
@@context
|
97
|
-
end
|
98
|
-
|
99
|
-
def self.reset_context!(context = nil)
|
100
|
-
mutex.synchronize do
|
101
|
-
@@context = context
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.unique_id_expression(adapter, offset = nil)
|
106
|
-
"* #{adapter.cast_to_int context.indexed_models.size} + #{offset || 0}"
|
107
|
-
end
|
108
|
-
|
109
|
-
# Check if index definition is disabled.
|
110
|
-
#
|
111
|
-
def self.define_indexes?
|
112
|
-
@@define_indexes
|
113
|
-
end
|
114
|
-
|
115
|
-
# Enable/disable indexes - you may want to do this while migrating data.
|
116
|
-
#
|
117
|
-
# ThinkingSphinx.define_indexes = false
|
118
|
-
#
|
119
|
-
def self.define_indexes=(value)
|
120
|
-
mutex.synchronize do
|
121
|
-
@@define_indexes = value
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# Check if delta indexing is enabled/disabled.
|
126
|
-
#
|
127
|
-
def self.deltas_enabled?
|
128
|
-
if @@deltas_enabled.nil?
|
129
|
-
mutex.synchronize do
|
130
|
-
if @@deltas_enabled.nil?
|
131
|
-
@@deltas_enabled = (
|
132
|
-
ThinkingSphinx::Configuration.environment != "test"
|
133
|
-
)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
@@deltas_enabled && !deltas_suspended?
|
139
|
-
end
|
140
|
-
|
141
|
-
# Enable/disable delta indexing.
|
142
|
-
#
|
143
|
-
# ThinkingSphinx.deltas_enabled = false
|
144
|
-
#
|
145
|
-
def self.deltas_enabled=(value)
|
146
|
-
mutex.synchronize do
|
147
|
-
@@deltas_enabled = value
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
# Check if delta indexing is suspended.
|
152
|
-
#
|
153
|
-
def self.deltas_suspended?
|
154
|
-
if Thread.current[:thinking_sphinx_deltas_suspended].nil?
|
155
|
-
Thread.current[:thinking_sphinx_deltas_suspended] = false
|
156
|
-
end
|
157
|
-
|
158
|
-
Thread.current[:thinking_sphinx_deltas_suspended]
|
159
|
-
end
|
160
|
-
|
161
|
-
# Suspend/resume delta indexing.
|
162
|
-
#
|
163
|
-
# ThinkingSphinx.deltas_suspended = false
|
164
|
-
#
|
165
|
-
def self.deltas_suspended=(value)
|
166
|
-
Thread.current[:thinking_sphinx_deltas_suspended] = value
|
167
|
-
end
|
168
|
-
|
169
|
-
# Check if updates are enabled. True by default, unless within the test
|
170
|
-
# environment.
|
171
|
-
#
|
172
|
-
def self.updates_enabled?
|
173
|
-
if @@updates_enabled.nil?
|
174
|
-
mutex.synchronize do
|
175
|
-
if @@updates_enabled.nil?
|
176
|
-
@@updates_enabled = (
|
177
|
-
ThinkingSphinx::Configuration.environment != "test"
|
178
|
-
)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
@@updates_enabled
|
184
|
-
end
|
185
|
-
|
186
|
-
# Enable/disable updates to Sphinx
|
187
|
-
#
|
188
|
-
# ThinkingSphinx.updates_enabled = false
|
189
|
-
#
|
190
|
-
def self.updates_enabled=(value)
|
191
|
-
mutex.synchronize do
|
192
|
-
@@updates_enabled = value
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
def self.suppress_delta_output?
|
197
|
-
@@suppress_delta_output
|
198
|
-
end
|
199
|
-
|
200
|
-
def self.suppress_delta_output=(value)
|
201
|
-
mutex.synchronize do
|
202
|
-
@@suppress_delta_output = value
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
# Checks to see if MySQL will allow simplistic GROUP BY statements. If not,
|
207
|
-
# or if not using MySQL, this will return false.
|
208
|
-
#
|
209
|
-
def self.use_group_by_shortcut?
|
210
|
-
if @@use_group_by_shortcut.nil?
|
211
|
-
mutex.synchronize do
|
212
|
-
if @@use_group_by_shortcut.nil?
|
213
|
-
@@use_group_by_shortcut = !!(
|
214
|
-
mysql? && ::ActiveRecord::Base.connection.select_all(
|
215
|
-
"SELECT @@global.sql_mode, @@session.sql_mode;"
|
216
|
-
).all? { |key, value|
|
217
|
-
value.nil? || value[/ONLY_FULL_GROUP_BY/].nil?
|
218
|
-
}
|
219
|
-
)
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
@@use_group_by_shortcut
|
225
|
-
end
|
226
|
-
|
227
|
-
def self.reset_use_group_by_shortcut
|
228
|
-
mutex.synchronize do
|
229
|
-
@@use_group_by_shortcut = nil
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
# An indication of whether Sphinx is running on a remote machine instead of
|
234
|
-
# the same machine.
|
235
|
-
#
|
236
|
-
def self.remote_sphinx?
|
237
|
-
@@remote_sphinx
|
238
|
-
end
|
239
|
-
|
240
|
-
# Tells Thinking Sphinx that Sphinx is running on a different machine, and
|
241
|
-
# thus it can't reliably guess whether it is running or not (ie: the
|
242
|
-
# #sphinx_running? method), and so just assumes it is.
|
243
|
-
#
|
244
|
-
# Useful for multi-machine deployments. Set it in your production.rb file.
|
245
|
-
#
|
246
|
-
# ThinkingSphinx.remote_sphinx = true
|
247
|
-
#
|
248
|
-
def self.remote_sphinx=(value)
|
249
|
-
mutex.synchronize do
|
250
|
-
@@remote_sphinx = value
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
# Check if Sphinx is running. If remote_sphinx is set to true (indicating
|
255
|
-
# Sphinx is on a different machine), this will always return true, and you
|
256
|
-
# will have to handle any connection errors yourself.
|
257
|
-
#
|
258
|
-
def self.sphinx_running?
|
259
|
-
remote_sphinx? || sphinx_running_by_pid?
|
260
|
-
end
|
261
|
-
|
262
|
-
# Check if Sphinx is actually running, provided the pid is on the same
|
263
|
-
# machine as this code.
|
264
|
-
#
|
265
|
-
def self.sphinx_running_by_pid?
|
266
|
-
!!sphinx_pid && pid_active?(sphinx_pid)
|
267
|
-
end
|
268
|
-
|
269
|
-
def self.sphinx_pid
|
270
|
-
if File.exists?(ThinkingSphinx::Configuration.instance.pid_file)
|
271
|
-
File.read(ThinkingSphinx::Configuration.instance.pid_file)[/\d+/]
|
272
|
-
else
|
273
|
-
nil
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def self.pid_active?(pid)
|
278
|
-
!!Process.kill(0, pid.to_i)
|
279
|
-
rescue Errno::EPERM => e
|
280
|
-
true
|
281
|
-
rescue Exception => e
|
282
|
-
false
|
283
|
-
end
|
284
|
-
|
285
|
-
def self.microsoft?
|
286
|
-
RUBY_PLATFORM =~ /mswin/
|
287
|
-
end
|
288
|
-
|
289
|
-
def self.jruby?
|
290
|
-
defined?(JRUBY_VERSION)
|
291
|
-
end
|
292
|
-
|
293
|
-
def self.mysql?
|
294
|
-
::ActiveRecord::Base.connection.class.name.demodulize == "MysqlAdapter" ||
|
295
|
-
::ActiveRecord::Base.connection.class.name.demodulize == "MysqlplusAdapter" || (
|
296
|
-
jruby? && ::ActiveRecord::Base.connection.config[:adapter] == "jdbcmysql"
|
297
|
-
)
|
298
|
-
end
|
299
|
-
|
300
|
-
extend ThinkingSphinx::SearchMethods::ClassMethods
|
301
|
-
end
|