thorsson_thinking-sphinx 1.3.18 → 2.0

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 (34) hide show
  1. data/README.textile +5 -0
  2. data/VERSION +1 -1
  3. data/features/facets.feature +9 -1
  4. data/features/searching_across_models.feature +1 -1
  5. data/features/sphinx_scopes.feature +26 -0
  6. data/features/step_definitions/scope_steps.rb +4 -0
  7. data/features/thinking_sphinx/models/alpha.rb +1 -0
  8. data/lib/cucumber/thinking_sphinx/external_world.rb +8 -4
  9. data/lib/thinking_sphinx.rb +1 -0
  10. data/lib/thinking_sphinx/active_record.rb +4 -0
  11. data/lib/thinking_sphinx/active_record/scopes.rb +7 -0
  12. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +2 -1
  13. data/lib/thinking_sphinx/auto_version.rb +2 -0
  14. data/lib/thinking_sphinx/bundled_search.rb +44 -0
  15. data/lib/thinking_sphinx/class_facet.rb +3 -2
  16. data/lib/thinking_sphinx/configuration.rb +8 -7
  17. data/lib/thinking_sphinx/context.rb +4 -2
  18. data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
  19. data/lib/thinking_sphinx/facet.rb +6 -5
  20. data/lib/thinking_sphinx/facet_search.rb +51 -23
  21. data/lib/thinking_sphinx/search.rb +75 -32
  22. data/lib/thinking_sphinx/tasks.rb +6 -1
  23. data/spec/thinking_sphinx/active_record/delta_spec.rb +1 -1
  24. data/spec/thinking_sphinx/active_record/scopes_spec.rb +2 -3
  25. data/spec/thinking_sphinx/auto_version_spec.rb +8 -0
  26. data/spec/thinking_sphinx/context_spec.rb +3 -2
  27. data/spec/thinking_sphinx/facet_search_spec.rb +75 -81
  28. data/spec/thinking_sphinx/facet_spec.rb +4 -4
  29. data/spec/thinking_sphinx/search_methods_spec.rb +4 -0
  30. data/spec/thinking_sphinx/search_spec.rb +26 -8
  31. data/spec/thinking_sphinx/test_spec.rb +20 -0
  32. data/tasks/distribution.rb +4 -2
  33. metadata +53 -45
  34. data/features/thinking_sphinx/database.yml +0 -3
@@ -167,3 +167,8 @@ Since I first released this library, there's been quite a few people who have su
167
167
  * James Brooks
168
168
  * Mark Dodwell
169
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.20
@@ -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
+
@@ -7,7 +7,7 @@ Feature: Searching across multiple model
7
7
  Given Sphinx is running
8
8
  When I search for James
9
9
  And I am retrieving the result count
10
- Then I should get a value of 3
10
+ Then I should get a value of 6
11
11
 
12
12
  Scenario: Confirming existance of a document id in a given index
13
13
  Given Sphinx is running
@@ -40,3 +40,29 @@ 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
+
51
+ Scenario: Default Scope
52
+ Given Sphinx is running
53
+ And I am searching on andrews
54
+ Then I should get 7 results
55
+
56
+ Scenario: Default Scope and additional query terms
57
+ Given Sphinx is running
58
+ And I am searching on andrews
59
+ When I search for "Byrne"
60
+ Then I should get 1 result
61
+
62
+ Scenario: Explicit scope plus search over a default scope
63
+ Given Sphinx is running
64
+ And I am searching on andrews
65
+ When I use the locked_last_name scope
66
+ And I search for "Cecil"
67
+ Then I should get 1 result
68
+
@@ -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
@@ -14,6 +14,7 @@ class Alpha < ActiveRecord::Base
14
14
 
15
15
  has value, created_at, created_on
16
16
  has cost, :facet => true
17
+ has active
17
18
 
18
19
  set_property :field_weights => {'alternative_name' => 10}
19
20
 
@@ -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
@@ -10,6 +10,7 @@ require 'thinking_sphinx/property'
10
10
  require 'thinking_sphinx/active_record'
