thinking-sphinx 1.3.18 → 1.3.19

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/README.textile CHANGED
@@ -165,3 +165,10 @@ Since I first released this library, there's been quite a few people who have su
165
165
  * Tomáš Pospíšek
166
166
  * Tom Stuart
167
167
  * James Brooks
168
+ * Mark Dodwell
169
+ * Frédéric Malamitsas
170
+ * Jon Gubman
171
+ * Michael Schuerig
172
+ * Ben Hutton
173
+ * Alfonso Jiménez
174
+ * Szymon Nowak
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.18
1
+ 1.3.19
@@ -27,7 +27,7 @@ Feature: Search and browse models by their defined facets
27
27
  And I should have the facet State
28
28
  And I should have the facet Age
29
29
 
30
- Scenario: Requseting float facets
30
+ Scenario: Requesting float facets
31
31
  Given Sphinx is running
32
32
  And I am searching on alphas
33
33
  When I am requesting facet results
@@ -80,3 +80,11 @@ Feature: Search and browse models by their defined facets
80
80
  And I am searching on posts
81
81
  When I am requesting facet results
82
82
  Then the Comment Ids facet should have 9 keys
83
+
84
+ Scenario: Requesting facets from a subclass
85
+ Given Sphinx is running
86
+ And I am searching on animals
87
+ When I am requesting facet results
88
+ And I want classes included
89
+ Then I should have the facet Class
90
+
@@ -40,3 +40,11 @@ Feature: Sphinx Scopes
40
40
  When I use the with_first_name scope set to "Andrew"
41
41
  And I am retrieving the scoped result count
42
42
  Then I should get a value of 7
43
+
44
+ Scenario: Counts with scopes and additional query terms
45
+ Given Sphinx is running
46
+ And I am searching on people
47
+ When I use the with_first_name scope set to "Andrew"
48
+ And I am retrieving the scoped result count for "Byrne"
49
+ Then I should get a value of 1
50
+
@@ -13,3 +13,7 @@ end
13
13
  When /^I am retrieving the scoped result count$/ do
14
14
  @results = results.search_count
15
15
  end
16
+
17
+ When /^I am retrieving the scoped result count for "([^"]*)"$/ do |query|
18
+ @results = results.search_count query
19
+ end
@@ -1,8 +1,12 @@
1
1
  require 'thinking_sphinx/test'
2
2
 
3
- class Cucumber::ThinkingSphinx::ExternalWorld
4
- def initialize(suppress_delta_output = true)
5
- ::ThinkingSphinx::Test.init
6
- ::ThinkingSphinx::Test.start_with_autostop
3
+ module Cucumber
4
+ module ThinkingSphinx
5
+ class ExternalWorld
6
+ def initialize(suppress_delta_output = true)
7
+ ::ThinkingSphinx::Test.init
8
+ ::ThinkingSphinx::Test.start_with_autostop
9
+ end
10
+ end
7
11
  end
8
12
  end
@@ -322,6 +322,10 @@ module ThinkingSphinx
322
322
  end
323
323
  end
324
324
 
325
+ attr_accessor :excerpts
326
+ attr_accessor :sphinx_attributes
327
+ attr_accessor :matching_fields
328
+
325
329
  def in_index?(suffix)
326
330
  self.class.search_for_id self.sphinx_document_id, sphinx_index_name(suffix)
327
331
  end
@@ -12,7 +12,9 @@ module ThinkingSphinx
12
12
  def self.detect(model)
13
13
  case model.connection.class.name
14
14
  when "ActiveRecord::ConnectionAdapters::MysqlAdapter",
15
- "ActiveRecord::ConnectionAdapters::MysqlplusAdapter"
15
+ "ActiveRecord::ConnectionAdapters::MysqlplusAdapter",
16
+ "ActiveRecord::ConnectionAdapters::Mysql2Adapter",
17
+ "ActiveRecord::ConnectionAdapters::NullDBAdapter"
16
18
  ThinkingSphinx::MysqlAdapter.new model
17
19
  when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
18
20
  ThinkingSphinx::PostgreSQLAdapter.new model
@@ -8,8 +8,9 @@ module ThinkingSphinx
8
8
  "class_crc"
9
9
  end
10
10
 
11
- def value(object, attribute_value)
12
- object.class.name
11
+ def value(object, attribute_hash)
12
+ crc = attribute_hash['class_crc']
13
+ ThinkingSphinx::Configuration.instance.models_by_crc[crc]
13
14
  end
14
15
  end
15
16
  end
@@ -44,7 +44,7 @@ module ThinkingSphinx
44
44
  config = ThinkingSphinx::Configuration.instance
45
45
  rotate = ThinkingSphinx.sphinx_running? ? "--rotate" : ""
46
46
 
