thinking-sphinx 1.4.4 → 1.4.5

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.
@@ -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)