11
11
  require 'thinking_sphinx/association'
12
12
  require 'thinking_sphinx/attribute'
13
+ require 'thinking_sphinx/bundled_search'
13
14
  require 'thinking_sphinx/configuration'
14
15
  require 'thinking_sphinx/context'
15
16
  require 'thinking_sphinx/excerpter'
@@ -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
@@ -53,6 +53,13 @@ module ThinkingSphinx
53
53
 
54
54
  ThinkingSphinx::Search.new(options)
55
55
  end
56
+
57
+ define_method("#{method}_without_default".to_sym) do |*args|
58
+ options = {:classes => classes_option, :ignore_default => true}
59
+ options.merge! block.call(*args)
60
+
61
+ ThinkingSphinx::Search.new(options)
62
+ end
56
63
  end
57
64
  end
58
65
 
@@ -13,7 +13,8 @@ module ThinkingSphinx
13
13
  case model.connection.class.name
14
14
  when "ActiveRecord::ConnectionAdapters::MysqlAdapter",
15
15
  "ActiveRecord::ConnectionAdapters::MysqlplusAdapter",
16
- "ActiveRecord::ConnectionAdapters::Mysql2Adapter"
16
+ "ActiveRecord::ConnectionAdapters::Mysql2Adapter",
17
+ "ActiveRecord::ConnectionAdapters::NullDBAdapter"
17
18
  ThinkingSphinx::MysqlAdapter.new model
18
19
  when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
19
20
  ThinkingSphinx::PostgreSQLAdapter.new model
@@ -5,6 +5,8 @@ module ThinkingSphinx
5
5
  case version
6
6
  when '0.9.8', '0.9.9'
7
7
  require "riddle/#{version}"
8
+ when '1.10-beta'
9
+ require 'riddle/1.10'
8
10
  else
9
11
  STDERR.puts %Q{
10
12
  Sphinx cannot be found on your system. You may need to configure the following
@@ -0,0 +1,44 @@
1
+ module ThinkingSphinx
2
+ class BundledSearch
3
+ attr_reader :client
4
+
5
+ def initialize
6
+ @searches = []
7
+ end
8
+
9
+ def search(*args)
10
+ @searches << ThinkingSphinx.search(*args)
11
+ @searches.last.append_to client
12
+ end
13
+
14
+ def search_for_ids(*args)
15
+ @searches << ThinkingSphinx.search_for_ids(*args)
16
+ @searches.last.append_to client
17
+ end
18
+
19
+ def searches
20
+ populate
21
+ @searches
22
+ end
23
+
24
+ private
25
+
26
+ def client
27
+ @client ||= ThinkingSphinx::Configuration.instance.client
28
+ end
29
+
30
+ def populated?
31
+ @populated
32
+ end
33
+
34
+ def populate
35
+ return if populated?
36
+
37
+ @populated = true
38
+
39
+ client.run.each_with_index do |results, index|
40
+ searches[index].populate_from_queue results
41
+ end
42
+ end
43
+ end
44
+ end
@@ -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
@@ -54,13 +54,14 @@ module ThinkingSphinx
54
54
  sql_query_killlist sql_ranged_throttle sql_query_post_index unpack_zlib
55
55
  unpack_mysqlcompress unpack_mysqlcompress_maxsize )
56
56
 
57
- IndexOptions = %w( charset_table charset_type charset_dictpath docinfo
58
- enable_star exceptions html_index_attrs html_remove_elements html_strip
59
- index_exact_words ignore_chars inplace_docinfo_gap inplace_enable
60
- inplace_hit_gap inplace_reloc_factor inplace_write_factor min_infix_len
61
- min_prefix_len min_stemming_len min_word_len mlock morphology ngram_chars
62
- ngram_len ondisk_dict overshort_step phrase_boundary phrase_boundary_step
63
- preopen stopwords stopwords_step wordforms )
57
+ IndexOptions = %w( blend_chars charset_table charset_type charset_dictpath
58
+ docinfo enable_star exceptions expand_keywords hitless_words
59
+ html_index_attrs html_remove_elements html_strip index_exact_words
60
+ ignore_chars inplace_docinfo_gap inplace_enable inplace_hit_gap
61
+ inplace_reloc_factor inplace_write_factor min_infix_len min_prefix_len
62
+ min_stemming_len min_word_len mlock morphology ngram_chars ngram_len
63
+ ondisk_dict overshort_step phrase_boundary phrase_boundary_step preopen
64
+ stopwords stopwords_step wordforms )
64
65
 
