sunspot 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/sunspot/adapters.rb +64 -17
- data/lib/sunspot/configuration.rb +1 -1
- data/lib/sunspot/query/dismax.rb +4 -4
- data/lib/sunspot/query/restriction.rb +27 -2
- data/lib/sunspot/version.rb +1 -1
- data/spec/api/adapters_spec.rb +12 -0
- data/spec/api/query/fulltext_examples.rb +4 -4
- data/spec/api/query/geo_examples.rb +4 -4
- data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +1 -1
- data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +1 -1
- data/spec/api/session_proxy/sharding_session_proxy_spec.rb +1 -1
- data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +1 -1
- data/spec/api/session_spec.rb +2 -2
- data/spec/helpers/integration_helper.rb +1 -1
- data/spec/helpers/query_helper.rb +1 -1
- data/spec/integration/keyword_search_spec.rb +28 -0
- data/spec/integration/scoped_search_spec.rb +39 -1
- data/spec/mocks/adapters.rb +3 -0
- metadata +11 -12
data/lib/sunspot/adapters.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
1
3
|
module Sunspot
|
2
4
|
#
|
3
5
|
# Sunspot works by saving references to the primary key (or natural ID) of
|
@@ -46,7 +48,7 @@ module Sunspot
|
|
46
48
|
# end
|
47
49
|
#
|
48
50
|
# # then in your initializer
|
49
|
-
# Sunspot::Adapters::InstanceAdapter.register(
|
51
|
+
# Sunspot::Adapters::InstanceAdapter.register(FileAdapter, File)
|
50
52
|
#
|
51
53
|
class InstanceAdapter
|
52
54
|
def initialize(instance) #:nodoc:
|
@@ -119,16 +121,28 @@ module Sunspot
|
|
119
121
|
#
|
120
122
|
# Sunspot::NoAdapterError:: If no adapter is registered for this class
|
121
123
|
#
|
122
|
-
def for(clazz)
|
123
|
-
|
124
|
-
|
125
|
-
next if ancestor_class.name.nil? || ancestor_class.name.empty?
|
126
|
-
class_name = ancestor_class.name.to_sym
|
127
|
-
return instance_adapters[class_name] if instance_adapters[class_name]
|
128
|
-
end
|
129
|
-
|
124
|
+
def for(clazz)
|
125
|
+
adapter = registered_adapter_for(clazz) || registered_adapter_for_ancestors_of(clazz)
|
126
|
+
return adapter if adapter
|
130
127
|
raise(Sunspot::NoAdapterError,
|
131
|
-
"No adapter is configured for #{
|
128
|
+
"No adapter is configured for #{clazz.name} or its superclasses. See the documentation for Sunspot::Adapters")
|
129
|
+
end
|
130
|
+
|
131
|
+
# Returns the directly-registered adapter for the specified class,
|
132
|
+
# if one exists, without searching the class's ancestors.
|
133
|
+
#
|
134
|
+
# === Parameters
|
135
|
+
#
|
136
|
+
# clazz<Class>:: The model class to be checked for the registered
|
137
|
+
# adapter
|
138
|
+
#
|
139
|
+
# === Returns
|
140
|
+
#
|
141
|
+
# Class:: Subclass of InstanceAdapter, or nil if none found
|
142
|
+
#
|
143
|
+
def registered_adapter_for(clazz)
|
144
|
+
return nil if clazz.name.nil? || clazz.name.empty?
|
145
|
+
instance_adapters[clazz.name.to_sym]
|
132
146
|
end
|
133
147
|
|
134
148
|
def index_id_for(class_name, id) #:nodoc:
|
@@ -146,6 +160,16 @@ module Sunspot
|
|
146
160
|
def instance_adapters #:nodoc:
|
147
161
|
@instance_adapters ||= {}
|
148
162
|
end
|
163
|
+
|
164
|
+
def registered_adapter_for_ancestors_of(clazz) # :nodoc:
|
165
|
+
clazz.ancestors.each do |ancestor_class|
|
166
|
+
if adapter = registered_adapter_for(ancestor_class)
|
167
|
+
register(adapter, clazz)
|
168
|
+
return adapter
|
169
|
+
end
|
170
|
+
end
|
171
|
+
nil
|
172
|
+
end
|
149
173
|
end
|
150
174
|
end
|
151
175
|
|
@@ -247,14 +271,27 @@ module Sunspot
|
|
247
271
|
# Sunspot::NoAdapterError:: If no data accessor exists for the given class
|
248
272
|
#
|
249
273
|
def for(clazz) #:nodoc:
|
250
|
-
|
251
|
-
|
252
|
-
next if ancestor_class.name.nil? || ancestor_class.name.empty?
|
253
|
-
class_name = ancestor_class.name.to_sym
|
254
|
-
return data_accessors[class_name] if data_accessors[class_name]
|
255
|
-
end
|
274
|
+
accessor = registered_accessor_for(clazz) || registered_accessor_for_ancestors_of(clazz)
|
275
|
+
return accessor if accessor
|
256
276
|
raise(Sunspot::NoAdapterError,
|
257
|
-
"No data accessor is configured for #{
|
277
|
+
"No data accessor is configured for #{clazz.name} or its superclasses. See the documentation for Sunspot::Adapters")
|
278
|
+
end
|
279
|
+
|
280
|
+
# Returns the directly-registered accessor for the specified class, if
|
281
|
+
# one exists, without searching the class's ancestors.
|
282
|
+
#
|
283
|
+
# === Parameters
|
284
|
+
#
|
285
|
+
# clazz<Class>:: The model class to be checked for the registered
|
286
|
+
# data accessor
|
287
|
+
#
|
288
|
+
# === Returns
|
289
|
+
#
|
290
|
+
# Class:: Subclass of DataAccessor, or nil if none found
|
291
|
+
#
|
292
|
+
def registered_accessor_for(clazz)
|
293
|
+
return nil if clazz.name.nil? || clazz.name.empty?
|
294
|
+
data_accessors[clazz.name.to_sym]
|
258
295
|
end
|
259
296
|
|
260
297
|
protected
|
@@ -268,6 +305,16 @@ module Sunspot
|
|
268
305
|
def data_accessors #:nodoc:
|
269
306
|
@adapters ||= {}
|
270
307
|
end
|
308
|
+
|
309
|
+
def registered_accessor_for_ancestors_of(clazz) # :nodoc:
|
310
|
+
clazz.ancestors.each do |ancestor_class|
|
311
|
+
if accessor = registered_accessor_for(ancestor_class)
|
312
|
+
register(accessor, clazz)
|
313
|
+
return accessor
|
314
|
+
end
|
315
|
+
end
|
316
|
+
nil
|
317
|
+
end
|
271
318
|
end
|
272
319
|
end
|
273
320
|
|
data/lib/sunspot/query/dismax.rb
CHANGED
@@ -30,7 +30,7 @@ module Sunspot
|
|
30
30
|
params = { :q => @keywords }
|
31
31
|
params[:fl] = '* score'
|
32
32
|
params[:qf] = @fulltext_fields.values.map { |field| field.to_boosted_field }.join(' ')
|
33
|
-
params[:defType] = '
|
33
|
+
params[:defType] = 'edismax'
|
34
34
|
if @phrase_fields
|
35
35
|
params[:pf] = @phrase_fields.map { |field| field.to_boosted_field }.join(' ')
|
36
36
|
end
|
@@ -71,7 +71,7 @@ module Sunspot
|
|
71
71
|
params.delete :fl
|
72
72
|
keywords = params.delete(:q)
|
73
73
|
options = params.map { |key, value| escape_param(key, value) }.join(' ')
|
74
|
-
"_query_:\"{!
|
74
|
+
"_query_:\"{!edismax #{options}}#{escape_quotes(keywords)}\""
|
75
75
|
end
|
76
76
|
|
77
77
|
#
|
@@ -82,7 +82,7 @@ module Sunspot
|
|
82
82
|
boost_query
|
83
83
|
end
|
84
84
|
|
85
|
-
#
|
85
|
+
#
|
86
86
|
# Add a boost function
|
87
87
|
#
|
88
88
|
def add_boost_function(function_query)
|
@@ -123,7 +123,7 @@ module Sunspot
|
|
123
123
|
|
124
124
|
|
125
125
|
private
|
126
|
-
|
126
|
+
|
127
127
|
def escape_param(key, value)
|
128
128
|
"#{key}='#{escape_quotes(Array(value).join(" "))}'"
|
129
129
|
end
|
@@ -273,10 +273,23 @@ module Sunspot
|
|
273
273
|
# Results must have field with value included in given collection
|
274
274
|
#
|
275
275
|
class AnyOf < Base
|
276
|
+
|
277
|
+
def negated?
|
278
|
+
if @value.empty?
|
279
|
+
false
|
280
|
+
else
|
281
|
+
super
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
276
285
|
private
|
277
286
|
|
278
287
|
def to_solr_conditional
|
279
|
-
|
288
|
+
if @value.empty?
|
289
|
+
"[* TO *]"
|
290
|
+
else
|
291
|
+
"(#{@value.map { |v| solr_value v } * ' OR '})"
|
292
|
+
end
|
280
293
|
end
|
281
294
|
end
|
282
295
|
|
@@ -285,10 +298,22 @@ module Sunspot
|
|
285
298
|
# collection (only makes sense for fields with multiple values)
|
286
299
|
#
|
287
300
|
class AllOf < Base
|
301
|
+
def negated?
|
302
|
+
if @value.empty?
|
303
|
+
false
|
304
|
+
else
|
305
|
+
super
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
288
309
|
private
|
289
310
|
|
290
311
|
def to_solr_conditional
|
291
|
-
|
312
|
+
if @value.empty?
|
313
|
+
"[* TO *]"
|
314
|
+
else
|
315
|
+
"(#{@value.map { |v| solr_value v } * ' AND '})"
|
316
|
+
end
|
292
317
|
end
|
293
318
|
end
|
294
319
|
|
data/lib/sunspot/version.rb
CHANGED
data/spec/api/adapters_spec.rb
CHANGED
@@ -14,6 +14,12 @@ describe Sunspot::Adapters::InstanceAdapter do
|
|
14
14
|
Sunspot::Adapters::InstanceAdapter::for(Module.new)
|
15
15
|
end.should raise_error(Sunspot::NoAdapterError)
|
16
16
|
end
|
17
|
+
|
18
|
+
it "registers adapters found by ancestor lookup with the descendant class" do
|
19
|
+
Sunspot::Adapters::InstanceAdapter::registered_adapter_for(UnseenModel).should be(nil)
|
20
|
+
Sunspot::Adapters::InstanceAdapter::for(UnseenModel)
|
21
|
+
Sunspot::Adapters::InstanceAdapter::registered_adapter_for(UnseenModel).should be(AbstractModelInstanceAdapter)
|
22
|
+
end
|
17
23
|
end
|
18
24
|
|
19
25
|
describe Sunspot::Adapters::DataAccessor do
|
@@ -30,6 +36,12 @@ describe Sunspot::Adapters::DataAccessor do
|
|
30
36
|
Sunspot::Adapters::DataAccessor::for(Module.new)
|
31
37
|
end.should raise_error(Sunspot::NoAdapterError)
|
32
38
|
end
|
39
|
+
|
40
|
+
it "registers adapters found by ancestor lookup with the descendant class" do
|
41
|
+
Sunspot::Adapters::DataAccessor::registered_accessor_for(UnseenModel).should be(nil)
|
42
|
+
Sunspot::Adapters::DataAccessor::for(UnseenModel)
|
43
|
+
Sunspot::Adapters::DataAccessor::registered_accessor_for(UnseenModel).should be(AbstractModelDataAccessor)
|
44
|
+
end
|
33
45
|
end
|
34
46
|
|
35
47
|
describe Sunspot::Adapters::Registry do
|
@@ -10,21 +10,21 @@ shared_examples_for 'fulltext query' do
|
|
10
10
|
search do
|
11
11
|
keywords ''
|
12
12
|
end
|
13
|
-
connection.should_not have_last_search_with(:defType => '
|
13
|
+
connection.should_not have_last_search_with(:defType => 'edismax')
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'ignores keywords if nil' do
|
17
17
|
search do
|
18
18
|
keywords nil
|
19
19
|
end
|
20
|
-
connection.should_not have_last_search_with(:defType => '
|
20
|
+
connection.should_not have_last_search_with(:defType => 'edismax')
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'ignores keywords with only whitespace' do
|
24
24
|
search do
|
25
25
|
keywords " \t"
|
26
26
|
end
|
27
|
-
connection.should_not have_last_search_with(:defType => '
|
27
|
+
connection.should_not have_last_search_with(:defType => 'edismax')
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'gracefully ignores keywords block if keywords ignored' do
|
@@ -37,7 +37,7 @@ shared_examples_for 'fulltext query' do
|
|
37
37
|
search do
|
38
38
|
keywords 'keyword search'
|
39
39
|
end
|
40
|
-
connection.should have_last_search_with(:defType => '
|
40
|
+
connection.should have_last_search_with(:defType => 'edismax')
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'searches types in filter query if keywords used' do
|
@@ -41,11 +41,11 @@ shared_examples_for 'geohash query' do
|
|
41
41
|
fulltext 'pizza', :fields => :title
|
42
42
|
with(:coordinates).near(40.7, -73.5)
|
43
43
|
end
|
44
|
-
expected =
|
45
|
-
"{!
|
44
|
+
expected =
|
45
|
+
"{!edismax fl='* score' qf='title_text'}pizza (#{build_geo_query})"
|
46
46
|
connection.should have_last_search_including(
|
47
47
|
:q,
|
48
|
-
%Q(_query_:"{!
|
48
|
+
%Q(_query_:"{!edismax qf='title_text'}pizza" (#{build_geo_query}))
|
49
49
|
)
|
50
50
|
end
|
51
51
|
|
@@ -57,7 +57,7 @@ shared_examples_for 'geohash query' do
|
|
57
57
|
boost = options[:boost] || 1.0
|
58
58
|
hash = 'dr5xx3nytvgs'
|
59
59
|
(precision..12).map do |i|
|
60
|
-
phrase =
|
60
|
+
phrase =
|
61
61
|
if i == 12 then hash
|
62
62
|
else "#{hash[0, i]}*"
|
63
63
|
end
|
@@ -68,7 +68,7 @@ describe Sunspot::SessionProxy::ClassShardingSessionProxy do
|
|
68
68
|
|
69
69
|
[:dirty, :delete_dirty].each do |method|
|
70
70
|
it "should be dirty if any of the sessions are dirty" do
|
71
|
-
@proxy.post_session.stub
|
71
|
+
@proxy.post_session.stub(:"#{method}?").and_return(true)
|
72
72
|
@proxy.should send("be_#{method}")
|
73
73
|
end
|
74
74
|
|
@@ -53,7 +53,7 @@ describe Sunspot::SessionProxy::Retry5xxSessionProxy do
|
|
53
53
|
|
54
54
|
@sunspot_session.should_receive(:index).and_return do
|
55
55
|
@sunspot_session.should_receive(:index).and_return do
|
56
|
-
@sunspot_session.stub
|
56
|
+
@sunspot_session.stub(:index).and_return(fake_success)
|
57
57
|
raise e
|
58
58
|
end
|
59
59
|
raise e
|
@@ -60,7 +60,7 @@ describe Sunspot::SessionProxy::ShardingSessionProxy do
|
|
60
60
|
|
61
61
|
[:dirty, :delete_dirty].each do |method|
|
62
62
|
it "should be dirty if any of the sessions are dirty" do
|
63
|
-
@proxy.sessions[0].stub
|
63
|
+
@proxy.sessions[0].stub(:"#{method}?").and_return(true)
|
64
64
|
@proxy.should send("be_#{method}")
|
65
65
|
end
|
66
66
|
|
@@ -13,7 +13,7 @@ describe Sunspot::SessionProxy::ShardingSessionProxy do
|
|
13
13
|
it "should call rescued_exception when an exception is caught" do
|
14
14
|
SUPPORTED_METHODS.each do |method|
|
15
15
|
e = FakeException.new(method)
|
16
|
-
@search_session.stub
|
16
|
+
@search_session.stub(method).and_raise(e)
|
17
17
|
@proxy.should_receive(:rescued_exception).with(method, e)
|
18
18
|
@proxy.send(method)
|
19
19
|
end
|
data/spec/api/session_spec.rb
CHANGED
@@ -77,7 +77,7 @@ describe 'Session' do
|
|
77
77
|
|
78
78
|
it 'should open connection with defaults if nothing specified' do
|
79
79
|
Sunspot.commit
|
80
|
-
connection.opts[:url].should == 'http://127.0.0.1:8983/solr'
|
80
|
+
connection.opts[:url].should == 'http://127.0.0.1:8983/solr/default'
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'should open a connection with custom host' do
|
@@ -217,7 +217,7 @@ describe 'Session' do
|
|
217
217
|
|
218
218
|
context 'session proxy' do
|
219
219
|
it 'should send messages to manually assigned session proxy' do
|
220
|
-
stub_session = stub
|
220
|
+
stub_session = stub('session')
|
221
221
|
Sunspot.session = stub_session
|
222
222
|
post = Post.new
|
223
223
|
stub_session.should_receive(:index).with(post)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module IntegrationHelper
|
2
2
|
def self.included(base)
|
3
3
|
base.before(:all) do
|
4
|
-
Sunspot.config.solr.url = ENV['SOLR_URL'] || 'http://localhost:8983/solr'
|
4
|
+
Sunspot.config.solr.url = ENV['SOLR_URL'] || 'http://localhost:8983/solr/default'
|
5
5
|
Sunspot.reset!(true)
|
6
6
|
end
|
7
7
|
end
|
@@ -11,7 +11,7 @@ module QueryHelper
|
|
11
11
|
def subqueries(param)
|
12
12
|
q = connection.searches.last[:q]
|
13
13
|
subqueries = []
|
14
|
-
subqueries = q.scan(%r(_query_:"\{!
|
14
|
+
subqueries = q.scan(%r(_query_:"\{!edismax (.*?)\}(.*?)"))
|
15
15
|
subqueries.map do |subquery|
|
16
16
|
params = {}
|
17
17
|
subquery[0].scan(%r((\S+?)='(.+?)')) do |key, value|
|
@@ -16,6 +16,34 @@ describe 'keyword search' do
|
|
16
16
|
Sunspot.index!(@comment)
|
17
17
|
end
|
18
18
|
|
19
|
+
context 'edismax' do
|
20
|
+
it 'matches with wildcards' do
|
21
|
+
results = Sunspot.search(Post) { keywords '*oas*' }.results
|
22
|
+
[0,2].each { |i| results.should include(@posts[i])}
|
23
|
+
[1].each { |i| results.should_not include(@posts[i])}
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'matches multiple keywords on different fields with wildcards using subqueries' do
|
27
|
+
results = Sunspot.search(Post) do
|
28
|
+
keywords 'insuffic*',:fields=>[:title]
|
29
|
+
keywords 'win*',:fields=>[:body]
|
30
|
+
end.results
|
31
|
+
[0].each {|i| results.should include(@posts[i])}
|
32
|
+
[1,2].each {|i| results.should_not include(@posts[i])}
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'matches with proximity' do
|
36
|
+
results = Sunspot.search(Post) { keywords '"wind buffer"~4' }.results
|
37
|
+
[0,1].each {|i| results.should_not include(@posts[i])}
|
38
|
+
[2].each {|i| results.should include(@posts[i])}
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'does not match if not within proximity' do
|
42
|
+
results = Sunspot.search(Post) { keywords '"wind buffer"~1' }.results
|
43
|
+
results.should == []
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
19
47
|
it 'matches a single keyword out of a single field' do
|
20
48
|
results = Sunspot.search(Post) { keywords 'toast' }.results
|
21
49
|
[0, 2].each { |i| results.should include(@posts[i]) }
|
@@ -266,6 +266,44 @@ describe 'scoped_search' do
|
|
266
266
|
end.results.should == posts[0..1]
|
267
267
|
end
|
268
268
|
|
269
|
+
it 'should return results, ignoring any restriction in a disjunction that has been passed an empty array' do
|
270
|
+
posts = (1..3).map { |i| Post.new(:blog_id => i)}
|
271
|
+
Sunspot.index!(posts)
|
272
|
+
Sunspot.search(Post) do
|
273
|
+
with(:blog_id, [])
|
274
|
+
end.results.should == posts
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'should return results, ignoring any restriction in a negative disjunction that has been passed an empty array' do
|
278
|
+
posts = (1..3).map { |i| Post.new(:blog_id => i)}
|
279
|
+
Sunspot.index!(posts)
|
280
|
+
Sunspot.search(Post) do
|
281
|
+
without(:blog_id, [])
|
282
|
+
end.results.should == posts
|
283
|
+
end
|
284
|
+
|
285
|
+
it 'should return results, ignoring any restriction in a conjunction that has been passed an empty array' do
|
286
|
+
posts = (1..3).map { |i| Post.new(:blog_id => i)}
|
287
|
+
Sunspot.index!(posts)
|
288
|
+
Sunspot.search(Post) do
|
289
|
+
all_of do
|
290
|
+
with(:blog_id, 1)
|
291
|
+
with(:blog_id, [])
|
292
|
+
end
|
293
|
+
end.results.should == posts[0..0]
|
294
|
+
end
|
295
|
+
|
296
|
+
it 'should return results, ignoring any restriction in a negative conjunction that has been passed an empty array' do
|
297
|
+
posts = (1..3).map { |i| Post.new(:blog_id => i)}
|
298
|
+
Sunspot.index!(posts)
|
299
|
+
Sunspot.search(Post) do
|
300
|
+
all_of do
|
301
|
+
with(:blog_id, 1)
|
302
|
+
without(:blog_id, [])
|
303
|
+
end
|
304
|
+
end.results.should == posts[0..0]
|
305
|
+
end
|
306
|
+
|
269
307
|
it 'should return results that match a nested conjunction in a disjunction' do
|
270
308
|
posts = [
|
271
309
|
Post.new(:title => 'No', :blog_id => 1),
|
@@ -379,7 +417,7 @@ describe 'scoped_search' do
|
|
379
417
|
|
380
418
|
it 'should order randomly (run this test again if it fails)' do
|
381
419
|
result_sets = Array.new(2) do
|
382
|
-
Sunspot.search(Post) {
|
420
|
+
Sunspot.search(Post) { order_by(:random) }.results.map do |result|
|
383
421
|
result.id
|
384
422
|
end
|
385
423
|
end
|
data/spec/mocks/adapters.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sunspot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -27,7 +27,7 @@ authors:
|
|
27
27
|
autorequire:
|
28
28
|
bindir: bin
|
29
29
|
cert_chain: []
|
30
|
-
date: 2013-
|
30
|
+
date: 2013-10-25 00:00:00.000000000 Z
|
31
31
|
dependencies:
|
32
32
|
- !ruby/object:Gem::Dependency
|
33
33
|
name: rsolr
|
@@ -82,7 +82,7 @@ dependencies:
|
|
82
82
|
requirement: !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
|
-
- -
|
85
|
+
- - '>='
|
86
86
|
- !ruby/object:Gem::Version
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
@@ -90,14 +90,13 @@ dependencies:
|
|
90
90
|
version_requirements: !ruby/object:Gem::Requirement
|
91
91
|
none: false
|
92
92
|
requirements:
|
93
|
-
- -
|
93
|
+
- - '>='
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: '0'
|
96
|
-
description:
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
boolean queries or building Solr parameters by hand.\n"
|
96
|
+
description: |2
|
97
|
+
Sunspot is a library providing a powerful, all-ruby API for the Solr search engine. Sunspot manages the configuration of persistent
|
98
|
+
Ruby classes for search and indexing and exposes Solr's most powerful features through a collection of DSLs. Complex search operations
|
99
|
+
can be performed without hand-writing any boolean queries or building Solr parameters by hand.
|
101
100
|
email:
|
102
101
|
- mat@patch.com
|
103
102
|
executables: []
|
@@ -299,18 +298,18 @@ require_paths:
|
|
299
298
|
required_ruby_version: !ruby/object:Gem::Requirement
|
300
299
|
none: false
|
301
300
|
requirements:
|
302
|
-
- -
|
301
|
+
- - '>='
|
303
302
|
- !ruby/object:Gem::Version
|
304
303
|
version: '0'
|
305
304
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
306
305
|
none: false
|
307
306
|
requirements:
|
308
|
-
- -
|
307
|
+
- - '>='
|
309
308
|
- !ruby/object:Gem::Version
|
310
309
|
version: '0'
|
311
310
|
requirements: []
|
312
311
|
rubyforge_project: sunspot
|
313
|
-
rubygems_version: 1.8.
|
312
|
+
rubygems_version: 1.8.25
|
314
313
|
signing_key:
|
315
314
|
specification_version: 3
|
316
315
|
summary: Library for expressive, powerful interaction with the Solr search engine
|