freelancing-god-thinking-sphinx 1.2.4 → 1.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -146,3 +146,4 @@ Since I first released this library, there's been quite a few people who have su
146
146
  * Josh Kalderimis
147
147
  * J.D. Hollis
148
148
  * Jeffrey Chupp
149
+ * Rob Anderton
@@ -38,16 +38,16 @@ module ThinkingSphinx
38
38
  module Version #:nodoc:
39
39
  Major = 1
40
40
  Minor = 2
41
- Tiny = 4
41
+ Tiny = 5
42
42
 
43
43
  String = [Major, Minor, Tiny].join('.')
44
44
  end
45
-
45
+
46
46
  # A ConnectionError will get thrown when a connection to Sphinx can't be
47
47
  # made.
48
48
  class ConnectionError < StandardError
49
49
  end
50
-
50
+
51
51
  # A StaleIdsException is thrown by Collection.instances_from_matches if there
52
52
  # are records in Sphinx but not in the database, so the search can be retried.
53
53
  class StaleIdsException < StandardError
@@ -56,42 +56,42 @@ module ThinkingSphinx
56
56
  self.ids = ids
57
57
  end
58
58
  end
59
-
59
+
60
60
  # The collection of indexed models. Keep in mind that Rails lazily loads
61
61
  # its classes, so this may not actually be populated with _all_ the models
62
62
  # that have Sphinx indexes.
63
63
  def self.indexed_models
64
64
  @@indexed_models ||= []
65
65
  end
66
-
66
+
67
67
  def self.unique_id_expression(offset = nil)
68
68
  "* #{ThinkingSphinx.indexed_models.size} + #{offset || 0}"
69
69
  end
70
-
70
+
71
71
  # Check if index definition is disabled.
72
- #
72
+ #
73
73
  def self.define_indexes?
74
74
  @@define_indexes = true unless defined?(@@define_indexes)
75
75
  @@define_indexes == true
76
76
  end
77
-
77
+
78
78
  # Enable/disable indexes - you may want to do this while migrating data.
79
- #
79
+ #
80
80
  # ThinkingSphinx.define_indexes = false
81
- #
81
+ #
82
82
  def self.define_indexes=(value)
83
83
  @@define_indexes = value
84
84
  end
85
-
85
+
86
86
  @@deltas_enabled = nil
87
87
 
88
88
  # Check if delta indexing is enabled.
89
- #
89
+ #
90
90
  def self.deltas_enabled?
91
91
  @@deltas_enabled = (ThinkingSphinx::Configuration.environment != 'test') if @@deltas_enabled.nil?
92
92
  @@deltas_enabled
93
93
  end
94
-
94
+
95
95
  # Enable/disable all delta indexing.
96
96
  #
97
97
  # ThinkingSphinx.deltas_enabled = false
@@ -99,38 +99,38 @@ module ThinkingSphinx
99
99
  def self.deltas_enabled=(value)
100
100
  @@deltas_enabled = value
101
101
  end
102
-
102
+
103
103
  @@updates_enabled = nil
104
-
104
+
105
105
  # Check if updates are enabled. True by default, unless within the test
106
106
  # environment.
107
- #
107
+ #
108
108
  def self.updates_enabled?
109
109
  @@updates_enabled = (ThinkingSphinx::Configuration.environment != 'test') if @@updates_enabled.nil?
110
110
  @@updates_enabled
111
111
  end
112
-
112
+
113
113
  # Enable/disable updates to Sphinx
114
- #
114
+ #
115
115
  # ThinkingSphinx.updates_enabled = false
116
116
  #
117
117
  def self.updates_enabled=(value)
118
118
  @@updates_enabled = value
119
119
  end
120
-
120
+
121
121
  @@suppress_delta_output = false
122
-
122
+
123
123
  def self.suppress_delta_output?
124
124
  @@suppress_delta_output
125
125
  end
126
-
126
+
127
127
  def self.suppress_delta_output=(value)
128
128
  @@suppress_delta_output = value
129
129
  end
130
-
130
+
131
131
  # Checks to see if MySQL will allow simplistic GROUP BY statements. If not,