65
66
  CustomOptions = %w( disable_range )
66
67
 
@@ -65,8 +65,10 @@ class ThinkingSphinx::Context
65
65
  model_name.gsub!(/.*[\/\\]/, '').nil? ? next : retry
66
66
  rescue NameError
67
67
  next
68
- rescue StandardError
69
- STDERR.puts "Warning: Error loading #{file}"
68
+ rescue StandardError => err
69
+ STDERR.puts "Warning: Error loading #{file}:"
70
+ STDERR.puts err.message
71
+ STDERR.puts err.backtrace.join("\n"), ''
70
72
  end
71
73
  end
72
74
  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,18 @@ module ThinkingSphinx
57
57
  ThinkingSphinx.facets *args
58
58
  end
59
59
 
60
+ def self.bundle_searches(enum = nil)
61
+ bundle = ThinkingSphinx::BundledSearch.new
62
+
63
+ if enum.nil?
64
+ yield bundle
65
+ else
66
+ enum.each { |item| yield bundle, item }
67
+ end
68
+
69
+ bundle.searches
70
+ end
71
+
60
72
  def self.matching_fields(fields, bitmask)
61
73
  matches = []
62
74
  bitstring = bitmask.to_s(2).rjust(32, '0').reverse
@@ -74,6 +86,8 @@ module ThinkingSphinx
74
86
  @options = args.extract_options!
75
87
  @args = args
76
88
 
89
+ add_default_scope unless options[:ignore_default]
90
+
77
91
  populate if @options[:populate]
78
92
  end
79
93
 
@@ -111,6 +125,7 @@ module ThinkingSphinx
111
125
  add_scope(method, *args, &block)
112
126
  return self
113
127
  elsif method == :search_count
128
+ merge_search one_class.search(*args)
114
129
  return scoped_count
115
130
  elsif method.to_s[/^each_with_.*/].nil? && !@array.respond_to?(method)
116
131
  super
@@ -186,6 +201,17 @@ module ThinkingSphinx
186
201
  # Compatibility with older versions of will_paginate
187
202
  alias_method :page_count, :total_pages
188
203
 
204
+ # Query time taken
205
+ #
206
+ # @return [Integer]
207
+ #
208
+ def query_time
209
+ populate
210
+ return 0 if @results[:time].nil?
211
+
212
+ @query_time ||= @results[:time]
213
+ end
214
+
189
215
  # The total number of search results available.
190
216
  #
191
217
  # @return [Integer]
@@ -232,6 +258,13 @@ module ThinkingSphinx
232
258
  end
233
259
  end
234
260
 
261
+ def each_with_match(&block)
262
+ populate
263
+ results[:matches].each_with_index do |match, index|
264
+ yield self[index], match
265
+ end
266
+ end
267
+
235
268
  def excerpt_for(string, model = nil)
236
269
  if model.nil? && one_class
237
270
  model ||= one_class
@@ -241,16 +274,45 @@ module ThinkingSphinx
241
274
  client.excerpts(
242
275
  :docs => [string],
243
276
  :words => results[:words].keys.join(' '),
244
- :index => "#{model.source_of_sphinx_index.sphinx_name}_core"
277
+ :index => options[:index] || "#{model.source_of_sphinx_index.sphinx_name}_core"
245
278
  ).first
246
279
  end
247
280
 
248
281
  def search(*args)
249
- add_default_scope
282
+ args << args.extract_options!.merge(:ignore_default => true)
250
283
  merge_search ThinkingSphinx::Search.new(*args)
251
284
  self
252
285
  end
253
286
 