47
- output = `#{config.bin_path}#{config.indexer_binary_name} --config '#{config.config_file}' #{rotate} #{model.delta_index_names.join(' ')}`
47
+ output = `#{config.bin_path}#{config.indexer_binary_name} --config "#{config.config_file}" #{rotate} #{model.delta_index_names.join(' ')}`
48
48
  puts(output) unless ThinkingSphinx.suppress_delta_output?
49
49
  end
50
50
 
@@ -71,7 +71,12 @@ module ThinkingSphinx
71
71
  @property.is_a?(Field) ? :string : @property.type
72
72
  end
73
73
 
74
- def value(object, attribute_value)
74
+ def float?
75
+ @property.type == :float
76
+ end
77
+
78
+ def value(object, attribute_hash)
79
+ attribute_value = attribute_hash['@groupby']
75
80
  return translate(object, attribute_value) if translate? || float?
76
81
 
77
82
  case @property.type
@@ -117,9 +122,5 @@ module ThinkingSphinx
117
122
  def column
118
123
  @property.columns.first
119
124
  end
120
-
121
- def float?
122
- @property.type == :float
123
- end
124
125
  end
125
126
  end
@@ -44,23 +44,21 @@ module ThinkingSphinx
44
44
  end
45
45
 
46
46
  def populate
47
- facet_names.each do |name|
48
- search_options = facet_search_options.merge(:group_by => name)
49
- add_from_results name, ThinkingSphinx.search(
50
- *(args + [search_options])
51
- )
52
- end
47
+ ThinkingSphinx::Search.bundle_searches(facet_names) { |sphinx, name|
48
+ sphinx.search *(args + [facet_search_options(name)])
49
+ }.each_with_index { |search, index|
50
+ add_from_results facet_names[index], search
51
+ }
53
52
  end
54
53
 
55
- def facet_search_options
56
- config = ThinkingSphinx::Configuration.instance
57
- max = config.configuration.searchd.max_matches || 1000
58
-
54
+ def facet_search_options(facet_name)
59
55
  options.merge(
60
56
  :group_function => :attr,
61
- :limit => max,
62
- :max_matches => max,
63
- :page => 1
57
+ :limit => max_matches,
58
+ :max_matches => max_matches,
59
+ :page => 1,
60
+ :group_by => facet_name,
61
+ :ids_only => !translate?(facet_name)
64
62
  )
65
63
  end
66
64
 
@@ -101,21 +99,34 @@ module ThinkingSphinx
101
99
  }
102
100
  end
103
101
 
104
- def add_from_results(facet, results)
105
- name = ThinkingSphinx::Facet.name_for(facet)
102
+ def translate?(name)
103
+ facet = facet_from_name(name)
104
+ facet.translate? || facet.float?
105
+ end
106
+
107
+ def config
108
+ ThinkingSphinx::Configuration.instance
109
+ end
110
+
111
+ def max_matches
112
+ @max_matches ||= config.configuration.searchd.max_matches || 1000
113
+ end
114
+
115
+ # example: facet = country_facet; name = :country
116
+ def add_from_results(facet, search)
117
+ name = ThinkingSphinx::Facet.name_for(facet)
118
+ facet = facet_from_name(facet)
106
119
 
107
120
  self[name] ||= {}
108
121
 
109
- return if results.empty?
110
-
111
- facet = facet_from_object(results.first, facet) if facet.is_a?(String)
122
+ return if search.empty?
112
123
 
113
- results.each_with_groupby_and_count { |result, group, count|
114
- facet_value = facet.value(result, group)
124
+ search.each_with_match do |result, match|
125
+ facet_value = facet.value(result, match[:attributes])
115
126
 
116
127
  self[name][facet_value] ||= 0
117
- self[name][facet_value] += count
118
- }
128
+ self[name][facet_value] += match[:attributes]["@count"]
129
+ end
119
130
  end
120
131
 
121
132
  def underlying_value(key, value)
@@ -130,7 +141,24 @@ module ThinkingSphinx
130
141
  end
131
142
 
132
143
  def facet_from_object(object, name)
133
- object.sphinx_facets.detect { |facet| facet.attribute_name == name }
144
+ facet = nil
145
+ klass = object.class
146
+
147
+ while klass != ::ActiveRecord::Base && facet.nil?
148
+ facet = klass.sphinx_facets.detect { |facet|
149
+ facet.attribute_name == name
150
+ }
151
+ klass = klass.superclass
152
+ end
153
+
154
+ facet
155
+ end
156
+
157
+ def facet_from_name(name)
158
+ name = ThinkingSphinx::Facet.name_for(name)
159
+ all_facets.detect { |facet|
160
+ facet.name == name
161
+ }
134
162
  end
135
163
  end
136
164
  end
@@ -57,6 +57,22 @@ module ThinkingSphinx
57
57
  ThinkingSphinx.facets *args