132
132
  # or if not using MySQL, this will return false.
133
- #
133
+ #
134
134
  def self.use_group_by_shortcut?
135
135
  !!(
136
136
  mysql? && ::ActiveRecord::Base.connection.select_all(
@@ -138,75 +138,65 @@ module ThinkingSphinx
138
138
  ).all? { |key,value| value.nil? || value[/ONLY_FULL_GROUP_BY/].nil? }
139
139
  )
140
140
  end
141
-
141
+
142
142
  @@remote_sphinx = false
143
-
143
+
144
144
  # An indication of whether Sphinx is running on a remote machine instead of
145
145
  # the same machine.
146
- #
146
+ #
147
147
  def self.remote_sphinx?
148
148
  @@remote_sphinx
149
149
  end
150
-
150
+
151
151
  # Tells Thinking Sphinx that Sphinx is running on a different machine, and
152
- # thus it can't reliably guess whether it is running or not (ie: the
152
+ # thus it can't reliably guess whether it is running or not (ie: the
153
153
  # #sphinx_running? method), and so just assumes it is.
154
- #
154
+ #
155
155
  # Useful for multi-machine deployments. Set it in your production.rb file.
156
- #
156
+ #
157
157
  # ThinkingSphinx.remote_sphinx = true
158
- #
158
+ #
159
159
  def self.remote_sphinx=(value)
160
160
  @@remote_sphinx = value
161
161
  end
162
-
162
+
163
163
  # Check if Sphinx is running. If remote_sphinx is set to true (indicating
164
164
  # Sphinx is on a different machine), this will always return true, and you
165
165
  # will have to handle any connection errors yourself.
166
- #
166
+ #
167
167
  def self.sphinx_running?
168
168
  remote_sphinx? || sphinx_running_by_pid?
169
169
  end
170
-
170
+
171
171
  # Check if Sphinx is actually running, provided the pid is on the same
172
172
  # machine as this code.
173
- #
173
+ #
174
174
  def self.sphinx_running_by_pid?
175
175
  !!sphinx_pid && pid_active?(sphinx_pid)
176
176
  end
177
-
177
+
178
178
  def self.sphinx_pid
179
- pid_file = ThinkingSphinx::Configuration.instance.pid_file
180
- cat_command = 'cat'
181
- return nil unless File.exists?(pid_file)
182
-
183
- if microsoft?
184
- pid_file.gsub!('/', '\\')
185
- cat_command = 'type'
179
+ if File.exists?(ThinkingSphinx::Configuration.instance.pid_file)
180
+ File.read(ThinkingSphinx::Configuration.instance.pid_file)[/\d+/]
181
+ else
182
+ nil
186
183
  end
187
-
188
- `#{cat_command} \"#{pid_file}\"`[/\d+/]
189
184
  end
190
-
185
+
191
186
  def self.pid_active?(pid)
192
- return true if microsoft?
193
-
194
- begin
195
- # In JRuby this returns -1 if the process doesn't exist
196
- Process.getpgid(pid.to_i) != -1
197
- rescue Exception => e
198
- false
199
- end
187
+ !!Process.kill(0, pid.to_i)
188
+ rescue Exception => e
189
+ false
200
190
  end
201
-
191
+
202
192
  def self.microsoft?
203
193
  RUBY_PLATFORM =~ /mswin/
204
194
  end
205
-
195
+
206
196
  def self.jruby?
207
197
  defined?(JRUBY_VERSION)
208
198
  end
209
-
199
+
210
200
  def self.mysql?
211
201
  ::ActiveRecord::Base.connection.class.name.demodulize == "MysqlAdapter" ||
