thinking-sphinx 1.3.3 → 1.3.4
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 +3 -0
- data/VERSION.yml +1 -1
- data/lib/thinking_sphinx.rb +0 -4
- data/lib/thinking_sphinx/active_record/scopes.rb +37 -1
- data/lib/thinking_sphinx/configuration.rb +10 -6
- data/lib/thinking_sphinx/deploy/capistrano.rb +1 -1
- data/lib/thinking_sphinx/search.rb +20 -7
- data/lib/thinking_sphinx/source.rb +2 -1
- data/rails/init.rb +4 -0
- data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +46 -2
- data/spec/lib/thinking_sphinx/configuration_spec.rb +25 -3
- data/spec/lib/thinking_sphinx/index/builder_spec.rb +14 -0
- data/tasks/distribution.rb +1 -1
- metadata +3 -3
data/README.textile
CHANGED
data/VERSION.yml
CHANGED
data/lib/thinking_sphinx.rb
CHANGED
@@ -8,6 +8,40 @@ module ThinkingSphinx
|
|
8
8
|
end
|
9
9
|
|
10
10
|
module ClassMethods
|
11
|
+
|
12
|
+
# Similar to ActiveRecord's default_scope method Thinking Sphinx supports
|
13
|
+
# a default_sphinx_scope. For example:
|
14
|
+
#
|
15
|
+
# default_sphinx_scope :some_sphinx_named_scope
|
16
|
+
#
|
17
|
+
# The scope is automatically applied when the search method is called. It
|
18
|
+
# will only be applied if it is an existing sphinx_scope.
|
19
|
+
def default_sphinx_scope(sphinx_scope_name)
|
20
|
+
@default_sphinx_scope = sphinx_scope_name
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the default_sphinx_scope or nil if none is set.
|
24
|
+
def get_default_sphinx_scope
|
25
|
+
@default_sphinx_scope
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns true if the current Model has a default_sphinx_scope. Also checks if
|
29
|
+
# the default_sphinx_scope actually is a scope.
|
30
|
+
def has_default_sphinx_scope?
|
31
|
+
!@default_sphinx_scope.nil? && sphinx_scopes.include?(@default_sphinx_scope)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Similar to ActiveRecord's named_scope method Thinking Sphinx supports
|
35
|
+
# scopes. For example:
|
36
|
+
#
|
37
|
+
# sphinx_scope(:latest_first) {
|
38
|
+
# {:order => 'created_at DESC, @relevance DESC'}
|
39
|
+
# }
|
40
|
+
#
|
41
|
+
# Usage:
|
42
|
+
#
|
43
|
+
# @articles = Article.latest_first.search 'pancakes'
|
44
|
+
#
|
11
45
|
def sphinx_scope(method, &block)
|
12
46
|
@sphinx_scopes ||= []
|
13
47
|
@sphinx_scopes << method
|
@@ -21,7 +55,9 @@ module ThinkingSphinx
|
|
21
55
|
end
|
22
56
|
end
|
23
57
|
end
|
24
|
-
|
58
|
+
|
59
|
+
# This returns an Array of all defined scopes. The default
|
60
|
+
# scope shows as :default.
|
25
61
|
def sphinx_scopes
|
26
62
|
@sphinx_scopes || []
|
27
63
|
end
|
@@ -49,14 +49,18 @@ module ThinkingSphinx
|
|
49
49
|
class Configuration
|
50
50
|
include Singleton
|
51
51
|
|
52
|
-
SourceOptions = %w( mysql_connect_flags
|
53
|
-
|
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
57
|
IndexOptions = %w( charset_table charset_type docinfo enable_star
|
56
|
-
exceptions html_index_attrs html_remove_elements html_strip
|
57
|
-
|
58
|
-
|
59
|
-
|
58
|
+
exceptions html_index_attrs html_remove_elements html_strip
|
59
|
+
index_exact_words ignore_chars inplace_docinfo_gap inplace_enable
|
60
|
+
inplace_hit_gap inplace_reloc_factor inplace_write_factor min_infix_len
|
61
|
+
min_prefix_len min_stemming_len min_word_len mlock morphology ngram_chars
|
62
|
+
ngram_len ondisk_dict overshort_step phrase_boundary phrase_boundary_step
|
63
|
+
preopen stopwords stopwords_step wordforms )
|
60
64
|
|
61
65
|
CustomOptions = %w( disable_range )
|
62
66
|
|
@@ -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
|
kind_of? member? method methods nil? object_id respond_to? send should
|
15
15
|
type )
|
16
16
|
SafeMethods = %w( partition private_methods protected_methods
|
17
|
-
public_methods send )
|
17
|
+
public_methods send class )
|
18
18
|
|
19
19
|
instance_methods.select { |method|
|
20
20
|
method.to_s[/^__/].nil? && !CoreMethods.include?(method.to_s)
|
@@ -215,6 +215,7 @@ module ThinkingSphinx
|
|
215
215
|
end
|
216
216
|
|
217
217
|
def search(*args)
|
218
|
+
add_default_scope
|
218
219
|
merge_search ThinkingSphinx::Search.new(*args)
|
219
220
|
self
|
220
221
|
end
|
@@ -231,8 +232,12 @@ module ThinkingSphinx
|
|
231
232
|
|
232
233
|
retry_on_stale_index do
|
233
234
|
begin
|
234
|
-
log "Querying
|
235
|
-
|
235
|
+
log "Querying: '#{query}'"
|
236
|
+
runtime = Benchmark.realtime {
|
237
|
+
@results = client.query query, indexes, comment
|
238
|
+
}
|
239
|
+
log "Found #{@results[:total_found]} results", :debug,
|
240
|
+
"Sphinx (#{sprintf("%f", runtime)}s)"
|
236
241
|
rescue Errno::ECONNREFUSED => err
|
237
242
|
raise ThinkingSphinx::ConnectionError,
|
238
243
|
'Connection to Sphinx Daemon (searchd) failed.'
|
@@ -280,13 +285,16 @@ module ThinkingSphinx
|
|
280
285
|
end
|
281
286
|
end
|
282
287
|
|
283
|
-
def self.log(message, method = :debug)
|
288
|
+
def self.log(message, method = :debug, identifier = 'Sphinx')
|
284
289
|
return if ::ActiveRecord::Base.logger.nil?
|
285
|
-
|
290
|
+
identifier_color, message_color = "4;32;1", "0" # 0;1 = Bold
|
291
|
+
info = " \e[#{identifier_color}m#{identifier}\e[0m "
|
292
|
+
info << "\e[#{message_color}m#{message}\e[0m"
|
293
|
+
::ActiveRecord::Base.logger.send method, info
|
286
294
|
end
|
287
295
|
|
288
|
-
def log(
|
289
|
-
self.class.log(
|
296
|
+
def log(*args)
|
297
|
+
self.class.log(*args)
|
290
298
|
end
|
291
299
|
|
292
300
|
def client
|
@@ -684,6 +692,11 @@ MSG
|
|
684
692
|
one_class && one_class.sphinx_scopes.include?(method)
|
685
693
|
end
|
686
694
|
|
695
|
+
# Adds the default_sphinx_scope if set.
|
696
|
+
def add_default_scope
|
697
|
+
add_scope(one_class.get_default_sphinx_scope) if one_class && one_class.has_default_sphinx_scope?
|
698
|
+
end
|
699
|
+
|
687
700
|
def add_scope(method, *args, &block)
|
688
701
|
merge_search one_class.send(method, *args, &block)
|
689
702
|
end
|
@@ -43,8 +43,8 @@ module ThinkingSphinx
|
|
43
43
|
|
44
44
|
set_source_database_settings source
|
45
45
|
set_source_attributes source, offset
|
46
|
-
set_source_sql source, offset
|
47
46
|
set_source_settings source
|
47
|
+
set_source_sql source, offset
|
48
48
|
|
49
49
|
source
|
50
50
|
end
|
@@ -57,6 +57,7 @@ module ThinkingSphinx
|
|
57
57
|
|
58
58
|
set_source_database_settings source
|
59
59
|
set_source_attributes source, offset, true
|
60
|
+
set_source_settings source
|
60
61
|
set_source_sql source, offset, true
|
61
62
|
|
62
63
|
source
|
data/rails/init.rb
CHANGED
@@ -34,7 +34,22 @@ describe ThinkingSphinx::ActiveRecord::Scopes do
|
|
34
34
|
Alpha.sphinx_scopes.should == [:by_name]
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
|
+
describe '.default_sphinx_scope' do
|
39
|
+
before :each do
|
40
|
+
Alpha.sphinx_scope(:scope_used_as_default_scope) { {:conditions => {:name => 'name'}} }
|
41
|
+
Alpha.default_sphinx_scope :scope_used_as_default_scope
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return an array of defined scope names as symbols" do
|
45
|
+
Alpha.sphinx_scopes.should == [:scope_used_as_default_scope]
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should have a default_sphinx_scope" do
|
49
|
+
Alpha.has_default_sphinx_scope?.should be_true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
38
53
|
describe '.remove_sphinx_scopes' do
|
39
54
|
before :each do
|
40
55
|
Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
|
@@ -49,7 +64,36 @@ describe ThinkingSphinx::ActiveRecord::Scopes do
|
|
49
64
|
Alpha.sphinx_scopes.should be_empty
|
50
65
|
end
|
51
66
|
end
|
52
|
-
|
67
|
+
|
68
|
+
describe '.example_default_scope' do
|
69
|
+
before :each do
|
70
|
+
Alpha.sphinx_scope(:foo_scope){ {:conditions => {:name => 'foo'}} }
|
71
|
+
Alpha.default_sphinx_scope :foo_scope
|
72
|
+
Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
|
73
|
+
Alpha.sphinx_scope(:by_foo) { |foo| {:conditions => {:foo => foo}} }
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return a ThinkingSphinx::Search object" do
|
77
|
+
Alpha.search.should be_a(ThinkingSphinx::Search)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should apply the default scope options to the underlying search object" do
|
81
|
+
search = ThinkingSphinx::Search.new(:classes => [Alpha])
|
82
|
+
search.search.options[:conditions].should == {:name => 'foo'}
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should apply the default scope options and scope options to the underlying search object" do
|
86
|
+
search = ThinkingSphinx::Search.new(:classes => [Alpha])
|
87
|
+
search.by_foo('foo').search.options[:conditions].should == {:foo => 'foo', :name => 'foo'}
|
88
|
+
end
|
89
|
+
|
90
|
+
# FIXME: Probably the other way around is more logical? How to do this?
|
91
|
+
it "should apply the default scope options after other scope options to the underlying search object" do
|
92
|
+
search = ThinkingSphinx::Search.new(:classes => [Alpha])
|
93
|
+
search.by_name('bar').search.options[:conditions].should == {:name => 'foo'}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
53
97
|
describe '.example_scope' do
|
54
98
|
before :each do
|
55
99
|
Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
|
@@ -50,7 +50,8 @@ describe ThinkingSphinx::Configuration do
|
|
50
50
|
"charset_table" => "table",
|
51
51
|
"ignore_chars" => "e",
|
52
52
|
"searchd_binary_name" => "sphinx-searchd",
|
53
|
-
"indexer_binary_name" => "sphinx-indexer"
|
53
|
+
"indexer_binary_name" => "sphinx-indexer",
|
54
|
+
"index_exact_words" => true
|
54
55
|
}
|
55
56
|
}
|
56
57
|
|
@@ -187,7 +188,9 @@ describe ThinkingSphinx::Configuration do
|
|
187
188
|
|
188
189
|
it "should insert set index options into the configuration file" do
|
189
190
|
config = ThinkingSphinx::Configuration.instance
|
191
|
+
|
190
192
|
ThinkingSphinx::Configuration::IndexOptions.each do |option|
|
193
|
+
config.reset
|
191
194
|
config.index_options[option.to_sym] = "something"
|
192
195
|
config.build
|
193
196
|
|
@@ -200,15 +203,34 @@ describe ThinkingSphinx::Configuration do
|
|
200
203
|
|
201
204
|
it "should insert set source options into the configuration file" do
|
202
205
|
config = ThinkingSphinx::Configuration.instance
|
206
|
+
config.reset
|
207
|
+
|
208
|
+
config.source_options[:sql_query_pre] = ["something"]
|
203
209
|
ThinkingSphinx::Configuration::SourceOptions.each do |option|
|
204
|
-
config.source_options[option.to_sym]
|
210
|
+
config.source_options[option.to_sym] ||= "something"
|
205
211
|
config.build
|
206
212
|
|
207
213
|
file = open(config.config_file) { |f| f.read }
|
208
214
|
file.should match(/#{option}\s+= something/)
|
209
215
|
|
210
|
-
config.source_options
|
216
|
+
config.source_options.delete option.to_sym
|
211
217
|
end
|
218
|
+
|
219
|
+
config.source_options[:sql_query_pre] = nil
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should not blow away delta or utf options if sql pre is specified in config" do
|
223
|
+
config = ThinkingSphinx::Configuration.instance
|
224
|
+
config.reset
|
225
|
+
|
226
|
+
config.source_options[:sql_query_pre] = ["a pre query"]
|
227
|
+
config.build
|
228
|
+
file = open(config.config_file) { |f| f.read }
|
229
|
+
|
230
|
+
file.should match(/sql_query_pre = a pre query\n\s*sql_query_pre = UPDATE `\w+` SET `delta` = 0 WHERE `delta` = 1/im)
|
231
|
+
file.should match(/sql_query_pre = a pre query\n\s*sql_query_pre = \n/im)
|
232
|
+
|
233
|
+
config.source_options[:sql_query_pre] = nil
|
212
234
|
end
|
213
235
|
|
214
236
|
it "should set any explicit prefixed or infixed fields" do
|
@@ -452,4 +452,18 @@ describe ThinkingSphinx::Index::Builder do
|
|
452
452
|
@index.delta_object.should be_a_kind_of(ThinkingSphinx::Deltas::DefaultDelta)
|
453
453
|
end
|
454
454
|
end
|
455
|
+
|
456
|
+
context 'index options' do
|
457
|
+
before :each do
|
458
|
+
@index = ThinkingSphinx::Index::Builder.generate(Person) do
|
459
|
+
indexes first_name
|
460
|
+
|
461
|
+
set_property :index_exact_words => true
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
it "should track the index_exact_words option to the index" do
|
466
|
+
@index.local_options[:index_exact_words].should be_true
|
467
|
+
end
|
468
|
+
end
|
455
469
|
end
|
data/tasks/distribution.rb
CHANGED
@@ -28,7 +28,7 @@ Jeweler::Tasks.new do |gem|
|
|
28
28
|
]
|
29
29
|
|
30
30
|
gem.add_dependency 'activerecord', '>= 1.15.6'
|
31
|
-
gem.add_dependency 'riddle', '>= 1.0.
|
31
|
+
gem.add_dependency 'riddle', '>= 1.0.1'
|
32
32
|
gem.add_dependency 'after_commit', '>= 1.0.2'
|
33
33
|
|
34
34
|
gem.post_install_message = <<-MESSAGE
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thinking-sphinx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Allan
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-16 00:00:00 +11:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.0.
|
33
|
+
version: 1.0.1
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: after_commit
|