outoftime-sunspot 0.0.1 → 0.0.2
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/History.txt +9 -6
- data/README.rdoc +45 -13
- data/Rakefile +5 -21
- data/VERSION.yml +4 -0
- data/bin/sunspot-solr +39 -0
- data/lib/sunspot/builder.rb +78 -0
- data/lib/sunspot/dsl/fields.rb +39 -0
- data/lib/sunspot/dsl/query.rb +32 -0
- data/lib/sunspot/dsl/scope.rb +35 -0
- data/lib/sunspot/dsl.rb +3 -0
- data/lib/sunspot/query.rb +9 -20
- data/lib/sunspot/search.rb +8 -25
- data/lib/sunspot.rb +2 -3
- data/solr/etc/jetty.xml +10 -4
- data/solr/solr/conf/{admin-extra.html → elevate.xml} +18 -13
- data/solr/solr/conf/solrconfig.xml +369 -67
- data/solr/webapps/solr.war +0 -0
- data/spec/api/build_search_spec.rb +195 -0
- data/spec/api/indexer_spec.rb +112 -0
- data/spec/api/search_retrieval_spec.rb +59 -0
- data/spec/api/session_spec.rb +44 -0
- data/spec/api/spec_helper.rb +1 -0
- data/spec/api/standard_search_builder_spec.rb +76 -0
- data/{test → spec}/custom_expectation.rb +0 -0
- data/{test/integration/test_field_types.rb → spec/integration/field_types_spec.rb} +9 -9
- data/{test/integration/test_keyword_search.rb → spec/integration/keyword_search_spec.rb} +5 -5
- data/spec/integration/spec_helper.rb +1 -0
- data/{test → spec}/integration/test_pagination.rb +5 -5
- data/{test → spec}/mocks/base_class.rb +0 -0
- data/{test → spec}/mocks/comment.rb +0 -0
- data/{test → spec}/mocks/mock_adapter.rb +0 -0
- data/{test → spec}/mocks/post.rb +0 -0
- data/{test/test_helper.rb → spec/spec_helper.rb} +6 -12
- data/tasks/gemspec.rake +18 -0
- data/tasks/rcov.rake +27 -5
- data/tasks/spec.rake +21 -0
- metadata +90 -125
- data/Manifest.txt +0 -104
- data/PostInstall.txt +0 -7
- data/config/hoe.rb +0 -74
- data/config/requirements.rb +0 -15
- data/lib/sunspot/conditions.rb +0 -50
- data/lib/sunspot/conditions_builder.rb +0 -37
- data/lib/sunspot/field_builder.rb +0 -37
- data/lib/sunspot/query_builder.rb +0 -30
- data/lib/sunspot/scope_builder.rb +0 -33
- data/lib/sunspot/version.rb +0 -10
- data/setup.rb +0 -1585
- data/solr/README.txt +0 -36
- data/solr/exampledocs/books.csv +0 -11
- data/solr/exampledocs/hd.xml +0 -46
- data/solr/exampledocs/ipod_other.xml +0 -50
- data/solr/exampledocs/ipod_video.xml +0 -35
- data/solr/exampledocs/mem.xml +0 -58
- data/solr/exampledocs/monitor.xml +0 -31
- data/solr/exampledocs/monitor2.xml +0 -30
- data/solr/exampledocs/mp500.xml +0 -39
- data/solr/exampledocs/post.jar +0 -0
- data/solr/exampledocs/post.sh +0 -28
- data/solr/exampledocs/sd500.xml +0 -33
- data/solr/exampledocs/solr.xml +0 -38
- data/solr/exampledocs/spellchecker.xml +0 -58
- data/solr/exampledocs/utf8-example.xml +0 -42
- data/solr/exampledocs/vidcard.xml +0 -52
- data/solr/solr/README.txt +0 -52
- data/solr/solr/bin/abc +0 -176
- data/solr/solr/bin/abo +0 -176
- data/solr/solr/bin/backup +0 -108
- data/solr/solr/bin/backupcleaner +0 -142
- data/solr/solr/bin/commit +0 -128
- data/solr/solr/bin/optimize +0 -129
- data/solr/solr/bin/readercycle +0 -129
- data/solr/solr/bin/rsyncd-disable +0 -77
- data/solr/solr/bin/rsyncd-enable +0 -76
- data/solr/solr/bin/rsyncd-start +0 -145
- data/solr/solr/bin/rsyncd-stop +0 -105
- data/solr/solr/bin/scripts-util +0 -83
- data/solr/solr/bin/snapcleaner +0 -148
- data/solr/solr/bin/snapinstaller +0 -168
- data/solr/solr/bin/snappuller +0 -248
- data/solr/solr/bin/snappuller-disable +0 -77
- data/solr/solr/bin/snappuller-enable +0 -77
- data/solr/solr/bin/snapshooter +0 -109
- data/solr/solr/conf/scripts.conf +0 -24
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/tasks/solr.rake +0 -12
- data/tasks/website.rake +0 -17
- data/test/api/test_build_search.rb +0 -216
- data/test/api/test_helper.rb +0 -4
- data/test/api/test_indexer.rb +0 -110
- data/test/api/test_retrieve_search.rb +0 -114
- data/test/api/test_session.rb +0 -46
- data/test/integration/test_helper.rb +0 -1
@@ -0,0 +1,195 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'Search' do
|
4
|
+
it 'should search by keywords' do
|
5
|
+
connection.should_receive(:query).with('(keyword search) AND (type:Post)', hash_including).twice
|
6
|
+
session.search Post, :keywords => 'keyword search'
|
7
|
+
session.search Post do
|
8
|
+
keywords 'keyword search'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should scope by exact match with a string' do
|
13
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['title_s:My\ Pet\ Post'])).twice
|
14
|
+
session.search Post, :conditions => { :title => 'My Pet Post' }
|
15
|
+
session.search Post do
|
16
|
+
with.title 'My Pet Post'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should ignore nonexistant fields in hash scope' do
|
21
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => []))
|
22
|
+
session.search Post, :conditions => { :bogus => 'Field' }
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should raise an ArgumentError for nonexistant fields in block scope' do
|
26
|
+
lambda do
|
27
|
+
session.search Post do
|
28
|
+
with.bogus 'Field'
|
29
|
+
end
|
30
|
+
end.should raise_error(ArgumentError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should scope by exact match with time' do
|
34
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['published_at_d:1983\-07\-08T09\:00\:00Z'])).twice
|
35
|
+
time = Time.parse('1983-07-08 05:00:00 -0400')
|
36
|
+
session.search Post, :conditions => { :published_at => time }
|
37
|
+
session.search Post do
|
38
|
+
with.published_at time
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should scope by less than match with float' do
|
43
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['average_rating_f:[* TO 3\.0]']))
|
44
|
+
session.search Post do
|
45
|
+
with.average_rating.less_than 3.0
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should scope by greater than match with float' do
|
50
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['average_rating_f:[3\.0 TO *]']))
|
51
|
+
session.search Post do
|
52
|
+
with.average_rating.greater_than 3.0
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should scope by between match with float' do
|
57
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['average_rating_f:[2\.0 TO 4\.0]']))
|
58
|
+
session.search Post do
|
59
|
+
with.average_rating.between 2.0..4.0
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should scope by any match with integer' do
|
64
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['category_ids_im:(2 OR 7 OR 12)'])).twice
|
65
|
+
session.search Post, :conditions => { :category_ids => [2, 7, 12] }
|
66
|
+
session.search Post do
|
67
|
+
with.category_ids.any_of [2, 7, 12]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should scope by all match with integer' do
|
72
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['category_ids_im:(2 AND 7 AND 12)']))
|
73
|
+
session.search Post do
|
74
|
+
with.category_ids.all_of [2, 7, 12]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should paginate using default per_page when page not provided' do
|
79
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:rows => 30))
|
80
|
+
session.search Post
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should paginate using default per_page when page provided' do
|
84
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:rows => 30, :start => 30)).twice
|
85
|
+
session.search Post, :page => 2
|
86
|
+
session.search Post do
|
87
|
+
paginate :page => 2
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should paginate using provided per_page' do
|
92
|
+
connection.should_receive(:query).with('(type:Post)', :filter_queries => [], :rows => 15, :start => 45).twice
|
93
|
+
session.search Post, :page => 4, :per_page => 15
|
94
|
+
session.search Post do
|
95
|
+
paginate :page => 4, :per_page => 15
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should order' do
|
100
|
+
connection.should_receive(:query).with('(type:Post)', hash_including(:sort => [{ :average_rating_f => :descending }])).twice
|
101
|
+
session.search Post, :order => 'average_rating desc'
|
102
|
+
session.search Post do
|
103
|
+
order_by :average_rating, :desc
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should build search for multiple types' do
|
108
|
+
connection.should_receive(:query).with('(type:(Post OR Comment))', hash_including)
|
109
|
+
session.search(Post, Comment)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should allow search on fields common to all types' do
|
113
|
+
connection.should_receive(:query).with('(type:(Post OR Comment))', hash_including(:filter_queries => ['published_at_d:1983\-07\-08T09\:00\:00Z'])).twice
|
114
|
+
time = Time.parse('1983-07-08 05:00:00 -0400')
|
115
|
+
session.search Post, Comment, :conditions => { :published_at => time }
|
116
|
+
session.search Post, Comment do
|
117
|
+
with.published_at time
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should raise exception if search scoped to field not common to all types' do
|
122
|
+
lambda do
|
123
|
+
session.search Post, Comment do
|
124
|
+
with.blog_id 1
|
125
|
+
end
|
126
|
+
end.should raise_error(ArgumentError)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should raise exception if search scoped to field configured differently between types' do
|
130
|
+
lambda do
|
131
|
+
session.search Post, Comment do
|
132
|
+
with.average_rating 2.2 # this is a float in Post but an integer in Comment
|
133
|
+
end
|
134
|
+
end.should raise_error(ArgumentError)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should ignore condition if field is not common to all types' do
|
138
|
+
connection.should_receive(:query).with('(type:(Post OR Comment))', hash_including(:filter_queries => []))
|
139
|
+
session.search Post, Comment, :conditions => { :blog_id => 1 }
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should raise ArgumentError if bogus field scoped' do
|
143
|
+
lambda do
|
144
|
+
session.search Post do
|
145
|
+
with.bogus.equal_to :field
|
146
|
+
end
|
147
|
+
end.should raise_error(ArgumentError)
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should raise NoMethodError if bogus operator referenced' do
|
151
|
+
lambda do
|
152
|
+
session.search Post do
|
153
|
+
with.category_ids.resembling :bogus_condition
|
154
|
+
end
|
155
|
+
end.should raise_error(NoMethodError)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should raise ArgumentError if no :page argument given to paginate' do
|
159
|
+
lambda do
|
160
|
+
session.search Post do
|
161
|
+
paginate
|
162
|
+
end
|
163
|
+
end.should raise_error(ArgumentError)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should raise ArgumentError if bogus argument given to paginate' do
|
167
|
+
lambda do
|
168
|
+
session.search Post do
|
169
|
+
paginate :page => 4, :ugly => :puppy
|
170
|
+
end
|
171
|
+
end.should raise_error(ArgumentError)
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should raise NoMethodError if more than one argument passed to scope method' do # or should it?
|
175
|
+
lambda do
|
176
|
+
session.search Post do
|
177
|
+
with.category_ids 4, 5
|
178
|
+
end
|
179
|
+
end.should raise_error(NoMethodError)
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def config
|
185
|
+
@config ||= Sunspot::Configuration.build
|
186
|
+
end
|
187
|
+
|
188
|
+
def connection
|
189
|
+
@connection ||= mock('connection')
|
190
|
+
end
|
191
|
+
|
192
|
+
def session
|
193
|
+
@session ||= Sunspot::Session.new(config, connection)
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'indexer' do
|
4
|
+
describe 'when indexing an object' do
|
5
|
+
it 'should index id and type' do
|
6
|
+
connection.should_receive(:add).with(hash_including(:id => "Post #{post.id}", :type => ['Post', 'BaseClass']))
|
7
|
+
session.index post
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should index text' do
|
11
|
+
post :title => 'A Title', :body => 'A Post'
|
12
|
+
connection.should_receive(:add).with(hash_including(:title_text => 'A Title', :body_text => 'A Post'))
|
13
|
+
session.index post
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should correctly index a string attribute field' do
|
17
|
+
post :title => 'A Title'
|
18
|
+
connection.should_receive(:add).with(hash_including(:title_s => 'A Title'))
|
19
|
+
session.index post
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should correctly index an integer attribute field' do
|
23
|
+
post :blog_id => 4
|
24
|
+
connection.should_receive(:add).with(hash_including(:blog_id_i => '4'))
|
25
|
+
session.index post
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should correctly index a float attribute field' do
|
29
|
+
post :average_rating => 2.23
|
30
|
+
connection.should_receive(:add).with(hash_including(:average_rating_f => '2.23'))
|
31
|
+
session.index post
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should allow indexing by a multiple-value field' do
|
35
|
+
post :category_ids => [3, 14]
|
36
|
+
connection.should_receive(:add).with(hash_including(:category_ids_im => ['3', '14']))
|
37
|
+
session.index post
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should correctly index a time field' do
|
41
|
+
post :published_at => Time.parse('1983-07-08 05:00:00 -0400')
|
42
|
+
connection.should_receive(:add).with(hash_including(:published_at_d => '1983-07-08T09:00:00Z'))
|
43
|
+
session.index post
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should correctly index a virtual field' do
|
47
|
+
post :title => 'The Blog Post'
|
48
|
+
connection.should_receive(:add).with(hash_including(:sort_title_s => 'blog post'))
|
49
|
+
session.index post
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should correctly index a field that is defined on a superclass' do
|
53
|
+
Sunspot.setup(BaseClass) { string :author_name }
|
54
|
+
post :author_name => 'Mat Brown'
|
55
|
+
connection.should_receive(:add).with(hash_including(:author_name_s => 'Mat Brown'))
|
56
|
+
session.index post
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should remove an object from the index' do
|
60
|
+
connection.should_receive(:delete).with("Post #{post.id}")
|
61
|
+
session.remove(post)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should be able to remove everything from the index' do
|
65
|
+
connection.should_receive(:delete_by_query).with("type:[* TO *]")
|
66
|
+
session.remove_all
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should be able to remove everything of a given class from the index' do
|
70
|
+
connection.should_receive(:delete_by_query).with("type:Post")
|
71
|
+
session.remove_all(Post)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should throw a NoMethodError only if a nonexistent type is defined' do
|
76
|
+
lambda { Sunspot.setup(Post) { string :author_name }}.should_not raise_error
|
77
|
+
lambda { Sunspot.setup(Post) { bogus :journey }}.should raise_error(NoMethodError)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should throw a NoMethodError if a nonexistent field argument is passed' do
|
81
|
+
lambda { Sunspot.setup(Post) { string :author_name, :bogus => :argument }}.should raise_error(ArgumentError)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should throw an ArgumentError if an attempt is made to index an object that has no configuration' do
|
85
|
+
lambda { session.index(Time.now) }.should raise_error(ArgumentError)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should throw an ArgumentError if single-value field tries to index multiple values' do
|
89
|
+
lambda do
|
90
|
+
Sunspot.setup(Post) { string :author_name }
|
91
|
+
session.index(post(:author_name => ['Mat Brown', 'Matthew Brown']))
|
92
|
+
end.should raise_error(ArgumentError)
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def config
|
98
|
+
Sunspot::Configuration.build
|
99
|
+
end
|
100
|
+
|
101
|
+
def connection
|
102
|
+
@connection ||= mock('connection')
|
103
|
+
end
|
104
|
+
|
105
|
+
def session
|
106
|
+
@session ||= Sunspot::Session.new(config, connection)
|
107
|
+
end
|
108
|
+
|
109
|
+
def post(attrs = {})
|
110
|
+
@post ||= Post.new(attrs)
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'retrieving search' do
|
4
|
+
it 'should load search result' do
|
5
|
+
post = Post.new
|
6
|
+
stub_results(post)
|
7
|
+
session.search(Post).results.should == [post]
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should load multiple search results in order' do
|
11
|
+
post_1, post_2 = Post.new, Post.new
|
12
|
+
stub_results(post_1, post_2)
|
13
|
+
session.search(Post).results.should == [post_1, post_2]
|
14
|
+
stub_results(post_2, post_1)
|
15
|
+
session.search(Post).results.should == [post_2, post_1]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should return search total as attribute of results if pagination is provided' do
|
19
|
+
stub_results(Post.new, 4)
|
20
|
+
session.search(Post, :page => 1).results.total_entries.should == 4
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should return vanilla array if pagination is provided but WillPaginate is not available' do
|
24
|
+
stub_results(Post.new)
|
25
|
+
without_class(WillPaginate) do
|
26
|
+
session.search(Post, :page => 1).results.should_not respond_to(:total_entries)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should return total' do
|
31
|
+
stub_results(Post.new, Post.new, 4)
|
32
|
+
session.search(Post, :page => 1).total.should == 4
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def stub_results(*results)
|
38
|
+
total_hits = if results.last.is_a?(Integer) then results.pop
|
39
|
+
else results.length
|
40
|
+
end
|
41
|
+
response = mock('response')
|
42
|
+
response.stub!(:hits).and_return(results.map { |result| { 'id' => "#{result.class.name} #{result.id}" }})
|
43
|
+
response.stub!(:total_hits).and_return(total_hits)
|
44
|
+
connection.stub!(:query).and_return(response)
|
45
|
+
end
|
46
|
+
|
47
|
+
def config
|
48
|
+
@config ||= Sunspot::Configuration.build
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def connection
|
53
|
+
@connection ||= mock('connection')
|
54
|
+
end
|
55
|
+
|
56
|
+
def session
|
57
|
+
@session ||= Sunspot::Session.new(config, connection)
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'Session' do
|
4
|
+
context 'using singleton session' do
|
5
|
+
before :each do
|
6
|
+
Sunspot.reset!
|
7
|
+
connection.should_receive(:add)
|
8
|
+
connection.should_receive(:query)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should open connection with defaults if nothing specified' do
|
12
|
+
Solr::Connection.stub!(:new).with('http://localhost:8983/solr', :autocommit => :on).and_return(connection)
|
13
|
+
Sunspot.index(Post.new)
|
14
|
+
Sunspot.search(Post)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should open a connection with custom host' do
|
18
|
+
Solr::Connection.stub!(:new).with('http://127.0.0.1:8981/solr', :autocommit => :on).and_return(connection)
|
19
|
+
Sunspot.config.solr.url = 'http://127.0.0.1:8981/solr'
|
20
|
+
Sunspot.index(Post.new)
|
21
|
+
Sunspot.search(Post)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'using custom session' do
|
26
|
+
before :each do
|
27
|
+
connection.should_receive(:add)
|
28
|
+
connection.should_receive(:query)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should open a connection with custom host' do
|
32
|
+
Solr::Connection.stub!(:new).with('http://127.0.0.1:8982/solr', :autocommit => :on).and_return(connection)
|
33
|
+
session = Sunspot::Session.new do |config|
|
34
|
+
config.solr.url = 'http://127.0.0.1:8982/solr'
|
35
|
+
end
|
36
|
+
session.index(Post.new)
|
37
|
+
session.search(Post)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def connection
|
42
|
+
@connection ||= stub_everything('Connection')
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'standard search builder' do
|
4
|
+
before :each do
|
5
|
+
stub_results
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should give access to order through hash and object' do
|
9
|
+
search = session.search(Post, :order => 'sort_title asc')
|
10
|
+
search.builder.params[:order].should == 'sort_title asc'
|
11
|
+
search.builder.order.should == 'sort_title asc'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should give nil order if no order set' do
|
15
|
+
search = session.search(Post)
|
16
|
+
search.builder.params.should have_key(:order)
|
17
|
+
search.builder.params[:order].should be_nil
|
18
|
+
search.builder.order.should be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should give access to page and per-page through hash and object' do
|
22
|
+
search = session.search(Post, :page => 2, :per_page => 15)
|
23
|
+
search.builder.params[:page].should == 2
|
24
|
+
search.builder.params[:per_page].should == 15
|
25
|
+
search.builder.page.should == 2
|
26
|
+
search.builder.per_page.should == 15
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should give access to keywords' do
|
30
|
+
search = session.search(Post, :keywords => 'some keywords')
|
31
|
+
search.builder.params[:keywords].should == 'some keywords'
|
32
|
+
search.builder.keywords.should == 'some keywords'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should have nil keywords if no keywords given' do
|
36
|
+
search = session.search(Post)
|
37
|
+
search.builder.params.should have_key(:keywords)
|
38
|
+
search.builder.params[:keywords].should be_nil
|
39
|
+
search.builder.keywords.should be_nil
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should give access to conditions' do
|
43
|
+
search = session.search(Post, :conditions => { :blog_id => 1 })
|
44
|
+
search.builder.params[:conditions][:blog_id].should == 1
|
45
|
+
search.builder.conditions.blog_id.should == 1
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should have nil values for fields with unspecified conditions' do
|
49
|
+
search = session.search(Post)
|
50
|
+
%w(title blog_id category_ids average_rating published_at sort_title).each do |field_name|
|
51
|
+
search.builder.params[:conditions].should have_key(field_name.to_sym)
|
52
|
+
search.builder.params[:conditions][field_name.to_sym].should == nil
|
53
|
+
search.builder.conditions.should respond_to(field_name)
|
54
|
+
search.builder.conditions.send(field_name).should == nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def stub_results(*results)
|
61
|
+
response = mock('response', :hits => [], :total_hits => 0)
|
62
|
+
connection.stub!(:query).and_return(response)
|
63
|
+
end
|
64
|
+
|
65
|
+
def config
|
66
|
+
@config ||= Sunspot::Configuration.build
|
67
|
+
end
|
68
|
+
|
69
|
+
def connection
|
70
|
+
@connection ||= mock('connection')
|
71
|
+
end
|
72
|
+
|
73
|
+
def session
|
74
|
+
@session ||= Sunspot::Session.new(config, connection)
|
75
|
+
end
|
76
|
+
end
|
File without changes
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
|
-
|
3
|
+
describe 'field types' do
|
4
4
|
def self.test_field_type(name, field, *values)
|
5
5
|
raise(ArgumentError, 'Please supply five values') unless values.length == 5
|
6
6
|
|
@@ -14,40 +14,40 @@ class TestFieldTypes < Test::Unit::TestCase
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
it 'should filter by exact match' do
|
18
18
|
Sunspot.search(Post) { with.send(field, values[2]) }.results.should == [@posts[2]]
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
it 'should filter by less than' do
|
22
22
|
results = Sunspot.search(Post) { with.send(field).less_than values[2] }.results
|
23
23
|
(0..2).each { |i| results.should include(@posts[i]) }
|
24
24
|
(3..4).each { |i| results.should_not include(@posts[i]) }
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
it 'should filter by greater than' do
|
28
28
|
results = Sunspot.search(Post) { with.send(field).greater_than values[2] }.results
|
29
29
|
(2..4).each { |i| results.should include(@posts[i]) }
|
30
30
|
(0..1).each { |i| results.should_not include(@posts[i]) }
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
it 'should filter by between' do
|
34
34
|
results = Sunspot.search(Post) { with.send(field).between(values[1]..values[3]) }.results
|
35
35
|
(1..3).each { |i| results.should include(@posts[i]) }
|
36
36
|
[0, 4].each { |i| results.should_not include(@posts[i]) }
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
it 'should filter by any of' do
|
40
40
|
results = Sunspot.search(Post) { with.send(field).any_of(values.values_at(1, 3)) }.results
|
41
41
|
[1, 3].each { |i| results.should include(@posts[i]) }
|
42
42
|
[0, 2, 4].each { |i| results.should_not include(@posts[i]) }
|
43
43
|
end
|
44
44
|
|
45
|
-
|
45
|
+
it 'should order by field ascending' do
|
46
46
|
results = Sunspot.search(Post) { order_by field, :asc }.results
|
47
47
|
results.should == @posts
|
48
48
|
end
|
49
49
|
|
50
|
-
|
50
|
+
it 'should order by field descending' do
|
51
51
|
results = Sunspot.search(Post) { order_by field, :desc }.results
|
52
52
|
results.should == @posts.reverse
|
53
53
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
|
-
|
3
|
+
describe 'keyword search' do
|
4
4
|
before :all do
|
5
5
|
Sunspot.remove_all
|
6
6
|
@posts = []
|
@@ -13,18 +13,18 @@ class TestKeywordSearch < Test::Unit::TestCase
|
|
13
13
|
Sunspot.index(*@posts)
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
it 'matches a single keyword out of a single field' do
|
17
17
|
results = Sunspot.search(Post) { keywords 'toast' }.results
|
18
18
|
[0, 2].each { |i| results.should include(@posts[i]) }
|
19
19
|
[1].each { |i| results.should_not include(@posts[i]) }
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
it 'matches multiple words out of a single field' do
|
23
23
|
results = Sunspot.search(Post) { keywords 'elects toast' }.results
|
24
24
|
results.should == [@posts[0]]
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
it 'matches multiple words in multiple fields' do
|
28
28
|
results = Sunspot.search(Post) { keywords 'toast wind' }.results
|
29
29
|
[0, 2].each { |i| results.should include(@posts[i]) }
|
30
30
|
[1].each { |i| results.should_not include(@posts[i]) }
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
|
-
|
3
|
+
describe 'pagination' do
|
4
4
|
before :all do
|
5
5
|
Sunspot.remove_all
|
6
6
|
@posts = (0..19).map do |i|
|
@@ -9,12 +9,12 @@ class TestPagination < Test::Unit::TestCase
|
|
9
9
|
Sunspot.index(*@posts)
|
10
10
|
end
|
11
11
|
|
12
|
-
should
|
12
|
+
it 'should return all by default' do
|
13
13
|
results = Sunspot.search(Post) { order_by :blog_id }.results
|
14
14
|
results.should == @posts
|
15
15
|
end
|
16
16
|
|
17
|
-
should
|
17
|
+
it 'should return first page of 10' do
|
18
18
|
results = Sunspot.search(Post) do
|
19
19
|
order_by :blog_id
|
20
20
|
paginate :page => 1, :per_page => 10
|
@@ -22,7 +22,7 @@ class TestPagination < Test::Unit::TestCase
|
|
22
22
|
results.should == @posts[0,10]
|
23
23
|
end
|
24
24
|
|
25
|
-
should
|
25
|
+
it 'should return second page of 10' do
|
26
26
|
results = Sunspot.search(Post) do
|
27
27
|
order_by :blog_id
|
28
28
|
paginate :page => 2, :per_page => 10
|
File without changes
|
File without changes
|
File without changes
|
data/{test → spec}/mocks/post.rb
RENAMED
File without changes
|
@@ -1,17 +1,13 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
gem 'jeremymcanally-matchy', '>= 0.0.1'
|
3
|
-
gem 'jeremymcanally-context', '>= 0.0.6'
|
4
2
|
gem 'ruby-debug', '~>0.10'
|
5
3
|
gem 'mislav-will_paginate', '~> 2.3'
|
4
|
+
gem 'rspec', '~> 1.1'
|
6
5
|
|
7
|
-
require 'matchy'
|
8
|
-
require 'context'
|
9
6
|
require 'ruby-debug'
|
7
|
+
require 'spec'
|
10
8
|
require 'will_paginate'
|
11
9
|
require 'will_paginate/collection'
|
12
10
|
|
13
|
-
require File.join(File.dirname(__FILE__), 'custom_expectation')
|
14
|
-
|
15
11
|
unless gem_name = ENV['SUNSPOT_TEST_GEM']
|
16
12
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
17
13
|
else
|
@@ -22,10 +18,8 @@ require 'sunspot'
|
|
22
18
|
require File.join(File.dirname(__FILE__), 'mocks', 'base_class.rb')
|
23
19
|
Dir.glob(File.join(File.dirname(__FILE__), 'mocks', '**', '*.rb')).each { |file| require file }
|
24
20
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
Object.class_eval { const_set(clazz.name.to_sym, clazz) }
|
30
|
-
end
|
21
|
+
def without_class(clazz)
|
22
|
+
Object.class_eval { remove_const(clazz.name.to_sym) }
|
23
|
+
yield
|
24
|
+
Object.class_eval { const_set(clazz.name.to_sym, clazz) }
|
31
25
|
end
|
data/tasks/gemspec.rake
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
begin
|
2
|
+
gem 'technicalpickles-jeweler', '~> 0.8.1'
|
3
|
+
require 'jeweler'
|
4
|
+
Jeweler::Tasks.new do |s|
|
5
|
+
s.name = 'sunspot'
|
6
|
+
s.executables = 'sunspot-solr'
|
7
|
+
s.summary = 'Library for expressive, powerful interaction with the Solr search engine'
|
8
|
+
s.email = 'mat@patch.com'
|
9
|
+
s.homepage = 'http://github.com/outoftime/sunspot'
|
10
|
+
s.description = 'Library for expressive, powerful interaction with the Solr search engine'
|
11
|
+
s.authors = ['Mat Brown']
|
12
|
+
s.files = FileList['[A-Z]*', '{bin,lib,spec,tasks}/**/*', 'solr/{etc,lib,webapps}/**/*', 'solr/solr/conf/*', 'solr/start.jar']
|
13
|
+
s.add_dependency 'solr-ruby', '>= 0.0.6'
|
14
|
+
s.add_dependency 'extlib', '>= 0.9.10'
|
15
|
+
s.add_development_dependency 'rspec', '~> 1.1'
|
16
|
+
s.add_development_dependency 'ruby-debug', '~> 0.10'
|
17
|
+
end
|
18
|
+
end
|