DrMark-thinking-sphinx 1.1.15 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.textile +22 -0
- data/VERSION.yml +4 -0
- data/lib/thinking_sphinx/active_record/scopes.rb +39 -0
- data/lib/thinking_sphinx/active_record.rb +27 -7
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +9 -3
- data/lib/thinking_sphinx/association.rb +4 -1
- data/lib/thinking_sphinx/attribute.rb +91 -30
- data/lib/thinking_sphinx/configuration.rb +51 -12
- data/lib/thinking_sphinx/deltas/datetime_delta.rb +2 -2
- data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
- data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +1 -1
- data/lib/thinking_sphinx/deltas/delayed_delta.rb +3 -0
- data/lib/thinking_sphinx/deploy/capistrano.rb +25 -8
- data/lib/thinking_sphinx/excerpter.rb +22 -0
- data/lib/thinking_sphinx/facet.rb +1 -1
- data/lib/thinking_sphinx/facet_search.rb +134 -0
- data/lib/thinking_sphinx/index.rb +2 -1
- data/lib/thinking_sphinx/rails_additions.rb +14 -0
- data/lib/thinking_sphinx/search.rb +599 -658
- data/lib/thinking_sphinx/search_methods.rb +421 -0
- data/lib/thinking_sphinx/source/internal_properties.rb +1 -1
- data/lib/thinking_sphinx/source/sql.rb +17 -13
- data/lib/thinking_sphinx/source.rb +6 -6
- data/lib/thinking_sphinx/tasks.rb +42 -8
- data/lib/thinking_sphinx.rb +82 -54
- data/rails/init.rb +14 -0
- data/spec/{unit → lib}/thinking_sphinx/active_record/delta_spec.rb +5 -5
- data/spec/{unit → lib}/thinking_sphinx/active_record/has_many_association_spec.rb +0 -0
- data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +96 -0
- data/spec/{unit → lib}/thinking_sphinx/active_record_spec.rb +51 -31
- data/spec/{unit → lib}/thinking_sphinx/association_spec.rb +4 -5
- data/spec/lib/thinking_sphinx/attribute_spec.rb +465 -0
- data/spec/{unit → lib}/thinking_sphinx/configuration_spec.rb +161 -29
- data/spec/{unit → lib}/thinking_sphinx/core/string_spec.rb +0 -0
- data/spec/lib/thinking_sphinx/excerpter_spec.rb +49 -0
- data/spec/lib/thinking_sphinx/facet_search_spec.rb +176 -0
- data/spec/{unit → lib}/thinking_sphinx/facet_spec.rb +24 -0
- data/spec/{unit → lib}/thinking_sphinx/field_spec.rb +8 -8
- data/spec/{unit → lib}/thinking_sphinx/index/builder_spec.rb +6 -2
- data/spec/{unit → lib}/thinking_sphinx/index/faux_column_spec.rb +0 -0
- data/spec/lib/thinking_sphinx/index_spec.rb +45 -0
- data/spec/{unit → lib}/thinking_sphinx/rails_additions_spec.rb +25 -5
- data/spec/lib/thinking_sphinx/search_methods_spec.rb +152 -0
- data/spec/lib/thinking_sphinx/search_spec.rb +960 -0
- data/spec/{unit → lib}/thinking_sphinx/source_spec.rb +63 -2
- data/spec/{unit → lib}/thinking_sphinx_spec.rb +32 -4
- data/tasks/distribution.rb +36 -35
- data/vendor/riddle/lib/riddle/client/message.rb +4 -3
- data/vendor/riddle/lib/riddle/client.rb +3 -0
- data/vendor/riddle/lib/riddle/configuration/section.rb +8 -2
- data/vendor/riddle/lib/riddle/controller.rb +17 -7
- data/vendor/riddle/lib/riddle.rb +1 -1
- metadata +79 -83
- data/lib/thinking_sphinx/active_record/search.rb +0 -57
- data/lib/thinking_sphinx/collection.rb +0 -148
- data/lib/thinking_sphinx/facet_collection.rb +0 -59
- data/lib/thinking_sphinx/search/facets.rb +0 -98
- data/spec/unit/thinking_sphinx/active_record/search_spec.rb +0 -107
- data/spec/unit/thinking_sphinx/attribute_spec.rb +0 -232
- data/spec/unit/thinking_sphinx/collection_spec.rb +0 -14
- data/spec/unit/thinking_sphinx/facet_collection_spec.rb +0 -64
- data/spec/unit/thinking_sphinx/index_spec.rb +0 -139
- data/spec/unit/thinking_sphinx/search_spec.rb +0 -130
@@ -4,32 +4,32 @@ describe ThinkingSphinx::Configuration do
|
|
4
4
|
describe "environment class method" do
|
5
5
|
before :each do
|
6
6
|
ThinkingSphinx::Configuration.send(:class_variable_set, :@@environment, nil)
|
7
|
-
|
7
|
+
|
8
8
|
ENV["RAILS_ENV"] = nil
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
it "should use the Merb environment value if set" do
|
12
12
|
unless defined?(Merb)
|
13
|
-
module Merb; end
|
13
|
+
module ::Merb; end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
ThinkingSphinx::Configuration.stub_method(:defined? => true)
|
17
|
-
Merb.
|
17
|
+
Merb.stub!(:environment => "merb_production")
|
18
18
|
ThinkingSphinx::Configuration.environment.should == "merb_production"
|
19
|
-
|
19
|
+
|
20
20
|
Object.send(:remove_const, :Merb)
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
it "should use the Rails environment value if set" do
|
24
24
|
ENV["RAILS_ENV"] = "rails_production"
|
25
25
|
ThinkingSphinx::Configuration.environment.should == "rails_production"
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
it "should default to development" do
|
29
29
|
ThinkingSphinx::Configuration.environment.should == "development"
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
describe "parse_config method" do
|
34
34
|
before :each do
|
35
35
|
@settings = {
|
@@ -48,89 +48,221 @@ describe ThinkingSphinx::Configuration do
|
|
48
48
|
"morphology" => "stem_ru",
|
49
49
|
"charset_type" => "latin1",
|
50
50
|
"charset_table" => "table",
|
51
|
-
"ignore_chars" => "e"
|
51
|
+
"ignore_chars" => "e",
|
52
|
+
"searchd_binary_name" => "sphinx-searchd",
|
53
|
+
"indexer_binary_name" => "sphinx-indexer"
|
52
54
|
}
|
53
55
|
}
|
54
|
-
|
56
|
+
|
55
57
|
open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
|
56
58
|
f.write YAML.dump(@settings)
|
57
59
|
end
|
58
60
|
end
|
59
|
-
|
61
|
+
|
60
62
|
it "should use the accessors to set the configuration values" do
|
61
63
|
config = ThinkingSphinx::Configuration.instance
|
62
64
|
config.send(:parse_config)
|
63
|
-
|
65
|
+
|
64
66
|
%w(config_file searchd_log_file query_log_file pid_file searchd_file_path
|
65
|
-
address port).each do |key|
|
67
|
+
address port searchd_binary_name indexer_binary_name).each do |key|
|
66
68
|
config.send(key).should == @settings["development"][key]
|
67
69
|
end
|
68
70
|
end
|
69
|
-
|
71
|
+
|
70
72
|
after :each do
|
71
73
|
FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
|
72
74
|
end
|
73
75
|
end
|
74
|
-
|
76
|
+
|
77
|
+
describe "block configuration" do
|
78
|
+
it "should let the user set-up a custom app_root" do
|
79
|
+
ThinkingSphinx::Configuration.configure do |config|
|
80
|
+
config.app_root = "/here/somewhere"
|
81
|
+
end
|
82
|
+
ThinkingSphinx::Configuration.instance.app_root.should == "/here/somewhere"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
75
86
|
describe "initialisation" do
|
76
87
|
it "should have a default bin_path of nothing" do
|
77
88
|
ThinkingSphinx::Configuration.instance.bin_path.should == ""
|
78
89
|
end
|
79
|
-
|
90
|
+
|
80
91
|
it "should append a / to bin_path if one is supplied" do
|
81
92
|
@settings = {
|
82
93
|
"development" => {
|
83
94
|
"bin_path" => "path/to/somewhere"
|
84
95
|
}
|
85
96
|
}
|
86
|
-
|
97
|
+
|
87
98
|
open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
|
88
99
|
f.write YAML.dump(@settings)
|
89
100
|
end
|
90
|
-
|
101
|
+
|
91
102
|
ThinkingSphinx::Configuration.instance.send(:parse_config)
|
92
103
|
ThinkingSphinx::Configuration.instance.bin_path.should match(/\/$/)
|
104
|
+
|
105
|
+
FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
|
93
106
|
end
|
94
107
|
end
|
95
|
-
|
108
|
+
|
109
|
+
describe "index options" do
|
110
|
+
before :each do
|
111
|
+
@settings = {
|
112
|
+
"development" => {"disable_range" => true}
|
113
|
+
}
|
114
|
+
|
115
|
+
open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
|
116
|
+
f.write YAML.dump(@settings)
|
117
|
+
end
|
118
|
+
|
119
|
+
@config = ThinkingSphinx::Configuration.instance
|
120
|
+
@config.send(:parse_config)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should collect disable_range" do
|
124
|
+
@config.index_options[:disable_range].should be_true
|
125
|
+
end
|
126
|
+
|
127
|
+
after :each do
|
128
|
+
FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#load_models" do
|
133
|
+
before :each do
|
134
|
+
@config = ThinkingSphinx::Configuration.instance
|
135
|
+
@config.model_directories = ['']
|
136
|
+
|
137
|
+
@file_name = 'a.rb'
|
138
|
+
@model_name_lower = 'a'
|
139
|
+
@class_name = 'A'
|
140
|
+
|
141
|
+
@file_name.stub!(:gsub).and_return(@model_name_lower)
|
142
|
+
@model_name_lower.stub!(:camelize).and_return(@class_name)
|
143
|
+
Dir.stub(:[]).and_return([@file_name])
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should load the files by guessing the file name" do
|
147
|
+
@class_name.should_receive(:constantize).and_return(true)
|
148
|
+
|
149
|
+
@config.load_models
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should not raise errors if the model name is nil" do
|
153
|
+
@file_name.stub!(:gsub).and_return(nil)
|
154
|
+
|
155
|
+
lambda {
|
156
|
+
@config.load_models
|
157
|
+
}.should_not raise_error
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should not raise errors if the file name does not represent a class name" do
|
161
|
+
@class_name.should_receive(:constantize).and_raise(NameError)
|
162
|
+
|
163
|
+
lambda {
|
164
|
+
@config.load_models
|
165
|
+
}.should_not raise_error
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should retry if the first pass fails and contains a directory" do
|
169
|
+
@model_name_lower.stub!(:gsub!).and_return(true, nil)
|
170
|
+
@class_name.stub(:constantize).and_raise(LoadError)
|
171
|
+
@model_name_lower.should_receive(:camelize).twice
|
172
|
+
|
173
|
+
lambda {
|
174
|
+
@config.load_models
|
175
|
+
}.should_not raise_error
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should catch database errors with a warning" do
|
179
|
+
@class_name.should_receive(:constantize).and_raise(Mysql::Error)
|
180
|
+
@config.should_receive(:puts).with('Warning: Error loading a.rb')
|
181
|
+
|
182
|
+
lambda {
|
183
|
+
@config.load_models
|
184
|
+
}.should_not raise_error
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
96
188
|
it "should insert set index options into the configuration file" do
|
97
189
|
config = ThinkingSphinx::Configuration.instance
|
98
190
|
ThinkingSphinx::Configuration::IndexOptions.each do |option|
|
99
191
|
config.index_options[option.to_sym] = "something"
|
100
192
|
config.build
|
101
|
-
|
193
|
+
|
102
194
|
file = open(config.config_file) { |f| f.read }
|
103
195
|
file.should match(/#{option}\s+= something/)
|
104
|
-
|
196
|
+
|
105
197
|
config.index_options[option.to_sym] = nil
|
106
198
|
end
|
107
199
|
end
|
108
|
-
|
200
|
+
|
109
201
|
it "should insert set source options into the configuration file" do
|
110
202
|
config = ThinkingSphinx::Configuration.instance
|
111
203
|
ThinkingSphinx::Configuration::SourceOptions.each do |option|
|
112
204
|
config.source_options[option.to_sym] = "something"
|
113
205
|
config.build
|
114
|
-
|
206
|
+
|
115
207
|
file = open(config.config_file) { |f| f.read }
|
116
208
|
file.should match(/#{option}\s+= something/)
|
117
|
-
|
209
|
+
|
118
210
|
config.source_options[option.to_sym] = nil
|
119
211
|
end
|
120
212
|
end
|
121
|
-
|
213
|
+
|
122
214
|
it "should set any explicit prefixed or infixed fields" do
|
123
215
|
file = open(ThinkingSphinx::Configuration.instance.config_file) { |f|
|
124
216
|
f.read
|
125
217
|
}
|
126
218
|
file.should match(/prefix_fields\s+= city/)
|
127
|
-
file.should match(/infix_fields\s+= state/)
|
219
|
+
file.should match(/infix_fields\s+= state/)
|
128
220
|
end
|
129
|
-
|
221
|
+
|
130
222
|
it "should not have prefix fields in indexes where nothing is set" do
|
131
223
|
file = open(ThinkingSphinx::Configuration.instance.config_file) { |f|
|
132
224
|
f.read
|
133
225
|
}
|
134
226
|
file.should_not match(/index alpha_core\s+\{\s+[^\}]*prefix_fields\s+=[^\}]*\}/m)
|
135
227
|
end
|
136
|
-
|
228
|
+
|
229
|
+
describe '#client' do
|
230
|
+
before :each do
|
231
|
+
@config = ThinkingSphinx::Configuration.instance
|
232
|
+
@config.address = 'domain.url'
|
233
|
+
@config.port = 3333
|
234
|
+
@config.configuration.searchd.max_matches = 100
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should return an instance of Riddle::Client" do
|
238
|
+
@config.client.should be_a(Riddle::Client)
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should use the configuration address" do
|
242
|
+
@config.client.server.should == 'domain.url'
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should use the configuration port" do
|
246
|
+
@config.client.port.should == 3333
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should use the configuration max matches" do
|
250
|
+
@config.client.max_matches.should == 100
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe '#models_by_crc' do
|
255
|
+
before :each do
|
256
|
+
@config = ThinkingSphinx::Configuration.instance
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should return a hash" do
|
260
|
+
@config.models_by_crc.should be_a(Hash)
|
261
|
+
end
|
262
|
+
|
263
|
+
it "should pair class names to their crc codes" do
|
264
|
+
@config.models_by_crc[Person.to_crc32].should == 'Person'
|
265
|
+
@config.models_by_crc[Alpha.to_crc32].should == 'Alpha'
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
File without changes
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Excerpter do
|
4
|
+
before :each do
|
5
|
+
@alpha = Alpha.find(:first)
|
6
|
+
@search = mock 'search', :excerpt_for => 'excerpted value'
|
7
|
+
@excerpter = ThinkingSphinx::Excerpter.new(@search, @alpha)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should not respond to id" do
|
11
|
+
@excerpter.should_not respond_to(:id)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#method_missing' do
|
15
|
+
it "should return the excerpt from Sphinx" do
|
16
|
+
@excerpter.name.should == 'excerpted value'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should send through the instance class to excerpt_for" do
|
20
|
+
@search.should_receive(:excerpt_for) do |string, model|
|
21
|
+
model.should == Alpha
|
22
|
+
end
|
23
|
+
|
24
|
+
@excerpter.name
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should use attribute methods for excerpts calls" do
|
28
|
+
@search.should_receive(:excerpt_for) do |string, model|
|
29
|
+
string.should == 'one'
|
30
|
+
end
|
31
|
+
|
32
|
+
@excerpter.name
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should use instance methods for excerpts calls" do
|
36
|
+
@search.should_receive(:excerpt_for) do |string, model|
|
37
|
+
string.should == 'ONE'
|
38
|
+
end
|
39
|
+
|
40
|
+
@excerpter.big_name
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should still raise an exception if no column or method exists" do
|
44
|
+
lambda {
|
45
|
+
@excerpter.foo
|
46
|
+
}.should raise_error(NoMethodError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::FacetSearch do
|
4
|
+
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])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should request all shared facets in a multi-model request by default" do
|
20
|
+
ThinkingSphinx.stub!(:search => [])
|
21
|
+
ThinkingSphinx::FacetSearch.new.facet_names.should == ['class_crc']
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should request all facets in a multi-model request if specified" do
|
25
|
+
ThinkingSphinx.stub!(:search => [])
|
26
|
+
ThinkingSphinx::FacetSearch.new(
|
27
|
+
:all_facets => true
|
28
|
+
).facet_names.should == [
|
29
|
+
'class_crc', 'city_facet', 'state_facet', 'birthday'
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
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
|
+
it "should use the system-set max_matches for limit on facet calls" do
|
92
|
+
ThinkingSphinx.should_receive(:search) do |options|
|
93
|
+
options[:max_matches].should == 10_000
|
94
|
+
options[:limit].should == 10_000
|
95
|
+
[]
|
96
|
+
end
|
97
|
+
|
98
|
+
ThinkingSphinx::FacetSearch.new
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should use the default max-matches if there is no explicit setting" do
|
102
|
+
@config.configuration.searchd.max_matches = nil
|
103
|
+
ThinkingSphinx.should_receive(:search) do |options|
|
104
|
+
options[:max_matches].should == 1000
|
105
|
+
options[:limit].should == 1000
|
106
|
+
[]
|
107
|
+
end
|
108
|
+
|
109
|
+
ThinkingSphinx::FacetSearch.new
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should ignore user-provided max_matches and limit on facet calls" do
|
113
|
+
ThinkingSphinx.should_receive(:search) do |options|
|
114
|
+
options[:max_matches].should == 10_000
|
115
|
+
options[:limit].should == 10_000
|
116
|
+
[]
|
117
|
+
end
|
118
|
+
|
119
|
+
ThinkingSphinx::FacetSearch.new(
|
120
|
+
:max_matches => 500,
|
121
|
+
:limit => 200
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should not use an explicit :page" do
|
126
|
+
ThinkingSphinx.should_receive(:search) do |options|
|
127
|
+
options[:page].should == 1
|
128
|
+
[]
|
129
|
+
end
|
130
|
+
|
131
|
+
ThinkingSphinx::FacetSearch.new(:page => 3)
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "conflicting facets" do
|
135
|
+
before :each do
|
136
|
+
@index = ThinkingSphinx::Index::Builder.generate(Alpha) do
|
137
|
+
indexes :name
|
138
|
+
has :value, :as => :city, :facet => true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
after :each do
|
143
|
+
Alpha.sphinx_facets.delete_at(-1)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should raise an error if searching with facets of same name but different type" do
|
147
|
+
lambda {
|
148
|
+
facets = ThinkingSphinx.facets :all_facets => true
|
149
|
+
}.should raise_error
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "#for" do
|
155
|
+
before do
|
156
|
+
@person = Person.find(:first)
|
157
|
+
@people = [@person]
|
158
|
+
@people.stub!(:each_with_groupby_and_count).
|
159
|
+
and_yield(@person, @person.city.to_crc32, 1)
|
160
|
+
ThinkingSphinx.stub!(:search => @people)
|
161
|
+
|
162
|
+
@facets = ThinkingSphinx::FacetSearch.new(
|
163
|
+
:classes => [Person], :facets => :city
|
164
|
+
)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should return the search results for the attribute and key pair" do
|
168
|
+
ThinkingSphinx.should_receive(:search) do |options|
|
169
|
+
options[:with].should have_key('city_facet')
|
170
|
+
options[:with]['city_facet'].should == @person.city.to_crc32
|
171
|
+
end
|
172
|
+
|
173
|
+
@facets.for(:city => @person.city)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -275,4 +275,28 @@ describe ThinkingSphinx::Facet do
|
|
275
275
|
ThinkingSphinx::Facet.new(attribute).type.should == :anything
|
276
276
|
end
|
277
277
|
end
|
278
|
+
|
279
|
+
describe "#value" do
|
280
|
+
before :each do
|
281
|
+
@index = ThinkingSphinx::Index.new(Friendship)
|
282
|
+
@source = ThinkingSphinx::Source.new(@index)
|
283
|
+
@field = ThinkingSphinx::Field.new(
|
284
|
+
@source, ThinkingSphinx::Index::FauxColumn.new(:person, :first_name)
|
285
|
+
)
|
286
|
+
@facet = ThinkingSphinx::Facet.new(@field)
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should return association values" do
|
290
|
+
person = Person.find(:first)
|
291
|
+
friendship = Friendship.new(:person => person)
|
292
|
+
|
293
|
+
@facet.value(friendship, 1).should == person.first_name
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should return nil if the association is nil" do
|
297
|
+
friendship = Friendship.new(:person => nil)
|
298
|
+
|
299
|
+
@facet.value(friendship, 1).should be_nil
|
300
|
+
end
|
301
|
+
end
|
278
302
|
end
|
@@ -85,15 +85,15 @@ describe ThinkingSphinx::Field do
|
|
85
85
|
@field.columns.each { |col| @field.associations[col] = [] }
|
86
86
|
@field.model = Person
|
87
87
|
|
88
|
-
@first_join = Object.
|
89
|
-
@
|
88
|
+
@first_join = Object.new
|
89
|
+
@first_join.stub!(:aliased_table_name => "tabular")
|
90
|
+
@second_join = Object.new
|
91
|
+
@second_join.stub!(:aliased_table_name => "data")
|
90
92
|
|
91
|
-
@first_assoc = ThinkingSphinx::Association.
|
92
|
-
|
93
|
-
|
94
|
-
@second_assoc
|
95
|
-
:join => @second_join, :has_column? => true
|
96
|
-
)
|
93
|
+
@first_assoc = ThinkingSphinx::Association.new nil, nil
|
94
|
+
@first_assoc.stub!(:join => @first_join, :has_column? => true)
|
95
|
+
@second_assoc = ThinkingSphinx::Association.new nil, nil
|
96
|
+
@second_assoc.stub!(:join => @second_join, :has_column? => true)
|
97
97
|
end
|
98
98
|
|
99
99
|
it "should return the column name if the column is a string" do
|
@@ -318,13 +318,17 @@ describe ThinkingSphinx::Index::Builder do
|
|
318
318
|
indexes first_name
|
319
319
|
|
320
320
|
set_property :charset_type => "utf16"
|
321
|
+
set_property :group_concat_max_len => 1024
|
321
322
|
end
|
322
323
|
end
|
323
324
|
|
324
|
-
it "should store the setting for the index" do
|
325
|
-
@index.local_options.length.should == 1
|
325
|
+
it "should store the index setting for the index" do
|
326
326
|
@index.local_options[:charset_type].should == "utf16"
|
327
327
|
end
|
328
|
+
|
329
|
+
it "should store non-Sphinx settings for the index" do
|
330
|
+
@index.local_options[:group_concat_max_len].should == 1024
|
331
|
+
end
|
328
332
|
end
|
329
333
|
|
330
334
|
describe "delta options" do
|
File without changes
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Index do
|
4
|
+
describe "prefix_fields method" do
|
5
|
+
before :each do
|
6
|
+
@index = ThinkingSphinx::Index.new(Person)
|
7
|
+
|
8
|
+
@field_a = ThinkingSphinx::Field.stub_instance(:prefixes => true)
|
9
|
+
@field_b = ThinkingSphinx::Field.stub_instance(:prefixes => false)
|
10
|
+
@field_c = ThinkingSphinx::Field.stub_instance(:prefixes => true)
|
11
|
+
|
12
|
+
@index.stub_method(:fields => [@field_a, @field_b, @field_c])
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return fields that are flagged as prefixed" do
|
16
|
+
@index.prefix_fields.should include(@field_a)
|
17
|
+
@index.prefix_fields.should include(@field_c)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not return fields that aren't flagged as prefixed" do
|
21
|
+
@index.prefix_fields.should_not include(@field_b)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "infix_fields method" do
|
26
|
+
before :each do
|
27
|
+
@index = ThinkingSphinx::Index.new(Person)
|
28
|
+
|
29
|
+
@field_a = ThinkingSphinx::Field.stub_instance(:infixes => true)
|
30
|
+
@field_b = ThinkingSphinx::Field.stub_instance(:infixes => false)
|
31
|
+
@field_c = ThinkingSphinx::Field.stub_instance(:infixes => true)
|
32
|
+
|
33
|
+
@index.stub_method(:fields => [@field_a, @field_b, @field_c])
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return fields that are flagged as infixed" do
|
37
|
+
@index.infix_fields.should include(@field_a)
|
38
|
+
@index.infix_fields.should include(@field_c)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should not return fields that aren't flagged as infixed" do
|
42
|
+
@index.infix_fields.should_not include(@field_b)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|