sunspot 1.0.5 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -0
- data/TODO +6 -5
- data/bin/sunspot-solr +4 -0
- data/installer/config/schema.yml +24 -0
- data/lib/sunspot/composite_setup.rb +14 -0
- data/lib/sunspot/dsl/adjustable.rb +47 -0
- data/lib/sunspot/dsl/fulltext.rb +23 -8
- data/lib/sunspot/dsl/function.rb +14 -0
- data/lib/sunspot/dsl/functional.rb +41 -0
- data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
- data/lib/sunspot/dsl/paginatable.rb +28 -0
- data/lib/sunspot/dsl/search.rb +1 -1
- data/lib/sunspot/dsl/{query.rb → standard_query.rb} +4 -49
- data/lib/sunspot/dsl.rb +3 -2
- data/lib/sunspot/field.rb +16 -2
- data/lib/sunspot/indexer.rb +1 -1
- data/lib/sunspot/installer/schema_builder.rb +1 -1
- data/lib/sunspot/installer/solrconfig_updater.rb +13 -0
- data/lib/sunspot/installer/task_helper.rb +1 -1
- data/lib/sunspot/query/abstract_field_facet.rb +5 -0
- data/lib/sunspot/query/boost_query.rb +5 -1
- data/lib/sunspot/query/{query.rb → common_query.rb} +26 -20
- data/lib/sunspot/query/composite_fulltext.rb +31 -0
- data/lib/sunspot/query/dismax.rb +45 -6
- data/lib/sunspot/query/function_query.rb +52 -0
- data/lib/sunspot/query/more_like_this.rb +60 -0
- data/lib/sunspot/query/more_like_this_query.rb +12 -0
- data/lib/sunspot/query/standard_query.rb +20 -0
- data/lib/sunspot/query/text_field_boost.rb +2 -0
- data/lib/sunspot/query.rb +3 -2
- data/lib/sunspot/search/abstract_search.rb +302 -0
- data/lib/sunspot/search/date_facet.rb +1 -1
- data/lib/sunspot/search/facet_row.rb +1 -1
- data/lib/sunspot/search/field_facet.rb +1 -1
- data/lib/sunspot/search/highlight.rb +1 -1
- data/lib/sunspot/search/hit.rb +1 -1
- data/lib/sunspot/search/more_like_this_search.rb +31 -0
- data/lib/sunspot/search/query_facet.rb +1 -1
- data/lib/sunspot/search/standard_search.rb +21 -0
- data/lib/sunspot/search.rb +3 -288
- data/lib/sunspot/server.rb +8 -4
- data/lib/sunspot/session.rb +30 -2
- data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +1 -1
- data/lib/sunspot/session_proxy/sharding_session_proxy.rb +9 -0
- data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +9 -2
- data/lib/sunspot/setup.rb +32 -3
- data/lib/sunspot/type.rb +74 -0
- data/lib/sunspot/util.rb +3 -2
- data/lib/sunspot/version.rb +1 -1
- data/lib/sunspot.rb +9 -1
- data/solr/solr/conf/schema.xml +12 -0
- data/solr/solr/conf/solrconfig.xml +6 -0
- data/spec/api/indexer/attributes_spec.rb +9 -3
- data/spec/api/indexer/fulltext_spec.rb +2 -2
- data/spec/api/indexer/removal_spec.rb +1 -1
- data/spec/api/query/advanced_manipulation_examples.rb +35 -0
- data/spec/api/query/{connectives_spec.rb → connectives_examples.rb} +19 -19
- data/spec/api/query/{dynamic_fields_spec.rb → dynamic_fields_examples.rb} +33 -17
- data/spec/api/query/{faceting_spec.rb → faceting_examples.rb} +146 -43
- data/spec/api/query/{fulltext_spec.rb → fulltext_examples.rb} +81 -47
- data/spec/api/query/function_spec.rb +70 -0
- data/spec/api/query/{highlighting_spec.rb → highlighting_examples.rb} +27 -27
- data/spec/api/query/{local_spec.rb → local_examples.rb} +5 -5
- data/spec/api/query/more_like_this_spec.rb +140 -0
- data/spec/api/query/{ordering_pagination_spec.rb → ordering_pagination_examples.rb} +16 -16
- data/spec/api/query/{scope_spec.rb → scope_examples.rb} +44 -61
- data/spec/api/query/standard_spec.rb +28 -0
- data/spec/api/query/{text_field_scoping_spec.rb → text_field_scoping_examples.rb} +5 -5
- data/spec/api/search/dynamic_fields_spec.rb +6 -0
- data/spec/api/search/faceting_spec.rb +10 -10
- data/spec/api/search/hits_spec.rb +1 -1
- data/spec/api/search/results_spec.rb +10 -0
- data/spec/api/server_spec.rb +6 -0
- data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +2 -2
- data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +17 -0
- data/spec/api/spec_helper.rb +2 -0
- data/spec/helpers/query_helper.rb +25 -0
- data/spec/helpers/search_helper.rb +4 -0
- data/spec/integration/faceting_spec.rb +8 -0
- data/spec/integration/keyword_search_spec.rb +75 -3
- data/spec/integration/local_search_spec.rb +1 -1
- data/spec/integration/more_like_this_spec.rb +43 -0
- data/spec/mocks/comment.rb +1 -1
- data/spec/mocks/connection.rb +27 -12
- data/spec/mocks/post.rb +5 -4
- data/spec/spec_helper.rb +4 -21
- data/tasks/gemspec.rake +1 -1
- metadata +39 -27
- data/spec/api/query/adjust_params_spec.rb +0 -37
- data/spec/api/query/facet_local_params_spec.rb +0 -103
@@ -53,7 +53,7 @@ describe 'faceting', :type => :search do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'returns float facet' do
|
56
|
-
stub_facet(:
|
56
|
+
stub_facet(:average_rating_ft, '9.3' => 2, '1.1' => 1)
|
57
57
|
result = session.search Post do
|
58
58
|
facet :average_rating
|
59
59
|
end
|
@@ -62,7 +62,7 @@ describe 'faceting', :type => :search do
|
|
62
62
|
|
63
63
|
it 'returns time facet' do
|
64
64
|
stub_facet(
|
65
|
-
:
|
65
|
+
:published_at_dt,
|
66
66
|
'2009-04-07T20:25:23Z' => 3,
|
67
67
|
'2009-04-07T20:26:19Z' => 2,
|
68
68
|
'2050-04-07T20:27:15Z' => 1
|
@@ -181,7 +181,7 @@ describe 'faceting', :type => :search do
|
|
181
181
|
end
|
182
182
|
|
183
183
|
it 'returns date range facet' do
|
184
|
-
stub_date_facet(:
|
184
|
+
stub_date_facet(:published_at_dt, 60*60*24, '2009-07-08T04:00:00Z' => 2, '2009-07-07T04:00:00Z' => 1)
|
185
185
|
start_time = Time.utc(2009, 7, 7, 4)
|
186
186
|
end_time = start_time + 2*24*60*60
|
187
187
|
result = session.search(Post) { facet(:published_at, :time_range => start_time..end_time) }
|
@@ -191,7 +191,7 @@ describe 'faceting', :type => :search do
|
|
191
191
|
end
|
192
192
|
|
193
193
|
it 'returns date range facet sorted by count' do
|
194
|
-
stub_date_facet(:
|
194
|
+
stub_date_facet(:published_at_dt, 60*60*24, '2009-07-08T04:00:00Z' => 2, '2009-07-07T04:00:00Z' => 1)
|
195
195
|
start_time = Time.utc(2009, 7, 7, 4)
|
196
196
|
end_time = start_time + 2*24*60*60
|
197
197
|
result = session.search(Post) { facet(:published_at, :time_range => start_time..end_time, :sort => :count) }
|
@@ -202,8 +202,8 @@ describe 'faceting', :type => :search do
|
|
202
202
|
|
203
203
|
it 'returns query facet' do
|
204
204
|
stub_query_facet(
|
205
|
-
'
|
206
|
-
'
|
205
|
+
'average_rating_ft:[3\.0 TO 5\.0]' => 3,
|
206
|
+
'average_rating_ft:[1\.0 TO 3\.0]' => 1
|
207
207
|
)
|
208
208
|
search = session.search(Post) do
|
209
209
|
facet :average_rating do
|
@@ -236,10 +236,10 @@ describe 'faceting', :type => :search do
|
|
236
236
|
|
237
237
|
before :each do
|
238
238
|
stub_query_facet(
|
239
|
-
'
|
240
|
-
'
|
241
|
-
'
|
242
|
-
'
|
239
|
+
'average_rating_ft:[1\.0 TO 2\.0]' => 2,
|
240
|
+
'average_rating_ft:[2\.0 TO 3\.0]' => 3,
|
241
|
+
'average_rating_ft:[3\.0 TO 4\.0]' => 1,
|
242
|
+
'average_rating_ft:[4\.0 TO 5\.0]' => 0
|
243
243
|
)
|
244
244
|
end
|
245
245
|
|
@@ -107,7 +107,7 @@ describe 'hits', :type => :search do
|
|
107
107
|
end
|
108
108
|
|
109
109
|
it 'should return stored text fields' do
|
110
|
-
stub_full_results('instance' => Post.new, '
|
110
|
+
stub_full_results('instance' => Post.new, 'body_textsv' => 'Body')
|
111
111
|
session.search(Post, Namespaced::Comment).hits.first.stored(:body).should == 'Body'
|
112
112
|
end
|
113
113
|
|
@@ -25,6 +25,11 @@ describe 'search results', :type => :search do
|
|
25
25
|
session.search(Post, Namespaced::Comment).results.should == results
|
26
26
|
end
|
27
27
|
|
28
|
+
it 'gracefully returns empty results when response is nil' do
|
29
|
+
stub_nil_results
|
30
|
+
session.search(Post).results.should == []
|
31
|
+
end
|
32
|
+
|
28
33
|
if ENV['USE_WILL_PAGINATE']
|
29
34
|
|
30
35
|
it 'returns search total as attribute of results' do
|
@@ -50,6 +55,11 @@ describe 'search results', :type => :search do
|
|
50
55
|
session.search(Post) { paginate(:page => 1) }.total.should == 4
|
51
56
|
end
|
52
57
|
|
58
|
+
it 'returns total for nil search' do
|
59
|
+
stub_nil_results
|
60
|
+
session.search(Post).total.should == 0
|
61
|
+
end
|
62
|
+
|
53
63
|
it 'returns available results if some results are not available from data store' do
|
54
64
|
posts = [Post.new, Post.new]
|
55
65
|
posts.last.destroy
|
data/spec/api/server_spec.rb
CHANGED
@@ -46,6 +46,12 @@ describe Sunspot::Server do
|
|
46
46
|
@server.run
|
47
47
|
end
|
48
48
|
|
49
|
+
it 'runs Solr with specified Solr jar' do
|
50
|
+
@server.solr_jar = SUNSPOT_START_JAR
|
51
|
+
FileUtils.should_receive(:cd).with(File.dirname(SUNSPOT_START_JAR))
|
52
|
+
@server.run
|
53
|
+
end
|
54
|
+
|
49
55
|
describe 'with logging' do
|
50
56
|
before :each do
|
51
57
|
@server.log_level = 'info'
|
@@ -7,8 +7,8 @@ describe Sunspot::SessionProxy::MasterSlaveSessionProxy do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
{
|
10
|
-
:master_session => Sunspot::Session.public_instance_methods(false) - [:search, 'search', :new_search, 'new_search', :config, 'config'],
|
11
|
-
:slave_session => [:search, :new_search]
|
10
|
+
:master_session => Sunspot::Session.public_instance_methods(false) - [:search, 'search', :new_search, 'new_search', :more_like_this, 'more_like_this', :new_more_like_this, 'new_more_like_this', :config, 'config'],
|
11
|
+
:slave_session => [:search, :new_search, :more_like_this, :new_more_like_this]
|
12
12
|
}.each_pair do |delegate, methods|
|
13
13
|
methods.each do |method|
|
14
14
|
it "should delegate #{method} to #{delegate}" do
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
require 'weakref'
|
2
3
|
|
3
4
|
describe Sunspot::SessionProxy::ThreadLocalSessionProxy do
|
4
5
|
before :each do
|
@@ -19,6 +20,22 @@ describe Sunspot::SessionProxy::ThreadLocalSessionProxy do
|
|
19
20
|
session1.should_not eql(session2)
|
20
21
|
end
|
21
22
|
|
23
|
+
it 'should not have the same session for the same thread in different proxy instances' do
|
24
|
+
proxy2 = Sunspot::SessionProxy::ThreadLocalSessionProxy.new(@config)
|
25
|
+
@proxy.session.should_not eql(proxy2.session)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should garbage collect session instance when proxy dereferenced' do
|
29
|
+
ref = WeakRef.new(@proxy.session)
|
30
|
+
@proxy = nil
|
31
|
+
GC.start
|
32
|
+
# need to do this a second time since the reference to the session is
|
33
|
+
# destroyed in the finalizer during the first GC run, and thus isn't picked
|
34
|
+
# up by that run.
|
35
|
+
GC.start
|
36
|
+
lambda { ref.inspect }.should raise_error(WeakRef::RefError)
|
37
|
+
end
|
38
|
+
|
22
39
|
(Sunspot::Session.public_instance_methods(false) - ['config', :config]).each do |method|
|
23
40
|
it "should delegate #{method.inspect} to its session" do
|
24
41
|
args = Array.new(Sunspot::Session.instance_method(method).arity.abs) do
|
data/spec/api/spec_helper.rb
CHANGED
@@ -10,4 +10,29 @@ module QueryHelper
|
|
10
10
|
def session
|
11
11
|
@session ||= Sunspot::Session.new(config, connection)
|
12
12
|
end
|
13
|
+
|
14
|
+
def get_filter_tag(boolean_query)
|
15
|
+
connection.searches.last[:fq].each do |fq|
|
16
|
+
if match = fq.match(/^\{!tag=(.+)\}#{Regexp.escape(boolean_query)}$/)
|
17
|
+
return match[1]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def subqueries(param)
|
24
|
+
q = connection.searches.last[:q]
|
25
|
+
subqueries = []
|
26
|
+
subqueries = q.scan(%r(_query_:"\{!dismax (.*?)\}(.*?)"))
|
27
|
+
subqueries.map do |subquery|
|
28
|
+
params = {}
|
29
|
+
subquery[0].scan(%r((\S+?)='(.+?)')) do |key, value|
|
30
|
+
params[key.to_sym] = value
|
31
|
+
end
|
32
|
+
unless subquery[1].empty?
|
33
|
+
params[:v] = subquery[1]
|
34
|
+
end
|
35
|
+
params
|
36
|
+
end
|
37
|
+
end
|
13
38
|
end
|
@@ -109,6 +109,14 @@ describe 'search faceting' do
|
|
109
109
|
search.facet(:title).rows.map { |row| row.value }.should == %w(four three two one)
|
110
110
|
end
|
111
111
|
|
112
|
+
it 'should limit facet values by prefix' do
|
113
|
+
search = Sunspot.search(Post) do
|
114
|
+
with :blog_id, 1
|
115
|
+
facet :title, :prefix => 't'
|
116
|
+
end
|
117
|
+
search.facet(:title).rows.map { |row| row.value }.sort.should == %w(three two)
|
118
|
+
end
|
119
|
+
|
112
120
|
it 'should return :all facet' do
|
113
121
|
search = Sunspot.search(Post) do
|
114
122
|
with :blog_id, 1
|
@@ -10,7 +10,7 @@ describe 'keyword search' do
|
|
10
10
|
@posts << Post.new(:title => 'A nail abbreviates the recovering insight outside the moron',
|
11
11
|
:body => 'The interpreted strain scans the buffer around the upper temper')
|
12
12
|
@posts << Post.new(:title => 'The toast abbreviates the recovering spirit',
|
13
|
-
:body => 'Does the wind interpret the buffer, moron?')
|
13
|
+
:body => 'Does the host\'s wind interpret the buffer, moron?')
|
14
14
|
Sunspot.index!(*@posts)
|
15
15
|
@comment = Namespaced::Comment.new(:body => 'Hey there where ya goin, not exactly knowin, who says you have to call just one place toast.')
|
16
16
|
Sunspot.index!(@comment)
|
@@ -47,6 +47,45 @@ describe 'keyword search' do
|
|
47
47
|
end.results
|
48
48
|
results.should == [@posts[1]]
|
49
49
|
end
|
50
|
+
|
51
|
+
it 'matches multiple keywords on different fields using subqueries' do
|
52
|
+
search = Sunspot.search(Post) do
|
53
|
+
keywords 'moron', :fields => [:title]
|
54
|
+
keywords 'wind', :fields => [:body]
|
55
|
+
end
|
56
|
+
search.results.should == []
|
57
|
+
|
58
|
+
search = Sunspot.search(Post) do
|
59
|
+
keywords 'moron', :fields => [:title]
|
60
|
+
keywords 'buffer', :fields => [:body]
|
61
|
+
end
|
62
|
+
search.results.should == [@posts[1]]
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'matches multiple keywords with escaped characters' do
|
66
|
+
search = Sunspot.search(Post) do
|
67
|
+
keywords 'spirit', :fields => [:title]
|
68
|
+
keywords 'host\'s', :fields => [:body]
|
69
|
+
end
|
70
|
+
search.results.should == [@posts[2]]
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'matches multiple keywords with phrase-based search' do
|
74
|
+
search = Sunspot.search(Post) do
|
75
|
+
keywords 'spirit', :fields => [:title]
|
76
|
+
keywords '"interpret the buffer"', :fields => [:body]
|
77
|
+
keywords '"does the"', :fields => [:body]
|
78
|
+
end
|
79
|
+
search.results.should == [@posts[2]]
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'matches multiple keywords different options' do
|
83
|
+
search = Sunspot.search(Post) do
|
84
|
+
keywords 'insufficient nonexistent', :fields => [:title], :minimum_match => 1
|
85
|
+
keywords 'wind does', :fields => [:body], :minimum_match => 2
|
86
|
+
end
|
87
|
+
search.results.should == [@posts[0]]
|
88
|
+
end
|
50
89
|
end
|
51
90
|
|
52
91
|
describe 'with field boost' do
|
@@ -75,7 +114,7 @@ describe 'keyword search' do
|
|
75
114
|
|
76
115
|
it 'should assign a higher score to the higher-boosted document' do
|
77
116
|
search = Sunspot.search(Post) { keywords 'test' }
|
78
|
-
search.hits.map { |hit| hit.primary_key }.should ==
|
117
|
+
search.hits.map { |hit| hit.primary_key }.should ==
|
79
118
|
@posts.map { |post| post.id.to_s }
|
80
119
|
search.hits.first.score.should > search.hits.last.score
|
81
120
|
end
|
@@ -110,7 +149,7 @@ describe 'keyword search' do
|
|
110
149
|
hits.first.instance.should == @comments.first
|
111
150
|
hits.first.score.should > hits.last.score
|
112
151
|
end
|
113
|
-
|
152
|
+
|
114
153
|
it 'assigns a higher score to documents in which the search terms appear in a higher boosted phrase field' do
|
115
154
|
hits = Sunspot.search(Namespaced::Comment) do
|
116
155
|
keywords 'test text' do
|
@@ -242,4 +281,37 @@ describe 'keyword search' do
|
|
242
281
|
@sorted_hits[4].score.should == @sorted_hits[5].score
|
243
282
|
end
|
244
283
|
end
|
284
|
+
|
285
|
+
describe 'with function queries' do
|
286
|
+
before :each do
|
287
|
+
Sunspot.remove_all
|
288
|
+
end
|
289
|
+
|
290
|
+
after :each do
|
291
|
+
@search.results.should == @posts
|
292
|
+
@search.hits.first.score.should > @search.hits.last.score
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'boosts via function query with float' do
|
296
|
+
@posts = [Post.new(:title => 'test', :ratings_average => 4.0),
|
297
|
+
Post.new(:title => 'test', :ratings_average => 2.0)]
|
298
|
+
Sunspot.index!(@posts)
|
299
|
+
@search = Sunspot.search(Post) do
|
300
|
+
keywords('test') do
|
301
|
+
boost function { :average_rating }
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
it 'boosts via function query with date' do
|
307
|
+
@posts = [Post.new(:title => 'test', :published_at => Time.now),
|
308
|
+
Post.new(:title => 'test', :published_at => Time.now - 60*60*24*31*6)] # roughly six months ago
|
309
|
+
Sunspot.index!(@posts)
|
310
|
+
@search = Sunspot.search(Post) do
|
311
|
+
keywords('test') do
|
312
|
+
boost function { recip(ms(Time.now, :published_at), 3.16e-11, 1, 1) }
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
245
317
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'more_like_this' do
|
4
|
+
before :all do
|
5
|
+
Sunspot.remove_all
|
6
|
+
@posts = [
|
7
|
+
Post.new(:body => "one two three", :tags => %w(ruby sunspot rsolr)),
|
8
|
+
Post.new(:body => "four five six", :tags => %w(ruby solr lucene)),
|
9
|
+
Post.new(:body => "two three four", :tags => %w(python sqlalchemy)),
|
10
|
+
Post.new(:body => "three four five", :tags => %w(ruby sunspot mat)),
|
11
|
+
Post.new(:body => "six seven eight", :tags => %w(bogus airplane))
|
12
|
+
]
|
13
|
+
Sunspot.index!(@posts)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should return results for all MLT fields' do
|
17
|
+
Sunspot.more_like_this(@posts.first).results.to_set.should == @posts[1..3].to_set
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should return results for specified text field' do
|
21
|
+
Sunspot.more_like_this(@posts.first) do
|
22
|
+
fields :body
|
23
|
+
end.results.to_set.should == @posts[2..3].to_set
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should return empty result set if no results' do
|
27
|
+
Sunspot.more_like_this(@posts.last) do
|
28
|
+
with(:title, 'bogus')
|
29
|
+
end.results.should == []
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'when non-indexed object searched' do
|
33
|
+
before(:each) { @mlt = Sunspot.more_like_this(Post.new) }
|
34
|
+
|
35
|
+
it 'should return empty result set' do
|
36
|
+
@mlt.results.should == []
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'shoult return a total of 0' do
|
40
|
+
@mlt.total.should == 0
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/mocks/comment.rb
CHANGED
data/spec/mocks/connection.rb
CHANGED
@@ -24,11 +24,14 @@ module Mock
|
|
24
24
|
class Connection
|
25
25
|
attr_reader :adds, :commits, :searches, :message, :opts, :deletes_by_query
|
26
26
|
attr_accessor :response
|
27
|
+
attr_writer :expected_handler
|
28
|
+
undef_method :select # annoyingly defined on Object
|
27
29
|
|
28
30
|
def initialize(opts = {})
|
29
31
|
@opts = opts
|
30
32
|
@message = OpenStruct.new
|
31
33
|
@adds, @deletes, @deletes_by_query, @commits, @searches = Array.new(5) { [] }
|
34
|
+
@expected_handler = :select
|
32
35
|
end
|
33
36
|
|
34
37
|
def add(documents)
|
@@ -47,11 +50,18 @@ module Mock
|
|
47
50
|
@commits << Time.now
|
48
51
|
end
|
49
52
|
|
50
|
-
def
|
51
|
-
|
53
|
+
def request(path, params)
|
54
|
+
unless path == "/#{@expected_handler}"
|
55
|
+
raise ArgumentError, "Expected request to #{@expected_handler} request handler"
|
56
|
+
end
|
57
|
+
@searches << @last_search = params
|
52
58
|
@response || {}
|
53
59
|
end
|
54
60
|
|
61
|
+
def method_missing(method, *args, &block)
|
62
|
+
request("/#{method}", *args)
|
63
|
+
end
|
64
|
+
|
55
65
|
def has_add_with?(*documents)
|
56
66
|
@adds.any? do |add|
|
57
67
|
documents.all? do |document|
|
@@ -81,16 +91,7 @@ module Mock
|
|
81
91
|
end
|
82
92
|
|
83
93
|
def has_last_search_with?(params)
|
84
|
-
|
85
|
-
if params.respond_to?(:all?)
|
86
|
-
params.all? do |key, value|
|
87
|
-
if @last_search.has_key?(key)
|
88
|
-
@last_search[key] == value
|
89
|
-
end
|
90
|
-
end
|
91
|
-
else
|
92
|
-
@last_search.has_key?(params)
|
93
|
-
end
|
94
|
+
with?(@last_search, params) if @last_search
|
94
95
|
end
|
95
96
|
|
96
97
|
def has_last_search_including?(key, *values)
|
@@ -103,5 +104,19 @@ module Mock
|
|
103
104
|
end
|
104
105
|
end
|
105
106
|
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def with?(request, params)
|
111
|
+
if params.respond_to?(:all?)
|
112
|
+
params.all? do |key, value|
|
113
|
+
if request.has_key?(key)
|
114
|
+
request[key] == value
|
115
|
+
end
|
116
|
+
end
|
117
|
+
else
|
118
|
+
request.has_key?(params)
|
119
|
+
end
|
120
|
+
end
|
106
121
|
end
|
107
122
|
end
|
data/spec/mocks/post.rb
CHANGED
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), 'super_class')
|
|
3
3
|
|
4
4
|
class Post < SuperClass
|
5
5
|
attr_accessor :title, :body, :blog_id, :published_at, :ratings_average,
|
6
|
-
:author_name, :featured, :expire_date, :coordinates
|
6
|
+
:author_name, :featured, :expire_date, :coordinates, :tags
|
7
7
|
alias_method :featured?, :featured
|
8
8
|
|
9
9
|
def category_ids
|
@@ -32,15 +32,16 @@ end
|
|
32
32
|
|
33
33
|
Sunspot.setup(Post) do
|
34
34
|
text :title, :boost => 2
|
35
|
-
text :body, :stored => true
|
35
|
+
text :body, :stored => true, :more_like_this => true
|
36
36
|
text :backwards_title do
|
37
37
|
title.reverse if title
|
38
38
|
end
|
39
|
+
text :tags, :more_like_this => true
|
39
40
|
string :title, :stored => true
|
40
41
|
integer :blog_id, :references => Blog
|
41
42
|
integer :category_ids, :multiple => true
|
42
|
-
float :average_rating, :using => :ratings_average
|
43
|
-
time :published_at
|
43
|
+
float :average_rating, :using => :ratings_average, :trie => true
|
44
|
+
time :published_at, :trie => true
|
44
45
|
date :expire_date
|
45
46
|
boolean :featured, :using => :featured?
|
46
47
|
string :sort_title do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
using_gems = false
|
2
|
-
|
3
1
|
if rsolr_gem_version = ENV['RSOLR_GEM_VERSION']
|
4
2
|
STDERR.puts("Forcing rsolr gem version #{rsolr_gem_version}")
|
5
3
|
using_gems = true
|
@@ -7,35 +5,20 @@ if rsolr_gem_version = ENV['RSOLR_GEM_VERSION']
|
|
7
5
|
gem 'rsolr', rsolr_gem_version
|
8
6
|
end
|
9
7
|
|
8
|
+
require 'ostruct'
|
10
9
|
begin
|
11
10
|
require 'spec'
|
12
|
-
begin
|
13
|
-
require 'ruby-debug'
|
14
|
-
rescue LoadError => e
|
15
|
-
if using_gems
|
16
|
-
module Kernel
|
17
|
-
def debugger
|
18
|
-
STDERR.puts('Debugger is not available')
|
19
|
-
end
|
20
|
-
end
|
21
|
-
else
|
22
|
-
raise(e)
|
23
|
-
end
|
24
|
-
end
|
25
11
|
if ENV['USE_WILL_PAGINATE']
|
26
12
|
require 'will_paginate'
|
27
13
|
require 'will_paginate/collection'
|
28
14
|
end
|
29
15
|
rescue LoadError => e
|
30
|
-
require 'rubygems'
|
31
|
-
if using_gems
|
32
|
-
raise(e)
|
33
|
-
else
|
34
|
-
using_gems = true
|
16
|
+
if require 'rubygems'
|
35
17
|
retry
|
18
|
+
else
|
19
|
+
raise(e)
|
36
20
|
end
|
37
21
|
end
|
38
|
-
require 'ostruct'
|
39
22
|
|
40
23
|
unless gem_name = ENV['SUNSPOT_TEST_GEM']
|
41
24
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
data/tasks/gemspec.rake
CHANGED
@@ -10,7 +10,7 @@ Sunspot::GemTasks.new(:build => :copy_rdoc) do |s|
|
|
10
10
|
s.description = <<TEXT
|
11
11
|
Sunspot is a library providing a powerful, all-ruby API for the Solr search engine. Sunspot manages the configuration of persistent Ruby classes for search and indexing and exposes Solr's most powerful features through a collection of DSLs. Complex search operations can be performed without hand-writing any boolean queries or building Solr parameters by hand.
|
12
12
|
TEXT
|
13
|
-
s.authors = ['Mat Brown', 'Peer Allan', 'Dmitriy Dzema', 'Benjamin Krause', 'Marcel de Graaf', 'Brandon Keepers', 'Peter Berkenbosch', 'Brian Atkinson', 'Tom Coleman', 'Matt Mitchell', 'Nathan Beyer']
|
13
|
+
s.authors = ['Mat Brown', 'Peer Allan', 'Dmitriy Dzema', 'Benjamin Krause', 'Marcel de Graaf', 'Brandon Keepers', 'Peter Berkenbosch', 'Brian Atkinson', 'Tom Coleman', 'Matt Mitchell', 'Nathan Beyer', 'Kieran Topping', 'Nicolas Braem', 'Jeremy Ashkenas']
|
14
14
|
s.rubyforge_project = 'sunspot'
|
15
15
|
s.files = FileList['[A-Z]*', '{bin,installer,lib,spec,tasks,templates}/**/*', 'solr/{etc,lib,webapps}/**/*', 'solr/solr/{conf,lib}/*', 'solr/start.jar']
|
16
16
|
s.add_runtime_dependency 'rsolr', '0.12.1'
|