58
58
  end
59
59
 
60
+ def self.bundle_searches(enum)
61
+ client = ThinkingSphinx::Configuration.instance.client
62
+
63
+ searches = enum.collect { |item|
64
+ search = yield ThinkingSphinx, item
65
+ search.append_to client
66
+ search
67
+ }
68
+
69
+ client.run.each_with_index.collect { |results, index|
70
+ searches[index].populate_from_queue results
71
+ }
72
+
73
+ searches
74
+ end
75
+
60
76
  def self.matching_fields(fields, bitmask)
61
77
  matches = []
62
78
  bitstring = bitmask.to_s(2).rjust(32, '0').reverse
@@ -111,6 +127,7 @@ module ThinkingSphinx
111
127
  add_scope(method, *args, &block)
112
128
  return self
113
129
  elsif method == :search_count
130
+ merge_search one_class.search(*args)
114
131
  return scoped_count
115
132
  elsif method.to_s[/^each_with_.*/].nil? && !@array.respond_to?(method)
116
133
  super
@@ -186,6 +203,17 @@ module ThinkingSphinx
186
203
  # Compatibility with older versions of will_paginate
187
204
  alias_method :page_count, :total_pages
188
205
 
206
+ # Query time taken
207
+ #
208
+ # @return [Integer]
209
+ #
210
+ def query_time
211
+ populate
212
+ return 0 if @results[:time].nil?
213
+
214
+ @query_time ||= @results[:time]
215
+ end
216
+
189
217
  # The total number of search results available.
190
218
  #
191
219
  # @return [Integer]
@@ -232,6 +260,13 @@ module ThinkingSphinx
232
260
  end
233
261
  end
234
262
 
263
+ def each_with_match(&block)
264
+ populate
265
+ results[:matches].each_with_index do |match, index|
266
+ yield self[index], match
267
+ end
268
+ end
269
+
235
270
  def excerpt_for(string, model = nil)
236
271
  if model.nil? && one_class
237
272
  model ||= one_class
@@ -241,7 +276,7 @@ module ThinkingSphinx
241
276
  client.excerpts(
242
277
  :docs => [string],
243
278
  :words => results[:words].keys.join(' '),
244
- :index => "#{model.source_of_sphinx_index.sphinx_name}_core"
279
+ :index => options[:index] || "#{model.source_of_sphinx_index.sphinx_name}_core"
245
280
  ).first
246
281
  end
247
282
 
@@ -251,6 +286,29 @@ module ThinkingSphinx
251
286
  self
252
287
  end
253
288
 
289
+ def append_to(client)
290
+ prepare client
291
+ client.append_query query, indexes, comment
292
+ client.reset
293
+ end
294
+
295
+ def populate_from_queue(results)
296
+ return if @populated
297
+ @populated = true
298
+ @results = results
299
+
300
+ if options[:ids_only]
301
+ replace @results[:matches].collect { |match|
302
+ match[:attributes]["sphinx_internal_id"]
303
+ }
304
+ else
305
+ replace instances_from_matches
306
+ add_excerpter
307
+ add_sphinx_attributes
308
+ add_matching_fields if client.rank_mode == :fieldmask
309
+ end
310
+ end
311
+
254
312
  private
255
313
 
256
314
  def config
@@ -289,43 +347,32 @@ module ThinkingSphinx
289
347
 
290
348
  def add_excerpter
291
349
  each do |object|
292
- next if object.respond_to?(:excerpts)
293
-
294
- excerpter = ThinkingSphinx::Excerpter.new self, object
295
- block = lambda { excerpter }
350
+ next if object.nil?
296
351
 
297
- object.singleton_class.instance_eval do
298
- define_method(:excerpts, &block)
299
- end
352
+ object.excerpts = ThinkingSphinx::Excerpter.new self, object
300
353
  end
301
354
  end
302
355
 
303
356
  def add_sphinx_attributes
304
357
  each do |object|
305
- next if object.nil? || object.respond_to?(:sphinx_attributes)
358
+ next if object.nil?
306
359
 
307
360
  match = match_hash object
308
361
  next if match.nil?
309
362
 
310
- object.singleton_class.instance_eval do
311
- define_method(:sphinx_attributes) { match[:attributes] }
312
- end
363
+ object.sphinx_attributes = match[:attributes]
313
364
  end
314
365
  end
315
366
 
316
367
  def add_matching_fields
317
368
  each do |object|
318
- next if object.nil? || object.respond_to?(:matching_fields)
369
+ next if object.nil?
319
370
 
320
371
  match = match_hash object
321
372
  next if match.nil?