287
+ def client
288
+ client = options[:client] || config.client
289
+
290
+ prepare client
291
+ end
292
+
293
+ def append_to(client)
294
+ prepare client
295
+ client.append_query query, indexes, comment
296
+ client.reset
297
+ end
298
+
299
+ def populate_from_queue(results)
300
+ return if @populated
301
+ @populated = true
302
+ @results = results
303
+
304
+ if options[:ids_only]
305
+ replace @results[:matches].collect { |match|
306
+ match[:attributes]["sphinx_internal_id"]
307
+ }
308
+ else
309
+ replace instances_from_matches
310
+ add_excerpter
311
+ add_sphinx_attributes
312
+ add_matching_fields if client.rank_mode == :fieldmask
313
+ end
314
+ end
315
+
254
316
  private
255
317
 
256
318
  def config
@@ -289,43 +351,32 @@ module ThinkingSphinx
289
351
 
290
352
  def add_excerpter
291
353
  each do |object|
292
- next if object.respond_to?(:excerpts)
354
+ next if object.nil?
293
355
 
294
- excerpter = ThinkingSphinx::Excerpter.new self, object
295
- block = lambda { excerpter }
296
-
297
- object.singleton_class.instance_eval do
298
- define_method(:excerpts, &block)
299
- end
356
+ object.excerpts = ThinkingSphinx::Excerpter.new self, object
300
357
  end
301
358
  end
302
359
 
303
360
  def add_sphinx_attributes
304
361
  each do |object|
305
- next if object.nil? || object.respond_to?(:sphinx_attributes)
362
+ next if object.nil?
306
363
 
307
364
  match = match_hash object
308
365
  next if match.nil?
309
366
 
310
- object.singleton_class.instance_eval do
311
- define_method(:sphinx_attributes) { match[:attributes] }
312
- end
367
+ object.sphinx_attributes = match[:attributes]
313
368
  end
314
369
  end
315
370
 
316
371
  def add_matching_fields
317
372
  each do |object|
318
- next if object.nil? || object.respond_to?(:matching_fields)
373
+ next if object.nil?
319
374
 
320
375
  match = match_hash object
321
376
  next if match.nil?
322
- fields = ThinkingSphinx::Search.matching_fields(
377
+ object.matching_fields = ThinkingSphinx::Search.matching_fields(
323
378
  @results[:fields], match[:weight]
324
379
  )
325
-
326
- object.singleton_class.instance_eval do
327
- define_method(:matching_fields) { fields }
328
- end
329
380
  end
330
381
  end
331
382
 
@@ -349,9 +400,7 @@ module ThinkingSphinx
349
400
  self.class.log(*args)
350
401
  end
351
402
 
352
- def client
353
- client = config.client
354
-
403
+ def prepare(client)
355
404
  index_options = one_class ?
356
405
  one_class.sphinx_indexes.first.local_options : {}
357
406
 
@@ -588,14 +637,6 @@ MSG
588
637
  end
589
638
 
590
639
  # 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
640
  def filter_value(value)
600
641
  case value
601
642
  when Range
@@ -603,7 +644,7 @@ MSG
603
644
  when Array
604
645
  value.collect { |v| filter_value(v) }.flatten
605
646
  when Time
606
- value.respond_to?(:in_time_zone) ? [value.utc.to_i] : [value.to_i]
647
+ [value.to_i]
607
648
  when NilClass
608
649
  0
609
650
  else
@@ -747,10 +788,12 @@ MSG
747
788
 
748
789
  # Adds the default_sphinx_scope if set.
749
790
  def add_default_scope
750
- add_scope(one_class.get_default_sphinx_scope) if one_class && one_class.has_default_sphinx_scope?
791
+ return unless one_class && one_class.has_default_sphinx_scope?
792
+ add_scope(one_class.get_default_sphinx_scope.to_sym)
751
793
  end
752
794
 
753
795
  def add_scope(method, *args, &block)
796
+ method = "#{method}_without_default".to_sym
754
797
  merge_search one_class.send(method, *args, &block)
755
798
  end
756
799
 
@@ -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)
@@ -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)
@@ -87,10 +87,9 @@ describe ThinkingSphinx::ActiveRecord::Scopes do
87
87
  search.by_foo('foo').search.options[:conditions].should == {:foo => 'foo', :name => 'foo'}
