thinking-sphinx 1.4.4 → 1.4.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,13 +3,13 @@ Capistrano::Configuration.instance(:must_exist).load do
3
3
  namespace :install do
4
4
  desc <<-DESC
5
5
  Install Sphinx by source
6
-
6
+
7
7
  If Postgres is available, Sphinx will use it.
8
-
8
+
9
9
  If the variable :thinking_sphinx_configure_args is set, it will
10
10
  be passed to the Sphinx configure script. You can use this to
11
11
  install Sphinx in a non-standard location:
12
-
12
+
13
13
  set :thinking_sphinx_configure_args, "--prefix=$HOME/software"
14
14
  DESC
15
15
 
@@ -22,7 +22,7 @@ DESC
22
22
  rescue Capistrano::CommandError => e
23
23
  puts "Continuing despite error: #{e.message}"
24
24
  end
25
-
25
+
26
26
  args = []
27
27
  if with_postgres
28
28
  run "pg_config --pkgincludedir" do |channel, stream, data|
@@ -30,60 +30,60 @@ DESC
30
30
  end
31
31
  end
32
32
  args << fetch(:thinking_sphinx_configure_args, '')
33
-
33
+
34
34
  commands = <<-CMD
35
- wget -q http://www.sphinxsearch.com/downloads/sphinx-0.9.8.1.tar.gz >> sphinx.log
36
- tar xzvf sphinx-0.9.8.1.tar.gz
37
- cd sphinx-0.9.8.1
35
+ wget -q http://sphinxsearch.com/downloads/sphinx-0.9.9.tar.gz >> sphinx.log
36
+ tar xzvf sphinx-0.9.9.tar.gz
37
+ cd sphinx-0.9.9
38
38
  ./configure #{args.join(" ")}
39
39
  make
40
40
  #{try_sudo} make install
41
- rm -rf sphinx-0.9.8.1 sphinx-0.9.8.1.tar.gz
41
+ rm -rf sphinx-0.9.9 sphinx-0.9.9.tar.gz
42
42
  CMD
43
43
  run commands.split(/\n\s+/).join(" && ")
44
44
  end
45
-
46
- desc "Install Thinking Sphinx as a gem from GitHub"
45
+
46
+ desc "Install Thinking Sphinx as a gem"
47
47
  task :ts do
48
- run "#{try_sudo} gem install thinking-sphinx --source http://gemcutter.org"
48
+ run "#{try_sudo} gem install thinking-sphinx"
49
49
  end
50
50
  end
51
-
51
+
52
52
  desc "Generate the Sphinx configuration file"
53
53
  task :configure do
54
54
  rake "thinking_sphinx:configure"
55
55
  end
56
-
56
+
57
57
  desc "Index data"
58
58
  task :index do
59
59
  rake "thinking_sphinx:index"
60
60
  end
61
-
61
+
62
62
  desc "Start the Sphinx daemon"
63
63
  task :start do
64
64
  configure
65
65
  rake "thinking_sphinx:start"
66
66
  end
67
-
67
+
68
68
  desc "Stop the Sphinx daemon"
69
69
  task :stop do
70
70
  configure
71
71
  rake "thinking_sphinx:stop"
72
72
  end
73
-
73
+
74
74
  desc "Stop and then start the Sphinx daemon"
75
75
  task :restart do
76
76
  stop
77
77
  start
78
78
  end
79
-
79
+
80
80
  desc "Stop, re-index and then start the Sphinx daemon"
81
81
  task :rebuild do
82
82
  stop
83
83
  index
84
84
  start
85
85
  end
86
-
86
+
87
87
  desc "Add the shared folder for sphinx files"
88
88
  task :shared_sphinx_folder, :roles => :web do
89
89
  rails_env = fetch(:rails_env, "production")
@@ -1,6 +1,7 @@
1
1
  module ThinkingSphinx
2
2
  class Excerpter
3
- CoreMethods = %w( kind_of? object_id respond_to? should should_not stub! )
3
+ CoreMethods = %w( kind_of? object_id respond_to? respond_to_missing? should
4
+ should_not stub! )
4
5
  # Hide most methods, to allow them to be passed through to the instance.