212
202
  ::ActiveRecord::Base.connection.class.name.demodulize == "MysqlplusAdapter" || (
@@ -274,13 +274,18 @@ module ThinkingSphinx
274
274
  # nothing
275
275
  end
276
276
 
277
+ # Returns the unique integer id for the object. This method uses the
278
+ # attribute hash to get around ActiveRecord always mapping the #id method
279
+ # to whatever the real primary key is (which may be a unique string hash).
280
+ #
281
+ # @return [Integer] Unique record id for the purposes of Sphinx.
282
+ #
277
283
  def primary_key_for_sphinx
278
- self.send(self.class.primary_key_for_sphinx)
284
+ attributes[self.class.primary_key_for_sphinx.to_s]
279
285
  end
280
-
286
+
281
287
  def sphinx_document_id
282
- key = self.class.primary_key_for_sphinx
283
- self.attributes[key] * ThinkingSphinx.indexed_models.size +
288
+ primary_key_for_sphinx * ThinkingSphinx.indexed_models.size +
284
289
  ThinkingSphinx.indexed_models.index(self.class.source_of_sphinx_index.name)
285
290
  end
286
291
 
@@ -14,7 +14,9 @@ module ThinkingSphinx
14
14
 
15
15
  metaclass.instance_eval do
16
16
  define_method(method) do |*args|
17
- options = block.call(*args)
17
+ options = {:classes => classes_option}
18
+ options.merge! block.call(*args)
19
+
18
20
  ThinkingSphinx::Search.new(options)
19
21
  end
20
22
  end
@@ -134,3 +134,17 @@ end
134
134
  Class.extend(
135
135
  ThinkingSphinx::ClassAttributeMethods
136
136
  ) unless Class.respond_to?(:cattr_reader)
137
+
138
+ module ThinkingSphinx
139
+ module MetaClass
140
+ def metaclass
141
+ class << self
142
+ self
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ unless Object.new.respond_to?(:metaclass)
149
+ Object.send(:include, ThinkingSphinx::MetaClass)
150
+ end
@@ -187,6 +187,11 @@ module ThinkingSphinx
187
187
  ).first
188
188
  end
189
189
 
190
+ def search(*args)
191
+ merge_search ThinkingSphinx::Search.new(*args)
192
+ self
193
+ end
194
+
190
195
  private
191
196
 
192
197
  def config
@@ -444,6 +449,11 @@ module ThinkingSphinx
444
449
  def condition_filters