88
88
  end
89
89
 
90
- # FIXME: Probably the other way around is more logical? How to do this?
91
- it "should apply the default scope options after other scope options to the underlying search object" do
90
+ it "should apply the default scope options before other scope options to the underlying search object" do
92
91
  search = ThinkingSphinx::Search.new(:classes => [Alpha])
93
- search.by_name('bar').search.options[:conditions].should == {:name => 'foo'}
92
+ search.by_name('bar').search.options[:conditions].should == {:name => 'bar'}
94
93
  end
95
94
  end
96
95
 
@@ -22,6 +22,14 @@ describe ThinkingSphinx::AutoVersion do
22
22
  ThinkingSphinx::AutoVersion.detect
23
23
  end
24
24
 
25
+ it "should require 1.10-beta if that is the detected version" do
26
+ ThinkingSphinx::AutoVersion.should_receive(:require).
27
+ with('riddle/1.10')
28
+
29
+ @config.stub!(:version => '1.10-beta')
30
+ ThinkingSphinx::AutoVersion.detect
31
+ end
32
+
25
33
  it "should output a warning if the detected version is something else" do
26
34
  STDERR.should_receive(:puts)
27
35
 
@@ -53,8 +53,9 @@ describe ThinkingSphinx::Context do
53
53
 
54
54
  it "should catch database errors with a warning" do
55
55
  @class_name.should_receive(:constantize).and_raise(Mysql::Error)
56
- STDERR.should_receive(:puts).with('Warning: Error loading a.rb')
57
-
56
+ STDERR.stub!(:puts => '')
57
+ STDERR.should_receive(:puts).with('Warning: Error loading a.rb:')
58
+
58
59
  lambda {
59
60
  @context.prepare
60
61
  }.should_not raise_error
@@ -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'
@@ -1197,6 +1202,19 @@ describe ThinkingSphinx::Search do
1197
1202
  @search.freeze.should be_a(ThinkingSphinx::Search)
1198
1203
  end
1199
1204
  end
1205
+
1206
+ describe '#client' do
1207
+ let(:client) { Riddle::Client.new }
1208
+ it "should respect the client in options" do
1209
+ search = ThinkingSphinx::Search.new :client => client
1210
+ search.client.should == client
1211
+ end
1212
+
1213
+ it "should get a new client from the configuration singleton by default" do
1214
+ ThinkingSphinx::Configuration.instance.stub!(:client => client)
1215
+ ThinkingSphinx::Search.new.client.should == client
1216
+ end
1217
+ end
1200
1218
  end
1201
1219
 
1202
1220
  describe ThinkingSphinx::Search, "playing nice with Search model" do
@@ -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,11 +23,13 @@ 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
 
30
- gem.add_dependency 'activerecord', '>= 1.15.6'
32
+ gem.add_dependency 'activerecord', '>= 1.15.6', '< 3.0.0'
31
33
  gem.add_dependency 'riddle', '>= 1.0.10'
32
34
  gem.add_dependency 'after_commit', '>= 1.0.6'
33
35
 
metadata CHANGED
@@ -3,10 +3,9 @@ name: thorsson_thinking-sphinx
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
- - 1
7
- - 3
8
- - 18
9
- version: 1.3.18
6
+ - 2
7
+ - 0
8
+ version: "2.0"
10
9
  platform: ruby
11
10
  authors:
12
11
  - Pat Allan
@@ -14,7 +13,7 @@ autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
15
 
17
- date: 2010-06-29 00:00:00 +02:00
16
+ date: 2010-09-03 00:00:00 +02:00
18
17
  default_executable:
19
18
  dependencies:
20
19
  - !ruby/object:Gem::Dependency
@@ -30,6 +29,13 @@ dependencies:
30
29
  - 15
31
30
  - 6