5
6
  instance_methods.select { |method|
6
7
  method.to_s[/^__/].nil? && !CoreMethods.include?(method.to_s)
@@ -98,16 +98,15 @@ module ThinkingSphinx
98
98
 
99
99
  def translate(object, attribute_value)
100
100
  objects = source_objects(object)
101
- return nil if objects.nil? || objects.empty?
102
-
103
- if objects.length > 1
104
- objects.collect { |item| item.send(column.__name) }.detect { |item|
105
- item.to_crc32 == attribute_value
106
- }
107
- else
108
- method = value_source || column.__name
109
- objects.first.send(method)
110
- end
101
+ return if objects.blank?
102
+
103
+ method = value_source || column.__name
104
+ object = objects.one? ? objects.first : objects.detect { |item|
105
+ result = item.send(method)
106
+ result && result.to_crc32 == attribute_value
107
+ }
108
+
109
+ object.try(method)
111
110
  end
112
111
 
113
112
  def source_objects(object)
@@ -251,6 +251,16 @@ module ThinkingSphinx
251
251
  FauxColumn.new(assoc, *args)
252
252
  end
253
253
 
254
+ # Use this method to generate SQL for your attributes, conditions, etc.
255
+ # You can pass in as whatever ActiveRecord::Base.sanitize_sql accepts.
256
+ #
257
+ # where sanitize_sql(["active = ?", true])
258
+ # #=> WHERE active = 1
259
+ #
260
+ def sanitize_sql(*args)
261
+ @index.model.send(:sanitize_sql, *args)
262
+ end
263
+
254
264
  private
255
265
 
256
266
  def source
@@ -148,3 +148,34 @@ end
148
148
  unless Object.new.respond_to?(:singleton_class)
149
149
  Object.send(:include, ThinkingSphinx::SingletonClass)
150
150
  end
151
+
152
+ module ThinkingSphinx
153
+ module ObjectTry
154
+ def try(*a, &b)
155
+ if a.empty? && block_given?
156
+ yield self
157
+ else
158
+ __send__(*a, &b)
159
+ end
160
+ end
161
+ end
162
+
163
+ module NilClassTry
164
+ def try(*args)
165
+ nil
166
+ end
167
+ end
168
+ end
169
+
170
+ Object.send(:include, ThinkingSphinx::ObjectTry) unless Object.new.respond_to?(:try)
171
+ NilClass.send(:include, ThinkingSphinx::NilClassTry) unless nil.respond_to?(:try)
172
+
173
+ module ThinkingSphinx
174
+ module EnumerableOne
175
+ def one?(&block)
176
+ select(&block).size == 1
177
+ end
178
+ end
179
+ end
180
+
181
+ Enumerable.send(:include, ThinkingSphinx::EnumerableOne) unless [].respond_to?(:one?)
@@ -7,12 +7,12 @@ module ThinkingSphinx
7
7
  # search_for_ids methods will do the job in exactly the same manner when
8
8
  # called from a model.
9
9
  #
10
- class Search
10
+ class Search < Array
11
11
  CoreMethods = %w( == class class_eval extend frozen? id instance_eval
12
12
  instance_of? instance_values instance_variable_defined?
13
13
  instance_variable_get instance_variable_set instance_variables is_a?
14
- kind_of? member? method methods nil? object_id respond_to? send should
15
- type )
14
+ kind_of? member? method methods nil? object_id respond_to?
15
+ respond_to_missing? send should type )
16
16
  SafeMethods = %w( partition private_methods protected_methods
17
17
  public_methods send class )
18
18
 
@@ -5,15 +5,16 @@ namespace :thinking_sphinx do
5
5
  task :app_env do
6
6
  if defined?(RAILS_ROOT)
7
7
  Rake::Task[:environment].invoke
8
-
9
8
  if defined?(Rails.configuration)
10
9
  Rails.configuration.cache_classes = false
11
10
  else
12
11
  Rails::Initializer.run { |config| config.cache_classes = false }
13
12
  end
13
+ elsif defined?(Merb)
14
+ Rake::Task[:merb_env].invoke
15
+ elsif defined?(Sinatra)
16
+ Sinatra::Application.environment = ENV['RACK_ENV']
14
17
  end
15
-
16
- Rake::Task[:merb_env].invoke if defined?(Merb)
17
18
  end
18
19
 
19
20
  desc "Output the current Thinking Sphinx version"
@@ -17,27 +17,27 @@ describe "ThinkingSphinx::ActiveRecord::Delta" do
17
17
 
18
18
  describe "suspended_delta method" do
19
19
  before :each do