322
- fields = ThinkingSphinx::Search.matching_fields(
373
+ object.matching_fields = ThinkingSphinx::Search.matching_fields(
323
374
  @results[:fields], match[:weight]
324
375
  )
325
-
326
- object.singleton_class.instance_eval do
327
- define_method(:matching_fields) { fields }
328
- end
329
376
  end
330
377
  end
331
378
 
@@ -352,6 +399,10 @@ module ThinkingSphinx
352
399
  def client
353
400
  client = config.client
354
401
 
402
+ prepare client
403
+ end
404
+
405
+ def prepare(client)
355
406
  index_options = one_class ?
356
407
  one_class.sphinx_indexes.first.local_options : {}
357
408
 
@@ -588,14 +639,6 @@ MSG
588
639
  end
589
640
 
590
641
  # When passed a Time instance, returns the integer timestamp.
591
- #
592
- # If using Rails 2.1+, need to handle timezones to translate them back to
593
- # UTC, as that's what datetimes will be stored as by MySQL.
594
- #
595
- # in_time_zone is a method that was added for the timezone support in
596
- # Rails 2.1, which is why it's used for testing. I'm sure there's better
597
- # ways, but this does the job.
598
- #
599
642
  def filter_value(value)
600
643
  case value
601
644
  when Range
@@ -603,7 +646,7 @@ MSG
603
646
  when Array
604
647
  value.collect { |v| filter_value(v) }.flatten
605
648
  when Time
606
- value.respond_to?(:in_time_zone) ? [value.utc.to_i] : [value.to_i]
649
+ [value.to_i]
607
650
  when NilClass
608
651
  0
609
652
  else
@@ -4,7 +4,12 @@ namespace :thinking_sphinx do
4
4
  task :app_env do
5
5
  if defined?(RAILS_ROOT)
6
6
  Rake::Task[:environment].invoke
7
- Rails.configuration.cache_classes = false
7
+
8
+ if defined?(Rails.configuration)
9
+ Rails.configuration.cache_classes = false
10
+ else
11
+ Rails::Initializer.run { |config| config.cache_classes = false }
12
+ end
8
13
  end
9
14
 
10
15
  Rake::Task[:merb_env].invoke if defined?(Merb)
@@ -27,9 +27,12 @@ class ThinkingSphinx::Test
27
27
  end
28
28
 
29
29
  def self.run(&block)
30
- start
31
- yield
32
- stop
30
+ begin
31
+ start
32
+ yield
33
+ ensure
34
+ stop
35
+ end
33
36
  end
34
37
 
35
38
  def self.config
@@ -106,7 +106,7 @@ describe "ThinkingSphinx::ActiveRecord::Delta" do
106
106
 
107
107
  it "should call indexer for the delta index" do
108
108
  Person.sphinx_indexes.first.delta_object.should_receive(:`).with(
109
- "#{ThinkingSphinx::Configuration.instance.bin_path}indexer --config '#{ThinkingSphinx::Configuration.instance.config_file}' --rotate person_delta"
109
+ "#{ThinkingSphinx::Configuration.instance.bin_path}indexer --config \"#{ThinkingSphinx::Configuration.instance.config_file}\" --rotate person_delta"
110
110
  )
111
111
 
112
112
  @person.send(:index_delta)
@@ -1,28 +1,26 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ThinkingSphinx::FacetSearch do
4
+ let(:search) { stub('search', :append_to => nil, :empty? => true) }
5
+ let(:config) { ThinkingSphinx::Configuration.instance }
6
+ let(:client) { stub('client', :run => []) }
7
+
8
+ before :each do
9
+ config.stub!(:client => client)
10
+ end
11
+
4
12
  describe 'populate' do
5
- it "should make separate Sphinx queries for each facet" do
6
- ThinkingSphinx.should_receive(:search).with(
7
- hash_including(:group_by => 'city_facet')
8
- ).and_return([])
9
- ThinkingSphinx.should_receive(:search).with(
10
- hash_including(:group_by => 'state_facet')
11
- ).and_return([])
12
- ThinkingSphinx.should_receive(:search).with(
13
- hash_including(:group_by => 'birthday')
14
- ).and_return([])
15
-
16
- ThinkingSphinx::FacetSearch.new(:classes => [Person])
13
+ before :each do
14
+ config.configuration.searchd.max_matches = 10_000
17
15
  end
18
-
16
+
19
17
  it "should request all shared facets in a multi-model request by default" do
20
- ThinkingSphinx.stub!(:search => [])
18
+ ThinkingSphinx.stub!(:search => search)
21
19
  ThinkingSphinx::FacetSearch.new.facet_names.should == ['class_crc']
22
20
  end
23
21
 
24
22
  it "should request all facets in a multi-model request if specified" do
25
- ThinkingSphinx.stub!(:search => [])
23
+ ThinkingSphinx.stub!(:search => search)
26
24
  ThinkingSphinx::FacetSearch.new(
27
25
  :all_facets => true
28
26
  ).facet_names.should == [
@@ -30,80 +28,22 @@ describe ThinkingSphinx::FacetSearch do
30
28
  ]
31
29
  end
32
30
 
33
- describe ':facets option' do
34
- it "should limit facets to the requested set" do
35
- ThinkingSphinx.should_receive(:search).once.and_return([])
36
-
37
- ThinkingSphinx::FacetSearch.new(
38
- :classes => [Person], :facets => :state
39
- )
40
- end
41
- end
42
-
43
- describe "empty result set for attributes" do
44
- before :each do
45
- ThinkingSphinx.stub!(:search => [])
46
- @facets = ThinkingSphinx::FacetSearch.new(
47
- :classes => [Person], :facets => :state
48
- )
49
- end
50
-
51
- it "should add key as attribute" do
52
- @facets.should have_key(:state)
53
- end
54
-
55
- it "should return an empty hash for the facet results" do
56
- @facets[:state].should be_empty
57
- end
58
- end
59
-
60
- describe "non-empty result set" do
61
- before :each do
62
- @person = Person.find(:first)
63
- @people = [@person]
64
- @people.stub!(:each_with_groupby_and_count).
65
- and_yield(@person, @person.city.to_crc32, 1)
66
- ThinkingSphinx.stub!(:search => @people)
67
-
68
- @facets = ThinkingSphinx::FacetSearch.new(
69
- :classes => [Person], :facets => :city
70
- )
71
- end
72
-
73
- it "should return a hash" do
74
- @facets.should be_a_kind_of(Hash)
75
- end
76
-
77
- it "should add key as attribute" do
78
- @facets.keys.should include(:city)
79
- end
80
-
81
- it "should return a hash" do
82
- @facets[:city].should == {@person.city => 1}
83
- end
84
- end
85
-
86
- before :each do
87
- @config = ThinkingSphinx::Configuration.instance
88
- @config.configuration.searchd.max_matches = 10_000
89
- end
90
-
91
31
  it "should use the system-set max_matches for limit on facet calls" do
92
32
  ThinkingSphinx.should_receive(:search) do |options|
93
33
  options[:max_matches].should == 10_000
94
34
  options[:limit].should == 10_000
95
- []
35
+ search
96
36
  end
97
37
 
98
38
  ThinkingSphinx::FacetSearch.new
99
39
  end
100
40
 
101
41
  it "should use the default max-matches if there is no explicit setting" do
102
- @config.configuration.searchd.max_matches = nil
42
+ config.configuration.searchd.max_matches = nil
103
43
  ThinkingSphinx.should_receive(:search) do |options|
104
44
  options[:max_matches].should == 1000
105
45
  options[:limit].should == 1000
106
- []
46
+ search
107
47
  end
108
48
 
109
49
  ThinkingSphinx::FacetSearch.new
@@ -113,7 +53,7 @@ describe ThinkingSphinx::FacetSearch do
113
53
  ThinkingSphinx.should_receive(:search) do |options|
114
54
  options[:max_matches].should == 10_000
115
55
  options[:limit].should == 10_000
116
- []
56
+ search
117
57
  end
118
58
 
119
59
  ThinkingSphinx::FacetSearch.new(
@@ -125,7 +65,7 @@ describe ThinkingSphinx::FacetSearch do
125
65
  it "should not use an explicit :page" do
126
66
  ThinkingSphinx.should_receive(:search) do |options|
127
67
  options[:page].should == 1
128
- []
68
+ search
129
69
  end
130
70
 
131
71
  ThinkingSphinx::FacetSearch.new(:page => 3)
@@ -149,15 +89,69 @@ describe ThinkingSphinx::FacetSearch do
149
89
  }.should raise_error
150
90
  end
151
91
  end
92
+
93
+ describe ':facets option' do
94
+ it "should limit facets to the requested set" do
95
+ ThinkingSphinx.should_receive(:search).once.and_return(search)
96
+
97
+ ThinkingSphinx::FacetSearch.new(
98
+ :classes => [Person], :facets => :state
99
+ )
100
+ end
101
+ end
102
+
103
+ describe "empty result set for attributes" do
104
+ before :each do
105
+ ThinkingSphinx.stub!(:search => search)
106
+ @facets = ThinkingSphinx::FacetSearch.new(
107
+ :classes => [Person], :facets => :state
108
+ )
109
+ end
110
+
111
+ it "should add key as attribute" do
112
+ @facets.should have_key(:state)
113
+ end
114
+
115
+ it "should return an empty hash for the facet results" do
116
+ @facets[:state].should be_empty
117
+ end
118
+ end
119
+
120
+ describe "non-empty result set" do
121
+ before :each do
122
+ @person = Person.find(:first)
123
+ @people = [@person]
124
+ search.stub!(:empty? => false)
125
+ search.stub!(:each_with_match).
126
+ and_yield(@person, {:attributes => {'@groupby' => @person.city.to_crc32, '@count' => 1}})
127
+ ThinkingSphinx::Search.stub!(:bundle_searches => [search])
128
+
129
+ @facets = ThinkingSphinx::FacetSearch.new(
130
+ :classes => [Person], :facets => :city
131
+ )
132
+ end
133
+
134
+ it "should return a hash" do
135
+ @facets.should be_a_kind_of(Hash)
136
+ end
137
+
138
+ it "should add key as attribute" do
139
+ @facets.keys.should include(:city)
140
+ end
141
+
142
+ it "should return a hash" do
143
+ @facets[:city].should == {@person.city => 1}
144
+ end
145
+ end
152
146
  end
153
147
 
154
148
  describe "#for" do
155
149
  before do
156
150
  @person = Person.find(:first)
157
151
  @people = [@person]
158
- @people.stub!(:each_with_groupby_and_count).
159
- and_yield(@person, @person.city.to_crc32, 1)
160
- ThinkingSphinx.stub!(:search => @people)
152
+ search.stub!(:each_with_match).
153
+ and_yield(@person, {:attributes => {'@groupby' => @person.city.to_crc32, '@count' => 1}})
154
+ ThinkingSphinx::Search.stub!(:bundle_searches => [search])
161
155
 
162
156
  @facets = ThinkingSphinx::FacetSearch.new(
163
157
  :classes => [Person], :facets => :city
@@ -291,13 +291,13 @@ describe ThinkingSphinx::Facet do
291
291
  person = Person.find(:first)
292
292
  friendship = Friendship.new(:person => person)
293
293
 
294
- @facet.value(friendship, 1).should == person.first_name
294
+ @facet.value(friendship, {'first_name_facet' => 1}).should == person.first_name
295
295
  end
296
296
 
297
297
  it "should return nil if the association is nil" do
298
298
  friendship = Friendship.new(:person => nil)
299
299
 
300
- @facet.value(friendship, 1).should be_nil
300
+ @facet.value(friendship, {'first_name_facet' => 1}).should be_nil
301
301
  end
302
302
 
303
303
  it "should return multi-level association values" do
@@ -308,7 +308,7 @@ describe ThinkingSphinx::Facet do
308
308
  field = ThinkingSphinx::Field.new(
309
309
  @source, ThinkingSphinx::Index::FauxColumn.new(:person, :tags, :name)
310
310
  )
311
- ThinkingSphinx::Facet.new(field).value(friendship, 'buried'.to_crc32).
311
+ ThinkingSphinx::Facet.new(field).value(friendship, {'name_facet' => 'buried'.to_crc32}).
312
312
  should == 'buried'
313
313
  end
314
314
  end
@@ -326,7 +326,7 @@ describe ThinkingSphinx::Facet do
326
326
  it "should translate using the given model" do
327
327
  alpha = Alpha.new(:cost => 10.5)
328
328
 
329
- @facet.value(alpha, 1093140480).should == 10.5
329
+ @facet.value(alpha, {'cost' => 1093140480}).should == 10.5
330
330
  end
331
331
  end
332
332
  end
@@ -135,6 +135,10 @@ describe ThinkingSphinx::SearchMethods do
135
135
  end
136
136
 
137
137
  describe '.facets' do
138
+ before :each do
139
+ ThinkingSphinx::Search.stub!(:bundle_searches => [])
140
+ end
141
+
138
142
  it "should return a FacetSearch instance" do
139
143
  Alpha.facets.should be_a(ThinkingSphinx::FacetSearch)
140
144
  end
@@ -785,9 +785,10 @@ describe ThinkingSphinx::Search do
785
785
  end
786
786
 
787
787
  it "should set up the excerpter with the instances and search" do
788
- ThinkingSphinx::Excerpter.should_receive(:new).with(@search, @alpha_a)
789
- ThinkingSphinx::Excerpter.should_receive(:new).with(@search, @alpha_b)
790
-
788
+ [@alpha_a, @beta_b, @alpha_b, @beta_a].each do |object|
789
+ ThinkingSphinx::Excerpter.should_receive(:new).with(@search, object)
790
+ end
791
+
791
792
  @search.first
792
793
  end
793
794
  end
@@ -822,11 +823,6 @@ describe ThinkingSphinx::Search do
822
823
  search.first.should respond_to(:matching_fields)
823
824
  end
824
825
 
825
- it "should not add matching_fields method if using a different ranking mode" do
826
- search = ThinkingSphinx::Search.new :rank_mode => :bm25
827
- search.first.should_not respond_to(:matching_fields)
828
- end
829
-
830
826
  it "should not add matching_fields method if object already have one" do
831
827
  search = ThinkingSphinx::Search.new :rank_mode => :fieldmask
832
828
  search.last.matching_fields.should_not be_an(Array)
@@ -1112,6 +1108,15 @@ describe ThinkingSphinx::Search do
1112
1108
  @search.excerpt_for('string')
1113
1109
  end
1114
1110
 
1111
+ it "should respect the provided index option" do
1112
+ @search = ThinkingSphinx::Search.new(:classes => [Alpha], :index => 'foo')
1113
+ @client.should_receive(:excerpts) do |options|
1114
+ options[:index].should == 'foo'
1115
+ end
1116
+
1117
+ @search.excerpt_for('string')
1118
+ end
1119
+
1115
1120
  it "should optionally take a second argument to allow for multi-model searches" do
1116
1121
  @client.should_receive(:excerpts) do |options|
1117
1122
  options[:index].should == 'beta_core'
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require "#{File.dirname(__FILE__)}/../../lib/thinking_sphinx/test"
3
+
4
+ describe ThinkingSphinx::Test do
5
+ describe ".run" do
6
+ before :each do
7
+ ThinkingSphinx::Test.stub!(:start)
8
+ end
9
+
10
+ it "should call stop when an exception is raised by passed block" do
11
+ ThinkingSphinx::Test.should_receive(:stop)
12
+
13
+ begin
14
+ ThinkingSphinx::Test.run { raise FakeError }
15
+ rescue => FakeError
16
+ # we raised it manually ourselves!
17
+ end
18
+ end
19
+ end
20
+ end
@@ -23,7 +23,9 @@ Jeweler::Tasks.new do |gem|
23
23
  "VERSION"
24
24
  ]
25
25
  gem.test_files = FileList[
26
- "features/**/*",
26
+ "features/**/*.rb",
27
+ "features/**/*.feature",
28
+ "features/**/*.example.yml",
27
29
  "spec/**/*_spec.rb"
28
30
  ]
29
31
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thinking-sphinx
3
3
  version: !ruby/object:Gem::Version
4
- hash: 63
4
+ hash: 61
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 3
9
- - 18
10
- version: 1.3.18
9
+ - 19
10
+ version: 1.3.19
11
11
  platform: ruby
12
12
  authors:
13
13
  - Pat Allan
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-29 00:00:00 +10:00
18
+ date: 2010-08-23 00:00:00 +08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -214,24 +214,6 @@ files:
214
214
  - tasks/distribution.rb
215
215
  - tasks/rails.rake
216
216
  - tasks/testing.rb
217
- - features/abstract_inheritance.feature
218
- - features/alternate_primary_key.feature
219
- - features/attribute_transformation.feature
220
- - features/attribute_updates.feature
221
- - features/deleting_instances.feature
222
- - features/direct_attributes.feature
223
- - features/excerpts.feature
224
- - features/extensible_delta_indexing.feature
225
- - features/facets.feature
226
- - features/facets_across_model.feature
227
- - features/handling_edits.feature
228
- - features/retry_stale_indexes.feature
229
- - features/searching_across_models.feature
230
- - features/searching_by_index.feature
231
- - features/searching_by_model.feature
232
- - features/searching_with_find_arguments.feature
233
- - features/sphinx_detection.feature
234
- - features/sphinx_scopes.feature
235
217
  - features/step_definitions/alpha_steps.rb
236
218
  - features/step_definitions/beta_steps.rb
237
219
  - features/step_definitions/common_steps.rb
@@ -242,11 +224,8 @@ files:
242
224
  - features/step_definitions/scope_steps.rb
243
225
  - features/step_definitions/search_steps.rb
244
226
  - features/step_definitions/sphinx_steps.rb
245
- - features/sti_searching.feature
246
227
  - features/support/env.rb
247
228
  - features/support/lib/generic_delta_handler.rb
248
- - features/thinking_sphinx/database.example.yml
249
- - features/thinking_sphinx/database.yml
250
229
  - features/thinking_sphinx/db/fixtures/alphas.rb
251
230
  - features/thinking_sphinx/db/fixtures/authors.rb
252
231
  - features/thinking_sphinx/db/fixtures/betas.rb
@@ -303,6 +282,26 @@ files:
303
282
  - features/thinking_sphinx/models/robot.rb
304
283
  - features/thinking_sphinx/models/tag.rb
305
284
  - features/thinking_sphinx/models/tagging.rb
285
+ - features/abstract_inheritance.feature
286
+ - features/alternate_primary_key.feature
287
+ - features/attribute_transformation.feature
288
+ - features/attribute_updates.feature
289
+ - features/deleting_instances.feature
290
+ - features/direct_attributes.feature
291
+ - features/excerpts.feature
292
+ - features/extensible_delta_indexing.feature
293
+ - features/facets.feature
294
+ - features/facets_across_model.feature
295
+ - features/handling_edits.feature
296
+ - features/retry_stale_indexes.feature
297
+ - features/searching_across_models.feature
298
+ - features/searching_by_index.feature
299
+ - features/searching_by_model.feature
300
+ - features/searching_with_find_arguments.feature
301
+ - features/sphinx_detection.feature
302
+ - features/sphinx_scopes.feature
303
+ - features/sti_searching.feature
304
+ - features/thinking_sphinx/database.example.yml
306
305
  - spec/thinking_sphinx/active_record/delta_spec.rb
307
306
  - spec/thinking_sphinx/active_record/has_many_association_spec.rb
308
307
  - spec/thinking_sphinx/active_record/scopes_spec.rb
@@ -325,6 +324,7 @@ files:
325
324
  - spec/thinking_sphinx/search_methods_spec.rb
326
325
  - spec/thinking_sphinx/search_spec.rb
327
326
  - spec/thinking_sphinx/source_spec.rb
327
+ - spec/thinking_sphinx/test_spec.rb
328
328
  - spec/thinking_sphinx_spec.rb
329
329
  has_rdoc: true
330
330
  homepage: http://ts.freelancing-gods.com
@@ -364,24 +364,6 @@ signing_key:
364
364
  specification_version: 3
365
365
  summary: ActiveRecord/Rails Sphinx library
366
366
  test_files:
367
- - features/abstract_inheritance.feature
368
- - features/alternate_primary_key.feature
369
- - features/attribute_transformation.feature
370
- - features/attribute_updates.feature
371
- - features/deleting_instances.feature
372
- - features/direct_attributes.feature
373
- - features/excerpts.feature
374
- - features/extensible_delta_indexing.feature
375
- - features/facets.feature
376
- - features/facets_across_model.feature
377
- - features/handling_edits.feature
378
- - features/retry_stale_indexes.feature
379
- - features/searching_across_models.feature
380
- - features/searching_by_index.feature
381
- - features/searching_by_model.feature
382
- - features/searching_with_find_arguments.feature
383
- - features/sphinx_detection.feature
384
- - features/sphinx_scopes.feature
385
367
  - features/step_definitions/alpha_steps.rb
386
368
  - features/step_definitions/beta_steps.rb
387
369
  - features/step_definitions/common_steps.rb
@@ -392,11 +374,8 @@ test_files:
392
374
  - features/step_definitions/scope_steps.rb
393
375
  - features/step_definitions/search_steps.rb
394
376
  - features/step_definitions/sphinx_steps.rb
395
- - features/sti_searching.feature
396
377
  - features/support/env.rb
397
378
  - features/support/lib/generic_delta_handler.rb
398
- - features/thinking_sphinx/database.example.yml
399
- - features/thinking_sphinx/database.yml
400
379
  - features/thinking_sphinx/db/fixtures/alphas.rb
401
380
  - features/thinking_sphinx/db/fixtures/authors.rb
402
381
  - features/thinking_sphinx/db/fixtures/betas.rb
@@ -453,6 +432,26 @@ test_files:
453
432
  - features/thinking_sphinx/models/robot.rb
454
433
  - features/thinking_sphinx/models/tag.rb
455
434
  - features/thinking_sphinx/models/tagging.rb
435
+ - features/abstract_inheritance.feature
436
+ - features/alternate_primary_key.feature
437
+ - features/attribute_transformation.feature
438
+ - features/attribute_updates.feature
439
+ - features/deleting_instances.feature
440
+ - features/direct_attributes.feature
441
+ - features/excerpts.feature
442
+ - features/extensible_delta_indexing.feature
443
+ - features/facets.feature
444
+ - features/facets_across_model.feature
445
+ - features/handling_edits.feature
446
+ - features/retry_stale_indexes.feature
447
+ - features/searching_across_models.feature
448
+ - features/searching_by_index.feature
449
+ - features/searching_by_model.feature
450
+ - features/searching_with_find_arguments.feature
451
+ - features/sphinx_detection.feature
452
+ - features/sphinx_scopes.feature
453
+ - features/sti_searching.feature
454
+ - features/thinking_sphinx/database.example.yml
456
455
  - spec/thinking_sphinx/active_record/delta_spec.rb
457
456
  - spec/thinking_sphinx/active_record/has_many_association_spec.rb
458
457
  - spec/thinking_sphinx/active_record/scopes_spec.rb
@@ -475,4 +474,5 @@ test_files:
475
474
  - spec/thinking_sphinx/search_methods_spec.rb
476
475
  - spec/thinking_sphinx/search_spec.rb
477
476
  - spec/thinking_sphinx/source_spec.rb
477
+ - spec/thinking_sphinx/test_spec.rb
478
478
  - spec/thinking_sphinx_spec.rb
@@ -1,3 +0,0 @@
1
- username: thinking_sphinx
2
- pool: 1
3
- min_messages: warning