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.
Files changed (38) hide show
  1. data/LICENCE +20 -0
  2. data/README +60 -0
  3. data/lib/riddle.rb +26 -0
  4. data/lib/riddle/client.rb +639 -0
  5. data/lib/riddle/client/filter.rb +44 -0
  6. data/lib/riddle/client/message.rb +65 -0
  7. data/lib/riddle/client/response.rb +84 -0
  8. data/lib/test.rb +46 -0
  9. data/lib/thinking_sphinx.rb +102 -0
  10. data/lib/thinking_sphinx/active_record.rb +141 -0
  11. data/lib/thinking_sphinx/active_record/delta.rb +97 -0
  12. data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
  13. data/lib/thinking_sphinx/active_record/search.rb +50 -0
  14. data/lib/thinking_sphinx/association.rb +144 -0
  15. data/lib/thinking_sphinx/attribute.rb +284 -0
  16. data/lib/thinking_sphinx/configuration.rb +283 -0
  17. data/lib/thinking_sphinx/field.rb +200 -0
  18. data/lib/thinking_sphinx/index.rb +340 -0
  19. data/lib/thinking_sphinx/index/builder.rb +195 -0
  20. data/lib/thinking_sphinx/index/faux_column.rb +110 -0
  21. data/lib/thinking_sphinx/rails_additions.rb +56 -0
  22. data/lib/thinking_sphinx/search.rb +482 -0
  23. data/lib/thinking_sphinx/tasks.rb +86 -0
  24. data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +207 -0
  25. data/spec/unit/thinking_sphinx/active_record/has_many_association_spec.rb +53 -0
  26. data/spec/unit/thinking_sphinx/active_record/search_spec.rb +107 -0
  27. data/spec/unit/thinking_sphinx/active_record_spec.rb +236 -0
  28. data/spec/unit/thinking_sphinx/association_spec.rb +247 -0
  29. data/spec/unit/thinking_sphinx/attribute_spec.rb +360 -0
  30. data/spec/unit/thinking_sphinx/configuration_spec.rb +493 -0
  31. data/spec/unit/thinking_sphinx/field_spec.rb +219 -0
  32. data/spec/unit/thinking_sphinx/index/builder_spec.rb +33 -0
  33. data/spec/unit/thinking_sphinx/index/faux_column_spec.rb +68 -0
  34. data/spec/unit/thinking_sphinx/index_spec.rb +277 -0
  35. data/spec/unit/thinking_sphinx/search_spec.rb +190 -0
  36. data/spec/unit/thinking_sphinx_spec.rb +129 -0
  37. data/tasks/thinking_sphinx_tasks.rake +1 -0
  38. 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