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.
- data/README.textile +5 -0
- data/VERSION +1 -1
- data/features/facets.feature +9 -1
- data/features/searching_across_models.feature +1 -1
- data/features/sphinx_scopes.feature +26 -0
- data/features/step_definitions/scope_steps.rb +4 -0
- data/features/thinking_sphinx/models/alpha.rb +1 -0
- data/lib/cucumber/thinking_sphinx/external_world.rb +8 -4
- data/lib/thinking_sphinx.rb +1 -0
- data/lib/thinking_sphinx/active_record.rb +4 -0
- data/lib/thinking_sphinx/active_record/scopes.rb +7 -0
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +2 -1
- data/lib/thinking_sphinx/auto_version.rb +2 -0
- data/lib/thinking_sphinx/bundled_search.rb +44 -0
- data/lib/thinking_sphinx/class_facet.rb +3 -2
- data/lib/thinking_sphinx/configuration.rb +8 -7
- data/lib/thinking_sphinx/context.rb +4 -2
- data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
- data/lib/thinking_sphinx/facet.rb +6 -5
- data/lib/thinking_sphinx/facet_search.rb +51 -23
- data/lib/thinking_sphinx/search.rb +75 -32
- data/lib/thinking_sphinx/tasks.rb +6 -1
- data/spec/thinking_sphinx/active_record/delta_spec.rb +1 -1
- data/spec/thinking_sphinx/active_record/scopes_spec.rb +2 -3
- data/spec/thinking_sphinx/auto_version_spec.rb +8 -0
- data/spec/thinking_sphinx/context_spec.rb +3 -2
- data/spec/thinking_sphinx/facet_search_spec.rb +75 -81
- data/spec/thinking_sphinx/facet_spec.rb +4 -4
- data/spec/thinking_sphinx/search_methods_spec.rb +4 -0
- data/spec/thinking_sphinx/search_spec.rb +26 -8
- data/spec/thinking_sphinx/test_spec.rb +20 -0
- data/tasks/distribution.rb +4 -2
- metadata +53 -45
- data/features/thinking_sphinx/database.yml +0 -3
data/README.textile
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.3.
|
|
1
|
+
1.3.20
|
data/features/facets.feature
CHANGED
|
@@ -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:
|
|
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
|
|
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
|
+
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
require 'thinking_sphinx/test'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
data/lib/thinking_sphinx.rb
CHANGED
|
@@ -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
|
|
@@ -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,
|
|
12
|
-
|
|
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
|
|
58
|
-
enable_star exceptions
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
|
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
|
|
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
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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 =>
|
|
62
|
-
:max_matches =>
|
|
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
|
|
105
|
-
|
|
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
|
|
110
|
-
|
|
111
|
-
facet = facet_from_object(results.first, facet) if facet.is_a?(String)
|
|
122
|
+
return if search.empty?
|
|
112
123
|
|
|
113
|
-
|
|
114
|
-
facet_value = facet.value(result,
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
354
|
+
next if object.nil?
|
|
293
355
|
|
|
294
|
-
|
|
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?
|
|
362
|
+
next if object.nil?
|
|
306
363
|
|
|
307
364
|
match = match_hash object
|
|
308
365
|
next if match.nil?
|
|
309
366
|
|
|
310
|
-
object.
|
|
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?
|
|
373
|
+
next if object.nil?
|
|
319
374
|
|
|
320
375
|
match = match_hash object
|
|
321
376
|
next if match.nil?
|
|
322
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 => '
|
|
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.
|
|
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
|
-
|
|
6
|
-
|
|
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
|
-
|
|
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
|
-
|
|
159
|
-
and_yield(@person, @person.city.to_crc32, 1)
|
|
160
|
-
ThinkingSphinx.stub!(:
|
|
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
|
-
|
|
789
|
-
|
|
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
|
data/tasks/distribution.rb
CHANGED
|
@@ -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
|
-
-
|
|
7
|
-
-
|
|
8
|
-
|
|
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-
|
|
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
|