32
31
  version: 1.15.6
32
+ - - <
33
+ - !ruby/object:Gem::Version
34
+ segments:
35
+ - 3
36
+ - 0
37
+ - 0
38
+ version: 3.0.0
33
39
  type: :runtime
34
40
  version_requirements: *id001
35
41
  - !ruby/object:Gem::Dependency
@@ -175,6 +181,7 @@ files:
175
181
  - lib/thinking_sphinx/association.rb
176
182
  - lib/thinking_sphinx/attribute.rb
177
183
  - lib/thinking_sphinx/auto_version.rb
184
+ - lib/thinking_sphinx/bundled_search.rb
178
185
  - lib/thinking_sphinx/class_facet.rb
179
186
  - lib/thinking_sphinx/configuration.rb
180
187
  - lib/thinking_sphinx/context.rb
@@ -204,24 +211,6 @@ files:
204
211
  - tasks/distribution.rb
205
212
  - tasks/rails.rake
206
213
  - tasks/testing.rb
207
- - features/abstract_inheritance.feature
208
- - features/alternate_primary_key.feature
209
- - features/attribute_transformation.feature
210
- - features/attribute_updates.feature
211
- - features/deleting_instances.feature
212
- - features/direct_attributes.feature
213
- - features/excerpts.feature
214
- - features/extensible_delta_indexing.feature
215
- - features/facets.feature
216
- - features/facets_across_model.feature
217
- - features/handling_edits.feature
218
- - features/retry_stale_indexes.feature
219
- - features/searching_across_models.feature
220
- - features/searching_by_index.feature
221
- - features/searching_by_model.feature
222
- - features/searching_with_find_arguments.feature
223
- - features/sphinx_detection.feature
224
- - features/sphinx_scopes.feature
225
214
  - features/step_definitions/alpha_steps.rb
226
215
  - features/step_definitions/beta_steps.rb
227
216
  - features/step_definitions/common_steps.rb
@@ -232,11 +221,9 @@ files:
232
221
  - features/step_definitions/scope_steps.rb
233
222
  - features/step_definitions/search_steps.rb
234
223
  - features/step_definitions/sphinx_steps.rb
235
- - features/sti_searching.feature
236
224
  - features/support/env.rb
237
225
  - features/support/lib/generic_delta_handler.rb
238
226
  - features/thinking_sphinx/database.example.yml
239
- - features/thinking_sphinx/database.yml
240
227
  - features/thinking_sphinx/db/fixtures/alphas.rb
241
228
  - features/thinking_sphinx/db/fixtures/authors.rb
242
229
  - features/thinking_sphinx/db/fixtures/betas.rb
@@ -293,6 +280,25 @@ files:
293
280
  - features/thinking_sphinx/models/robot.rb
294
281
  - features/thinking_sphinx/models/tag.rb
295
282
  - features/thinking_sphinx/models/tagging.rb
283
+ - features/abstract_inheritance.feature
284
+ - features/alternate_primary_key.feature
285
+ - features/attribute_transformation.feature
286
+ - features/attribute_updates.feature
287
+ - features/deleting_instances.feature
288
+ - features/direct_attributes.feature
289
+ - features/excerpts.feature
290
+ - features/extensible_delta_indexing.feature
291
+ - features/facets.feature
292
+ - features/facets_across_model.feature
293
+ - features/handling_edits.feature
294
+ - features/retry_stale_indexes.feature
295
+ - features/searching_across_models.feature
296
+ - features/searching_by_index.feature
297
+ - features/searching_by_model.feature
298
+ - features/searching_with_find_arguments.feature
299
+ - features/sphinx_detection.feature
300
+ - features/sphinx_scopes.feature
301
+ - features/sti_searching.feature
296
302
  - spec/thinking_sphinx/active_record/delta_spec.rb
297
303
  - spec/thinking_sphinx/active_record/has_many_association_spec.rb
298
304
  - spec/thinking_sphinx/active_record/scopes_spec.rb
@@ -315,6 +321,7 @@ files:
315
321
  - spec/thinking_sphinx/search_methods_spec.rb