445
450
  (options[:conditions] || {}).collect { |attrib, value|
446
451
  if attributes.include?(attrib)
452
+ puts <<-MSG
453
+ Deprecation Warning: filters on attributes should be done using the :with
454
+ option, not :conditions. For example:
455
+ :with => {:#{attrib} => #{value.inspect}}
456
+ MSG
447
457
  Riddle::Client::Filter.new attrib.to_s, filter_value(value)
448
458
  else
449
459
  nil
@@ -619,7 +629,11 @@ module ThinkingSphinx
619
629
  end
620
630
 
621
631
  def add_scope(method, *args, &block)
622
- search = options[:classes].first.send(method, *args, &block)
632
+ merge_search options[:classes].first.send(method, *args, &block)
633
+ end
634
+
635
+ def merge_search(search)
636
+ search.args.each { |arg| args << arg }
623
637
 
624
638
  search.options.keys.each do |key|
625
639
  if HashOptions.include?(key)
@@ -628,6 +642,7 @@ module ThinkingSphinx
628
642
  elsif ArrayOptions.include?(key)
629
643
  options[key] ||= []
630
644
  options[key] += search.options[key]
645
+ options[key].uniq!
631
646
  else
632
647
  options[key] = search.options[key]
633
648
  end
@@ -57,10 +57,14 @@ describe ThinkingSphinx::ActiveRecord::Scopes do
57
57
  Alpha.sphinx_scope(:with_betas) { {:classes => [Beta]} }
58
58
  end
59
59
 
60
- it "should return a ThinkingSphinx object" do
60
+ it "should return a ThinkingSphinx::Search object" do
61
61
  Alpha.by_name('foo').should be_a(ThinkingSphinx::Search)
62
62
  end
63
63
 
64
+ it "should set the classes option" do
65
+ Alpha.by_name('foo').options[:classes].should == [Alpha]
66
+ end
67
+
64
68
  it "should be able to be called on a ThinkingSphinx::Search object" do
65
69
  search = ThinkingSphinx::Search.new(:classes => [Alpha])
66
70
  lambda {
@@ -326,4 +326,29 @@ describe "ThinkingSphinx::ActiveRecord" do
326
326
 
327
327
  (beta.id * model_count + offset).should == beta.sphinx_document_id
328
328
  end
329
+
330
+ describe '#primary_key_for_sphinx' do
331
+ before :each do
332
+ @person = Person.find(:first)
333
+ end
334
+
335
+ after :each do
336
+ Person.set_sphinx_primary_key nil
337
+ end
338
+
339
+ it "should return the id by default" do
340
+ @person.primary_key_for_sphinx.should == @person.id
341
+ end
342
+
343
+ it "should use the sphinx primary key to determine the value" do
344
+ Person.set_sphinx_primary_key :first_name
345
+ @person.primary_key_for_sphinx.should == @person.first_name
346
+ end
347
+
348
+ it "should not use accessor methods but the attributes hash" do
349
+ id = @person.id
350
+ @person.stub!(:id => 'unique_hash')
351
+ @person.primary_key_for_sphinx.should == id
352
+ end
353
+ end
329
354
  end
@@ -4,32 +4,32 @@ describe ThinkingSphinx::Configuration do
4
4
  describe "environment class method" do
5
5
  before :each do
6
6
  ThinkingSphinx::Configuration.send(:class_variable_set, :@@environment, nil)
7
-
7
+
8
8
  ENV["RAILS_ENV"] = nil
9
9
  end
10
-
10
+
11
11
  it "should use the Merb environment value if set" do
12
12
  unless defined?(Merb)
13
13
  module ::Merb; end
14
14
  end
15
-
15
+
16
16
  ThinkingSphinx::Configuration.stub_method(:defined? => true)
17
17
  Merb.stub!(:environment => "merb_production")
18
18
  ThinkingSphinx::Configuration.environment.should == "merb_production"
19
-
19
+
20
20
  Object.send(:remove_const, :Merb)
21
21
  end
22
-
22
+
23
23
  it "should use the Rails environment value if set" do
24
24
  ENV["RAILS_ENV"] = "rails_production"
25
25
  ThinkingSphinx::Configuration.environment.should == "rails_production"
26
26
  end
27
-
27
+
28
28
  it "should default to development" do
29
29
  ThinkingSphinx::Configuration.environment.should == "development"
30
30
  end
31
31
  end
32
-
32
+
33
33
  describe "parse_config method" do
34
34
  before :each do
35
35
  @settings = {
@@ -53,22 +53,22 @@ describe ThinkingSphinx::Configuration do
53
53
  "indexer_binary_name" => "sphinx-indexer"
54
54
  }
55
55
  }
56
-
56
+
57
57
  open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
58
58
  f.write YAML.dump(@settings)
59
59
  end
60
60
  end
61
-
61
+
62
62
  it "should use the accessors to set the configuration values" do
63
63
  config = ThinkingSphinx::Configuration.instance
64
64
  config.send(:parse_config)
65
-
65
+
66
66
  %w(config_file searchd_log_file query_log_file pid_file searchd_file_path
67
67
  address port searchd_binary_name indexer_binary_name).each do |key|
68
68
  config.send(key).should == @settings["development"][key]
69
69
  end
70
70
  end
71
-
71
+
72
72
  after :each do
73
73
  FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
74
74
  end
@@ -82,137 +82,143 @@ describe ThinkingSphinx::Configuration do
82
82
  ThinkingSphinx::Configuration.instance.app_root.should == "/here/somewhere"
83
83
  end
84
84
  end
85
-
85
+
86
86
  describe "initialisation" do
87
87
  it "should have a default bin_path of nothing" do
88
88
  ThinkingSphinx::Configuration.instance.bin_path.should == ""
89
89
  end
90
-
90
+
91
91
  it "should append a / to bin_path if one is supplied" do
92
92
  @settings = {
93
93
  "development" => {
94
94
  "bin_path" => "path/to/somewhere"
95
95
  }
96
96
  }
97
-
97
+
98
98
  open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
99
99
  f.write YAML.dump(@settings)
100
100
  end
101
-
101
+
102
102
  ThinkingSphinx::Configuration.instance.send(:parse_config)
103
103
  ThinkingSphinx::Configuration.instance.bin_path.should match(/\/$/)
104
+
105
+ FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
104
106
  end
105
107
  end
106
-
108
+
107
109
  describe "index options" do
108
110
  before :each do
109
111
  @settings = {
110
112
  "development" => {"disable_range" => true}
111
113
  }
112
-
114
+
113
115
  open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
114
116
  f.write YAML.dump(@settings)
115
117
  end
116
-
118
+
117
119
  @config = ThinkingSphinx::Configuration.instance
118
120
  @config.send(:parse_config)
119
121
  end
120
-
122
+
121
123
  it "should collect disable_range" do
122
124
  @config.index_options[:disable_range].should be_true
123
125
  end
126
+
127
+ after :each do
128
+ FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
129
+ end
124
130
  end
125
-
131
+
126
132
  describe "#load_models" do
127
133
  before :each do
128
134
  @config = ThinkingSphinx::Configuration.instance
129
135
  @config.model_directories = ['']
130
-
136
+
131
137
  @file_name = 'a.rb'
132
138
  @model_name_lower = 'a'
133
139
  @class_name = 'A'
134
-
140
+
135
141
  @file_name.stub!(:gsub).and_return(@model_name_lower)
136
142
  @model_name_lower.stub!(:camelize).and_return(@class_name)
137
143
  Dir.stub(:[]).and_return([@file_name])
138
144
  end
139
-
145
+
140
146
  it "should load the files by guessing the file name" do
141
147
  @class_name.should_receive(:constantize).and_return(true)
142
-
148
+
143
149
  @config.load_models
144
150
  end
145
-
151
+
146
152
  it "should not raise errors if the model name is nil" do
147
153
  @file_name.stub!(:gsub).and_return(nil)
148
-
154
+
149
155
  lambda {
150
156
  @config.load_models
151
157
  }.should_not raise_error
152
158
  end
153
-
159
+
154
160
  it "should not raise errors if the file name does not represent a class name" do
155
161
  @class_name.should_receive(:constantize).and_raise(NameError)
156
-
162
+
157
163
  lambda {
158
164
  @config.load_models
159
165
  }.should_not raise_error
160
166
  end
161
-
167
+
162
168
  it "should retry if the first pass fails and contains a directory" do
163
169
  @model_name_lower.stub!(:gsub!).and_return(true, nil)
164
170
  @class_name.stub(:constantize).and_raise(LoadError)
165
171
  @model_name_lower.should_receive(:camelize).twice
166
-
172
+
167
173
  lambda {
168
174
  @config.load_models
169
175
  }.should_not raise_error
170
176
  end
171
-
177
+
172
178
  it "should catch database errors with a warning" do
173
179
  @class_name.should_receive(:constantize).and_raise(Mysql::Error)
174
180
  @config.should_receive(:puts).with('Warning: Error loading a.rb')
175
-
181
+
176
182
  lambda {
177
183
  @config.load_models
178
184
  }.should_not raise_error
179
185
  end
180
186
  end
181
-
187
+
182
188
  it "should insert set index options into the configuration file" do
183
189
  config = ThinkingSphinx::Configuration.instance
184
190
  ThinkingSphinx::Configuration::IndexOptions.each do |option|
185
191
  config.index_options[option.to_sym] = "something"
186
192
  config.build
187
-
193
+
188
194
  file = open(config.config_file) { |f| f.read }
189
195
  file.should match(/#{option}\s+= something/)
190
-
196
+
191
197
  config.index_options[option.to_sym] = nil
192
198
  end
193
199
  end
194
-
200
+
195
201
  it "should insert set source options into the configuration file" do
196
202
  config = ThinkingSphinx::Configuration.instance
197
203
  ThinkingSphinx::Configuration::SourceOptions.each do |option|
198
204
  config.source_options[option.to_sym] = "something"
199
205
  config.build
200
-
206
+
201
207
  file = open(config.config_file) { |f| f.read }
202
208
  file.should match(/#{option}\s+= something/)
203
-
209
+
204
210
  config.source_options[option.to_sym] = nil
205
211
  end
206
212
  end
207
-
213
+
208
214
  it "should set any explicit prefixed or infixed fields" do
209
215
  file = open(ThinkingSphinx::Configuration.instance.config_file) { |f|
210
216
  f.read
211
217
  }
212
218
  file.should match(/prefix_fields\s+= city/)
213
- file.should match(/infix_fields\s+= state/)
219
+ file.should match(/infix_fields\s+= state/)
214
220
  end
215
-
221
+
216
222
  it "should not have prefix fields in indexes where nothing is set" do
217
223
  file = open(ThinkingSphinx::Configuration.instance.config_file) { |f|
218
224
  f.read
@@ -118,6 +118,18 @@ describe ThinkingSphinx::ActiveRecordStoreFullSTIClass do
118
118
  end
119
119
  end
120
120
 
121
+ describe ThinkingSphinx::MetaClass do
122
+ describe 'metaclass' do
123
+ it "should exist as an instance method in Object" do
124
+ Object.new.should respond_to('metaclass')
125
+ end
126
+
127
+ it "should return the meta/eigen/singleton class" do
128
+ Object.new.metaclass.should be_a(Class)
129
+ end
130
+ end
131
+ end
132
+
121
133
  class TestModel
122
134
  @@squares = 89
123
135
  @@circles = 43
@@ -50,6 +50,24 @@ describe ThinkingSphinx::Search do
50
50
  ThinkingSphinx::Search.new.foo
51
51
  }.should raise_error(NoMethodError)
52
52
  end
53
+
54
+ it "should accept sphinx scopes" do
55
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
56
+
57
+ lambda {
58
+ search.by_name('Pat')
59
+ }.should_not raise_error(NoMethodError)
60
+ end
61
+
62
+ it "should return itself when using a sphinx scope" do
63
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
64
+ search.by_name('Pat').object_id.should == search.object_id
65
+ end
66
+
67
+ it "should keep the same search object when chaining multiple scopes" do
68
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
69
+ search.by_name('Pat').ids_only.object_id.should == search.object_id
70
+ end
53
71
  end
54
72
 
55
73
  describe '.search' do
@@ -104,13 +122,16 @@ describe ThinkingSphinx::Search do
104
122
  @alpha_a, @alpha_b = Alpha.new, Alpha.new
105
123
  @beta_a, @beta_b = Beta.new, Beta.new
106
124
 
107
- @alpha_a.stub!(:id => 1); @alpha_b.stub!(:id => 2)
108
- @beta_a.stub!(:id => 1); @beta_b.stub!(:id => 2)
125
+ @alpha_a.stub! :id => 1, :attributes => {'id' => 1}
126
+ @alpha_b.stub! :id => 2, :attributes => {'id' => 2}
127
+ @beta_a.stub! :id => 1, :attributes => {'id' => 1}
128
+ @beta_b.stub! :id => 2, :attributes => {'id' => 2}
129
+
109
130
  @client.stub! :query => {
110
131
  :matches => minimal_result_hashes(@alpha_a, @beta_b, @alpha_b, @beta_a)
111
132
  }
112
- Alpha.stub!(:find => [@alpha_a, @alpha_b])
113
- Beta.stub!(:find => [@beta_a, @beta_b])
133
+ Alpha.stub! :find => [@alpha_a, @alpha_b]
134
+ Beta.stub! :find => [@beta_a, @beta_b]
114
135
  end
115
136
 
116
137
  it "should issue only one select per model" do
@@ -740,7 +761,7 @@ describe ThinkingSphinx::Search do
740
761
  describe '.each_with_groupby_and_count' do
741
762
  before :each do
742
763
  @alpha = Alpha.new
743
- @alpha.stub!(:id => 1)
764
+ @alpha.stub!(:id => 1, :attributes => {'id' => 1})
744
765
 
745
766
  @client.stub! :query => {
746
767
  :matches => [{
@@ -768,7 +789,7 @@ describe ThinkingSphinx::Search do
768
789
  describe '.each_with_weighting' do
769
790
  before :each do
770
791
  @alpha = Alpha.new
771
- @alpha.stub!(:id => 1)
792
+ @alpha.stub!(:id => 1, :attributes => {'id' => 1})
772
793
 
773
794
  @client.stub! :query => {
774
795
  :matches => [{
@@ -793,7 +814,7 @@ describe ThinkingSphinx::Search do
793
814
  describe '.each_with_*' do
794
815
  before :each do
795
816
  @alpha = Alpha.new
796
- @alpha.stub!(:id => 1)
817
+ @alpha.stub!(:id => 1, :attributes => {'id' => 1})
797
818
 
798
819
  @client.stub! :query => {
799
820
  :matches => [{
@@ -878,6 +899,47 @@ describe ThinkingSphinx::Search do
878
899
  @search.excerpt_for('string', Beta)
879
900
  end
880
901
  end
902
+
903
+ describe '#search' do
904
+ before :each do
905
+ @search = ThinkingSphinx::Search.new('word',
906
+ :conditions => {:field => 'field'},
907
+ :with => {:int => 5}
908
+ )
909
+ end
910
+
911
+ it "should return itself" do
912
+ @search.search.object_id.should == @search.object_id
913
+ end
914
+
915
+ it "should merge in arguments" do
916
+ @client.should_receive(:query) do |query, index, comments|
917
+ query.should == 'word more @field field'
918
+ end
919
+
920
+ @search.search('more').first
921
+ end
922
+
923
+ it "should merge conditions" do
924
+ @client.should_receive(:query) do |query, index, comments|
925
+ query.should match(/@name plato/)
926
+ query.should match(/@field field/)
927
+ end
928
+
929
+ @search.search(:conditions => {:name => 'plato'}).first
930
+ end
931
+
932
+ it "should merge filters" do
933
+ @search.search(:with => {:float => 1.5}).first
934
+
935
+ @client.filters.detect { |filter|
936
+ filter.attribute == 'float'
937
+ }.should_not be_nil
938
+ @client.filters.detect { |filter|
939
+ filter.attribute == 'int'
940
+ }.should_not be_nil
941
+ end
942
+ end
881
943
  end
882
944
 
883
945
  describe ThinkingSphinx::Search, "playing nice with Search model" do
@@ -4,7 +4,7 @@ module Riddle
4
4
  @configuration = configuration
5
5
  @path = path
6
6
  end
7
-
7
+
8
8
  def index
9
9
  cmd = "indexer --config #{@path} --all"
10
10
  cmd << " --rotate" if running?
@@ -15,7 +15,8 @@ module Riddle
15
15
  return if running?
16
16
 
17
17
  cmd = "searchd --pidfile --config #{@path}"
18
- `#{cmd}`
18
+ cmd = "start /B #{cmd}" if RUBY_PLATFORM =~ /mswin/
19
+ `#{cmd}`
19
20
 
20
21
  sleep(1)
21
22
 
@@ -26,19 +27,24 @@ module Riddle
26
27
 
27
28
  def stop
28
29
  return unless running?
29
- `kill #{pid}`
30
+ Process.kill('SIGTERM', pid.to_i)
31
+ rescue Errno::EINVAL
32
+ Process.kill('SIGKILL', pid.to_i)
30
33
  end
31
34
 
32
35
  def pid
33
- if File.exists?("#{@configuration.searchd.pid_file}")
34
- `cat #{@configuration.searchd.pid_file}`[/\d+/]
36
+ if File.exists?(@configuration.searchd.pid_file)
37
+ File.read(@configuration.searchd.pid_file)[/\d+/]
35
38
  else
36
39
  nil
37
40
  end
38
41
  end
39
42
 
40
43
  def running?
41
- pid && `ps #{pid} | wc -l`.to_i > 1
44
+ !!pid && !!Process.kill(0, pid.to_i)
45
+ rescue
46
+ false
42
47
  end
48
+
43
49
  end
44
50
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: freelancing-god-thinking-sphinx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.2.5
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-07-30 00:00:00 -07:00
12
+ date: 2009-08-02 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15