20
- ThinkingSphinx.deltas_enabled = true
20
+ ThinkingSphinx.deltas_suspended = false
21
21
  Person.sphinx_indexes.first.delta_object.stub!(:` => "")
22
22
  end
23
23
 
24
24
  it "should execute the argument block with deltas disabled" do
25
- ThinkingSphinx.should_receive(:deltas_enabled=).once.with(false)
26
- ThinkingSphinx.should_receive(:deltas_enabled=).once.with(true)
25
+ ThinkingSphinx.should_receive(:deltas_suspended=).once.with(true)
26
+ ThinkingSphinx.should_receive(:deltas_suspended=).once.with(false)
27
27
  lambda { Person.suspended_delta { raise 'i was called' } }.should(
28
28
  raise_error(Exception)
29
29
  )
30
30
  end
31
31
 
32
32
  it "should restore deltas_enabled to its original setting" do
33
- ThinkingSphinx.deltas_enabled = false
34
- ThinkingSphinx.should_receive(:deltas_enabled=).twice.with(false)
33
+ ThinkingSphinx.deltas_suspended = true
34
+ ThinkingSphinx.should_receive(:deltas_suspended=).twice.with(true)
35
35
  Person.suspended_delta { 'no-op' }
36
36
  end
37
37
 
38
38
  it "should restore deltas_enabled to its original setting even if there was an exception" do
39
- ThinkingSphinx.deltas_enabled = false
40
- ThinkingSphinx.should_receive(:deltas_enabled=).twice.with(false)
39
+ ThinkingSphinx.deltas_suspended = true
40
+ ThinkingSphinx.should_receive(:deltas_suspended=).twice.with(true)
41
41
  lambda { Person.suspended_delta { raise 'bad error' } }.should(
42
42
  raise_error(Exception)
43
43
  )
@@ -388,6 +388,10 @@ describe ThinkingSphinx::ActiveRecord do
388
388
  @person = Person.find(:first)
389
389
  end
390
390
 
391
+ after :each do
392
+ Person.clear_primary_key_for_sphinx
393
+ end
394
+
391
395
  after :each do
392
396
  Person.set_sphinx_primary_key nil
393
397
  end
@@ -81,9 +81,9 @@ describe ThinkingSphinx::Attribute do
81
81
 
82
82
  describe '#is_many?' do
83
83
  before :each do
84
- @assoc_a = stub('assoc', :is_many? => true)
85
- @assoc_b = stub('assoc', :is_many? => true)
86
- @assoc_c = stub('assoc', :is_many? => true)
84
+ @assoc_a = ThinkingSphinx::Association.new(nil, nil)
85
+ @assoc_b = ThinkingSphinx::Association.new(nil, nil)
86
+ @assoc_c = ThinkingSphinx::Association.new(nil, nil)
87
87
 
88
88
  @attribute = ThinkingSphinx::Attribute.new(
89
89
  @source, [ThinkingSphinx::Index::FauxColumn.new(:col_name)]
@@ -91,6 +91,9 @@ describe ThinkingSphinx::Attribute do
91
91
  @attribute.associations = {
92
92
  :a => @assoc_a, :b => @assoc_b, :c => @assoc_c
93
93
  }
94
+ @attribute.associations.values.each { |assoc|
95
+ assoc.stub!(:is_many? => true)
96
+ }
94
97
  end
95
98
 
96
99
  it "should return true if all associations return true to is_many?" do
@@ -30,7 +30,7 @@ describe ThinkingSphinx::AutoVersion do
30
30
  ThinkingSphinx::AutoVersion.detect
31
31
  end
32
32
 
33
- it "should require 1.10-beta if that is the detected version" do
33
+ it "should require 1.10-beta if using 1.10-beta compiled with id64 support" do
34
34
  ThinkingSphinx::AutoVersion.should_receive(:require).
35
35
  with('riddle/1.10')
36
36
 
@@ -38,15 +38,23 @@ describe ThinkingSphinx::AutoVersion do
38
38
  ThinkingSphinx::AutoVersion.detect
39
39
  end
40
40
 
41
- it "should output a warning if the detected version is something else" do
42
- STDERR.should_receive(:puts).twice
41
+ it "should require 2.0.1 if using Sphinx 2.0.1 beta" do
42
+ ThinkingSphinx::AutoVersion.should_receive(:require).
43
+ with('riddle/2.0.1')
44
+
45
+ @config.stub!(:version => '2.0.1-beta')
46
+ ThinkingSphinx::AutoVersion.detect
47
+ end
48
+
49
+ it "should output a warning if the detected version is unsupported" do
50
+ STDERR.should_receive(:puts).with(/unsupported/i)
43
51
 
44
52
  @config.stub!(:version => '0.9.7')
45
53
  ThinkingSphinx::AutoVersion.detect
46
54
  end
47
55
 
48
56
  it "should output a warning if the version cannot be determined" do
49
- STDERR.should_receive(:puts)
57
+ STDERR.should_receive(:puts).at_least(:once)
50
58
 
51
59
  @config.stub!(:version => nil)
52
60
  ThinkingSphinx::AutoVersion.detect
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe ThinkingSphinx::Configuration do
4
4
  describe "environment class method" do
5
5
  before :each do
6
- Thread.current[:thinking_sphinx_environment] = nil
6
+ ThinkingSphinx::Configuration.reset_environment
7
7
 
8
8
  ENV["RAILS_ENV"] = nil
9
9
  end
@@ -41,6 +41,7 @@ describe ThinkingSphinx::Context do
41
41
  }.should_not raise_error
42
42
  end
43
43
 
44
+ # Fails in Ruby 1.9 (or maybe it's an RSpec update). Not sure why.
44
45
  it "should retry if the first pass fails and contains a directory" do
45
46
  @model_name_lower.stub!(:gsub!).and_return(true, nil)
46
47
  @class_name.stub(:constantize).and_raise(LoadError)
@@ -98,14 +98,6 @@ describe ThinkingSphinx::FacetSearch do
98
98
  :classes => [Person], :facets => :state
99
99
  )
100
100
  end
101
-
102
- it "should handle multiple facets" do
103
- ThinkingSphinx.should_receive(:search).twice.and_return(search)
104
-
105
- ThinkingSphinx::FacetSearch.new(
106
- :classes => [Person], :facets => [:state, :city]
107
- )
108
- end
109
101
  end
110
102
 
111
103
  describe "empty result set for attributes" do
@@ -311,6 +311,18 @@ describe ThinkingSphinx::Facet do
311
311
  ThinkingSphinx::Facet.new(field).value(friendship, {'name_facet' => 'buried'.to_crc32}).
312
312
  should == 'buried'
313
313
  end
314
+
315
+ it "should not error with multi-level association values containing a nil value" do
316
+ person = Person.find(:first)
317
+ tag = person.tags.build(:name => nil)
318
+ tag = person.tags.build(:name => "buried")
319
+ friendship = Friendship.new(:person => person)
320
+
321
+ field = ThinkingSphinx::Field.new(
322
+ @source, ThinkingSphinx::Index::FauxColumn.new(:person, :tags, :name)
323
+ )
324
+ lambda{ThinkingSphinx::Facet.new(field).value(friendship, {'name_facet' => 'buried'.to_crc32})}.should_not raise_error
325
+ end
314
326
  end
315
327
 
316
328
  describe 'for float attributes' do
@@ -90,9 +90,9 @@ describe ThinkingSphinx::Field do
90
90
 
91
91
  describe "is_many? method" do
92
92
  before :each do
93
- @assoc_a = stub('assoc', :is_many? => true)
94
- @assoc_b = stub('assoc', :is_many? => true)
95
- @assoc_c = stub('assoc', :is_many? => true)
93
+ @assoc_a = ThinkingSphinx::Association.new(nil, nil)
94
+ @assoc_b = ThinkingSphinx::Association.new(nil, nil)
95
+ @assoc_c = ThinkingSphinx::Association.new(nil, nil)
96
96
 
97
97
  @field = ThinkingSphinx::Field.new(
98
98
  @source, [ThinkingSphinx::Index::FauxColumn.new(:col_name)]
@@ -100,6 +100,9 @@ describe ThinkingSphinx::Field do
100
100
  @field.associations = {
101
101
  :a => @assoc_a, :b => @assoc_b, :c => @assoc_c
102
102
  }
103
+ @field.associations.values.each { |assoc|
104
+ assoc.stub!(:is_many? => true)
105
+ }
103
106
  end
104
107
 
105
108
  it "should return true if all associations return true to is_many?" do
@@ -492,4 +492,17 @@ describe ThinkingSphinx::Index::Builder do
492
492
  index.name.should == 'custom'
493
493
  end
494
494
  end
495
+
496
+ describe "sanitize_sql" do
497
+ def index
498
+ @index ||= ThinkingSphinx::Index::Builder.generate(Person) do
499
+ indexes first_name, last_name
500
+ where sanitize_sql(["gender = ?", "female"])
501
+ end
502
+ end
503
+
504
+ it "should be aliased to ActiveRecord::Base.sanitize_sql" do
505
+ index.sources.first.conditions.first.should == index.model.send(:sanitize_sql, ["gender = ?", "female"])
506
+ end
507
+ end
495
508
  end
@@ -914,7 +914,8 @@ describe ThinkingSphinx::Search do
914
914
  it "should not add excerpts method if objects already have one" do
915
915
  @search.last.excerpts.should_not be_a(ThinkingSphinx::Excerpter)
916
916
  end
917
-
917
+
918
+ # Fails in Ruby 1.9 (or maybe it's an RSpec update). Not sure why.
918
919
  it "should set up the excerpter with the instances and search" do
919
920
  [@alpha_a, @beta_b, @alpha_b, @beta_a].each do |object|
920
921
  ThinkingSphinx::Excerpter.should_receive(:new).with(@search, object)