ryanb-thinking_sphinx 0.9.8
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/LICENCE +20 -0
- data/README +60 -0
- data/lib/riddle.rb +26 -0
- data/lib/riddle/client.rb +639 -0
- data/lib/riddle/client/filter.rb +44 -0
- data/lib/riddle/client/message.rb +65 -0
- data/lib/riddle/client/response.rb +84 -0
- data/lib/test.rb +46 -0
- data/lib/thinking_sphinx.rb +102 -0
- data/lib/thinking_sphinx/active_record.rb +141 -0
- data/lib/thinking_sphinx/active_record/delta.rb +97 -0
- data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
- data/lib/thinking_sphinx/active_record/search.rb +50 -0
- data/lib/thinking_sphinx/association.rb +144 -0
- data/lib/thinking_sphinx/attribute.rb +284 -0
- data/lib/thinking_sphinx/configuration.rb +283 -0
- data/lib/thinking_sphinx/field.rb +200 -0
- data/lib/thinking_sphinx/index.rb +340 -0
- data/lib/thinking_sphinx/index/builder.rb +195 -0
- data/lib/thinking_sphinx/index/faux_column.rb +110 -0
- data/lib/thinking_sphinx/rails_additions.rb +56 -0
- data/lib/thinking_sphinx/search.rb +482 -0
- data/lib/thinking_sphinx/tasks.rb +86 -0
- data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +207 -0
- data/spec/unit/thinking_sphinx/active_record/has_many_association_spec.rb +53 -0
- data/spec/unit/thinking_sphinx/active_record/search_spec.rb +107 -0
- data/spec/unit/thinking_sphinx/active_record_spec.rb +236 -0
- data/spec/unit/thinking_sphinx/association_spec.rb +247 -0
- data/spec/unit/thinking_sphinx/attribute_spec.rb +360 -0
- data/spec/unit/thinking_sphinx/configuration_spec.rb +493 -0
- data/spec/unit/thinking_sphinx/field_spec.rb +219 -0
- data/spec/unit/thinking_sphinx/index/builder_spec.rb +33 -0
- data/spec/unit/thinking_sphinx/index/faux_column_spec.rb +68 -0
- data/spec/unit/thinking_sphinx/index_spec.rb +277 -0
- data/spec/unit/thinking_sphinx/search_spec.rb +190 -0
- data/spec/unit/thinking_sphinx_spec.rb +129 -0
- data/tasks/thinking_sphinx_tasks.rake +1 -0
- metadata +103 -0
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
namespace :thinking_sphinx do
|
4
|
+
task :app_env do
|
5
|
+
Rake::Task[:environment].invoke if defined?(RAILS_ROOT)
|
6
|
+
Rake::Task[:merb_env].invoke if defined?(Merb)
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Start a Sphinx searchd daemon using Thinking Sphinx's settings"
|
10
|
+
task :start => :app_env do
|
11
|
+
config = ThinkingSphinx::Configuration.new
|
12
|
+
|
13
|
+
FileUtils.mkdir_p config.searchd_file_path
|
14
|
+
raise RuntimeError, "searchd is already running." if sphinx_running?
|
15
|
+
|
16
|
+
Dir["#{config.searchd_file_path}/*.spl"].each { |file| File.delete(file) }
|
17
|
+
|
18
|
+
cmd = "searchd --config #{config.config_file}"
|
19
|
+
puts cmd
|
20
|
+
system cmd
|
21
|
+
|
22
|
+
sleep(2)
|
23
|
+
|
24
|
+
if sphinx_running?
|
25
|
+
puts "Started successfully (pid #{sphinx_pid})."
|
26
|
+
else
|
27
|
+
puts "Failed to start searchd daemon. Check #{config.searchd_log_file}."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Stop Sphinx using Thinking Sphinx's settings"
|
32
|
+
task :stop => :app_env do
|
33
|
+
raise RuntimeError, "searchd is not running." unless sphinx_running?
|
34
|
+
pid = sphinx_pid
|
35
|
+
system "kill #{pid}"
|
36
|
+
puts "Stopped search daemon (pid #{pid})."
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Restart Sphinx"
|
40
|
+
task :restart => [:app_env, :stop, :start]
|
41
|
+
|
42
|
+
desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
|
43
|
+
task :configure => :app_env do
|
44
|
+
ThinkingSphinx::Configuration.new.build
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Index data for Sphinx using Thinking Sphinx's settings"
|
48
|
+
task :index => [:app_env, :configure] do
|
49
|
+
config = ThinkingSphinx::Configuration.new
|
50
|
+
|
51
|
+
FileUtils.mkdir_p config.searchd_file_path
|
52
|
+
cmd = "indexer --config #{config.config_file} --all"
|
53
|
+
cmd << " --rotate" if sphinx_running?
|
54
|
+
puts cmd
|
55
|
+
system cmd
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
namespace :ts do
|
60
|
+
desc "Start a Sphinx searchd daemon using Thinking Sphinx's settings"
|
61
|
+
task :start => "thinking_sphinx:start"
|
62
|
+
desc "Stop Sphinx using Thinking Sphinx's settings"
|
63
|
+
task :stop => "thinking_sphinx:stop"
|
64
|
+
desc "Index data for Sphinx using Thinking Sphinx's settings"
|
65
|
+
task :in => "thinking_sphinx:index"
|
66
|
+
desc "Index data for Sphinx using Thinking Sphinx's settings"
|
67
|
+
task :index => "thinking_sphinx:index"
|
68
|
+
desc "Restart Sphinx"
|
69
|
+
task :restart => "thinking_sphinx:restart"
|
70
|
+
desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
|
71
|
+
task :config => "thinking_sphinx:configure"
|
72
|
+
end
|
73
|
+
|
74
|
+
def sphinx_pid
|
75
|
+
config = ThinkingSphinx::Configuration.new
|
76
|
+
|
77
|
+
if File.exists?(config.pid_file)
|
78
|
+
`cat #{config.pid_file}`[/\d+/]
|
79
|
+
else
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def sphinx_running?
|
85
|
+
sphinx_pid && `ps -p #{sphinx_pid} | wc -l`.to_i > 1
|
86
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe "ThinkingSphinx::ActiveRecord::Delta" do
|
4
|
+
describe "after_commit callback" do
|
5
|
+
before :each do
|
6
|
+
Person.stub_method(:write_inheritable_array => true)
|
7
|
+
end
|
8
|
+
|
9
|
+
# This spec only passes with ActiveRecord 2.0.2 or earlier.
|
10
|
+
# it "should add callbacks" do
|
11
|
+
# Person.after_commit :toggle_delta
|
12
|
+
#
|
13
|
+
# Person.should have_received(:write_inheritable_array).with(
|
14
|
+
# :after_commit, [:toggle_delta]
|
15
|
+
# )
|
16
|
+
# end
|
17
|
+
|
18
|
+
it "should have an after_commit method by default" do
|
19
|
+
Person.instance_methods.should include("after_commit")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "save_with_after_commit_callback method" do
|
24
|
+
before :each do
|
25
|
+
@person = Person.new
|
26
|
+
@person.stub_methods(
|
27
|
+
:save_without_after_commit_callback => true,
|
28
|
+
:callback => true
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should call the normal save method" do
|
33
|
+
@person.save
|
34
|
+
|
35
|
+
@person.should have_received(:save_without_after_commit_callback)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should call the callbacks if the save was successful" do
|
39
|
+
@person.save
|
40
|
+
|
41
|
+
@person.should have_received(:callback).with(:after_commit)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "shouldn't call the callbacks if the save failed" do
|
45
|
+
@person.stub_method(:save_without_after_commit_callback => false)
|
46
|
+
|
47
|
+
@person.save
|
48
|
+
|
49
|
+
@person.should_not have_received(:callback)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return the normal save's result" do
|
53
|
+
@person.save.should be_true
|
54
|
+
|
55
|
+
@person.stub_method(:save_without_after_commit_callback => false)
|
56
|
+
|
57
|
+
@person.save.should be_false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "save_with_after_commit_callback! method" do
|
62
|
+
before :each do
|
63
|
+
@person = Person.new
|
64
|
+
@person.stub_methods(
|
65
|
+
:save_without_after_commit_callback! => true,
|
66
|
+
:callback => true
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should call the normal save! method" do
|
71
|
+
@person.save!
|
72
|
+
|
73
|
+
@person.should have_received(:save_without_after_commit_callback!)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should call the callbacks if the save! was successful" do
|
77
|
+
@person.save!
|
78
|
+
|
79
|
+
@person.should have_received(:callback).with(:after_commit)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "shouldn't call the callbacks if the save! failed" do
|
83
|
+
@person.stub_method(:save_without_after_commit_callback! => false)
|
84
|
+
|
85
|
+
@person.save!
|
86
|
+
|
87
|
+
@person.should_not have_received(:callback)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should return the normal save's result" do
|
91
|
+
@person.save!.should be_true
|
92
|
+
|
93
|
+
@person.stub_method(:save_without_after_commit_callback! => false)
|
94
|
+
|
95
|
+
@person.save!.should be_false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "destroy_with_after_commit_callback method" do
|
100
|
+
before :each do
|
101
|
+
@person = Person.new
|
102
|
+
@person.stub_methods(
|
103
|
+
:destroy_without_after_commit_callback => true,
|
104
|
+
:callback => true
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should call the normal destroy method" do
|
109
|
+
@person.destroy
|
110
|
+
|
111
|
+
@person.should have_received(:destroy_without_after_commit_callback)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should call the callbacks if the destroy was successful" do
|
115
|
+
@person.destroy
|
116
|
+
|
117
|
+
@person.should have_received(:callback).with(:after_commit)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "shouldn't call the callbacks if the destroy failed" do
|
121
|
+
@person.stub_method(:destroy_without_after_commit_callback => false)
|
122
|
+
|
123
|
+
@person.destroy
|
124
|
+
|
125
|
+
@person.should_not have_received(:callback)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should return the normal save's result" do
|
129
|
+
@person.destroy.should be_true
|
130
|
+
|
131
|
+
@person.stub_method(:destroy_without_after_commit_callback => false)
|
132
|
+
|
133
|
+
@person.destroy.should be_false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "toggle_delta method" do
|
138
|
+
it "should set the delta value to true" do
|
139
|
+
@person = Person.new
|
140
|
+
|
141
|
+
@person.delta.should be_false
|
142
|
+
@person.send(:toggle_delta)
|
143
|
+
@person.delta.should be_true
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "index_delta method" do
|
148
|
+
before :each do
|
149
|
+
ThinkingSphinx::Configuration.stub_method(:environment => "spec")
|
150
|
+
ThinkingSphinx.stub_method(:deltas_enabled? => true)
|
151
|
+
|
152
|
+
@person = Person.new
|
153
|
+
@person.stub_method(:system => true, :in_core_index? => false)
|
154
|
+
|
155
|
+
@client = Riddle::Client.stub_instance(:update => true)
|
156
|
+
Riddle::Client.stub_method(:new => @client)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "shouldn't index if delta indexing is disabled" do
|
160
|
+
ThinkingSphinx.stub_method(:deltas_enabled? => false)
|
161
|
+
|
162
|
+
@person.send(:index_delta)
|
163
|
+
|
164
|
+
@person.should_not have_received(:system)
|
165
|
+
@client.should_not have_received(:update)
|
166
|
+
end
|
167
|
+
|
168
|
+
it "shouldn't index if index updating is disabled" do
|
169
|
+
ThinkingSphinx.stub_method(:updates_enabled? => false)
|
170
|
+
|
171
|
+
@person.send(:index_delta)
|
172
|
+
|
173
|
+
@person.should_not have_received(:system)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "shouldn't index if the environment is 'test'" do
|
177
|
+
ThinkingSphinx.unstub_method(:deltas_enabled?)
|
178
|
+
ThinkingSphinx::Configuration.stub_method(:environment => "test")
|
179
|
+
|
180
|
+
@person.send(:index_delta)
|
181
|
+
|
182
|
+
@person.should_not have_received(:system)
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should call indexer for the delta index" do
|
186
|
+
@person.send(:index_delta)
|
187
|
+
|
188
|
+
@person.should have_received(:system).with(
|
189
|
+
"indexer --config #{ThinkingSphinx::Configuration.new.config_file} --rotate person_delta"
|
190
|
+
)
|
191
|
+
end
|
192
|
+
|
193
|
+
it "shouldn't update the deleted attribute if not in the index" do
|
194
|
+
@person.send(:index_delta)
|
195
|
+
|
196
|
+
@client.should_not have_received(:update)
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should update the deleted attribute if in the core index" do
|
200
|
+
@person.stub_method(:in_core_index? => true)
|
201
|
+
|
202
|
+
@person.send(:index_delta)
|
203
|
+
|
204
|
+
@client.should have_received(:update)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe 'ThinkingSphinx::ActiveRecord::HasManyAssociation' do
|
4
|
+
describe "search method" do
|
5
|
+
before :each do
|
6
|
+
Friendship.stub_method(:search => true)
|
7
|
+
|
8
|
+
@person = Person.find(:first)
|
9
|
+
@index = Friendship.indexes.first
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should raise an error if the required attribute doesn't exist" do
|
13
|
+
@index.stub_method(:attributes => [])
|
14
|
+
|
15
|
+
lambda { @person.friendships.search "test" }.should raise_error(RuntimeError)
|
16
|
+
|
17
|
+
@index.unstub_method(:attributes)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should add a filter for the attribute into a normal search call" do
|
21
|
+
@person.friendships.search "test"
|
22
|
+
|
23
|
+
Friendship.should have_received(:search).with(
|
24
|
+
"test", :with => {:person_id => @person.id}
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "search method for has_many :through" do
|
30
|
+
before :each do
|
31
|
+
Person.stub_method(:search => true)
|
32
|
+
|
33
|
+
@person = Person.find(:first)
|
34
|
+
@index = Person.indexes.first
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should raise an error if the required attribute doesn't exist" do
|
38
|
+
@index.stub_method(:attributes => [])
|
39
|
+
|
40
|
+
lambda { @person.friends.search "test" }.should raise_error(RuntimeError)
|
41
|
+
|
42
|
+
@index.unstub_method(:attributes)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should add a filter for the attribute into a normal search call" do
|
46
|
+
@person.friends.search "test"
|
47
|
+
|
48
|
+
Person.should have_received(:search).with(
|
49
|
+
"test", :with => {:friendly_ids => @person.id}
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe "ThinkingSphinx::ActiveRecord::Search" do
|
4
|
+
it "should add search_for_ids to ActiveRecord::Base" do
|
5
|
+
ActiveRecord::Base.methods.should include("search_for_ids")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should add search_for_ids to ActiveRecord::Base" do
|
9
|
+
ActiveRecord::Base.methods.should include("search")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should add search_count to ActiveRecord::Base" do
|
13
|
+
ActiveRecord::Base.methods.should include("search_count")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should add search_for_id to ActiveRecord::Base" do
|
17
|
+
ActiveRecord::Base.methods.should include("search_for_id")
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "search_for_ids method" do
|
21
|
+
before :each do
|
22
|
+
ThinkingSphinx::Search.stub_method(:search_for_ids => true)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should call ThinkingSphinx::Search#search_for_ids with the class option set" do
|
26
|
+
Person.search_for_ids("search")
|
27
|
+
|
28
|
+
ThinkingSphinx::Search.should have_received(:search_for_ids).with(
|
29
|
+
"search", :class => Person
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should override the class option" do
|
34
|
+
Person.search_for_ids("search", :class => Friendship)
|
35
|
+
|
36
|
+
ThinkingSphinx::Search.should have_received(:search_for_ids).with(
|
37
|
+
"search", :class => Person
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "search method" do
|
43
|
+
before :each do
|
44
|
+
ThinkingSphinx::Search.stub_method(:search => true)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should call ThinkingSphinx::Search#search with the class option set" do
|
48
|
+
Person.search("search")
|
49
|
+
|
50
|
+
ThinkingSphinx::Search.should have_received(:search).with(
|
51
|
+
"search", :class => Person
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should override the class option" do
|
56
|
+
Person.search("search", :class => Friendship)
|
57
|
+
|
58
|
+
ThinkingSphinx::Search.should have_received(:search).with(
|
59
|
+
"search", :class => Person
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "search_for_id method" do
|
65
|
+
before :each do
|
66
|
+
ThinkingSphinx::Search.stub_method(:search_for_id => true)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should call ThinkingSphinx::Search#search with the class option set" do
|
70
|
+
Person.search_for_id(10)
|
71
|
+
|
72
|
+
ThinkingSphinx::Search.should have_received(:search_for_id).with(
|
73
|
+
10, :class => Person
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should override the class option" do
|
78
|
+
Person.search_for_id(10, :class => Friendship)
|
79
|
+
|
80
|
+
ThinkingSphinx::Search.should have_received(:search_for_id).with(
|
81
|
+
10, :class => Person
|
82
|
+
)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "search_count method" do
|
87
|
+
before :each do
|
88
|
+
ThinkingSphinx::Search.stub_method(:count => true)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should call ThinkingSphinx::Search#search with the class option set" do
|
92
|
+
Person.search_count("search")
|
93
|
+
|
94
|
+
ThinkingSphinx::Search.should have_received(:count).with(
|
95
|
+
"search", :class => Person
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should override the class option" do
|
100
|
+
Person.search_count("search", :class => Friendship)
|
101
|
+
|
102
|
+
ThinkingSphinx::Search.should have_received(:count).with(
|
103
|
+
"search", :class => Person
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|