316
322
  - spec/thinking_sphinx/search_spec.rb
317
323
  - spec/thinking_sphinx/source_spec.rb
324
+ - spec/thinking_sphinx/test_spec.rb
318
325
  - spec/thinking_sphinx_spec.rb
319
326
  has_rdoc: true
320
327
  homepage: http://ts.freelancing-gods.com
@@ -352,24 +359,6 @@ signing_key:
352
359
  specification_version: 3
353
360
  summary: ActiveRecord/Rails Sphinx library
354
361
  test_files:
355
- - features/abstract_inheritance.feature
356
- - features/alternate_primary_key.feature
357
- - features/attribute_transformation.feature
358
- - features/attribute_updates.feature
359
- - features/deleting_instances.feature
360
- - features/direct_attributes.feature
361
- - features/excerpts.feature
362
- - features/extensible_delta_indexing.feature
363
- - features/facets.feature
364
- - features/facets_across_model.feature
365
- - features/handling_edits.feature
366
- - features/retry_stale_indexes.feature
367
- - features/searching_across_models.feature
368
- - features/searching_by_index.feature
369
- - features/searching_by_model.feature
370
- - features/searching_with_find_arguments.feature
371
- - features/sphinx_detection.feature
372
- - features/sphinx_scopes.feature
373
362
  - features/step_definitions/alpha_steps.rb
374
363
  - features/step_definitions/beta_steps.rb
375
364
  - features/step_definitions/common_steps.rb
@@ -380,11 +369,9 @@ test_files:
380
369
  - features/step_definitions/scope_steps.rb
381
370
  - features/step_definitions/search_steps.rb
382
371
  - features/step_definitions/sphinx_steps.rb
383
- - features/sti_searching.feature
384
372
  - features/support/env.rb
385
373
  - features/support/lib/generic_delta_handler.rb
386
374
  - features/thinking_sphinx/database.example.yml
387
- - features/thinking_sphinx/database.yml
388
375
  - features/thinking_sphinx/db/fixtures/alphas.rb
389
376
  - features/thinking_sphinx/db/fixtures/authors.rb
390
377
  - features/thinking_sphinx/db/fixtures/betas.rb
@@ -441,6 +428,26 @@ test_files:
441
428
  - features/thinking_sphinx/models/robot.rb
442
429
  - features/thinking_sphinx/models/tag.rb
443
430
  - features/thinking_sphinx/models/tagging.rb
431
+ - features/abstract_inheritance.feature
432
+ - features/alternate_primary_key.feature
433
+ - features/attribute_transformation.feature
434
+ - features/attribute_updates.feature
435
+ - features/deleting_instances.feature
436
+ - features/direct_attributes.feature
437
+ - features/excerpts.feature
438
+ - features/extensible_delta_indexing.feature
439
+ - features/facets.feature
440
+ - features/facets_across_model.feature
441
+ - features/handling_edits.feature
442
+ - features/retry_stale_indexes.feature
443
+ - features/searching_across_models.feature
444
+ - features/searching_by_index.feature
445
+ - features/searching_by_model.feature
446
+ - features/searching_with_find_arguments.feature
447
+ - features/sphinx_detection.feature
448
+ - features/sphinx_scopes.feature
449
+ - features/sti_searching.feature
450
+ - features/thinking_sphinx/database.example.yml
444
451
  - spec/thinking_sphinx/active_record/delta_spec.rb
445
452
  - spec/thinking_sphinx/active_record/has_many_association_spec.rb
446
453
  - spec/thinking_sphinx/active_record/scopes_spec.rb
@@ -463,4 +470,5 @@ test_files:
463
470
  - spec/thinking_sphinx/search_methods_spec.rb
464
471
  - spec/thinking_sphinx/search_spec.rb
465
472
  - spec/thinking_sphinx/source_spec.rb
473
+ - spec/thinking_sphinx/test_spec.rb
466
474
  - spec/thinking_sphinx_spec.rb
@@ -1,3 +0,0 @@
1
- username: root
2
- host: localhost
3
- password: