sunspot 2.5.0 → 2.7.1
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.
- checksums.yaml +4 -4
- data/lib/sunspot/adapters.rb +14 -3
- data/lib/sunspot/data_extractor.rb +1 -1
- data/lib/sunspot/dsl/fulltext.rb +1 -1
- data/lib/sunspot/dsl/standard_query.rb +29 -1
- data/lib/sunspot/dsl.rb +2 -2
- data/lib/sunspot/field.rb +21 -4
- data/lib/sunspot/indexer.rb +37 -8
- data/lib/sunspot/query/abstract_fulltext.rb +7 -3
- data/lib/sunspot/query/abstract_json_field_facet.rb +3 -0
- data/lib/sunspot/query/composite_fulltext.rb +21 -2
- data/lib/sunspot/query/date_field_json_facet.rb +2 -16
- data/lib/sunspot/query/dismax.rb +10 -4
- data/lib/sunspot/query/function_query.rb +25 -1
- data/lib/sunspot/query/join.rb +1 -1
- data/lib/sunspot/query/range_json_facet.rb +5 -2
- data/lib/sunspot/query/restriction.rb +16 -10
- data/lib/sunspot/query/standard_query.rb +12 -0
- data/lib/sunspot/search/field_json_facet.rb +14 -3
- data/lib/sunspot/session.rb +7 -5
- data/lib/sunspot/setup.rb +38 -0
- data/lib/sunspot/util.rb +24 -21
- data/lib/sunspot/version.rb +1 -1
- data/lib/sunspot.rb +9 -1
- data/spec/api/binding_spec.rb +15 -0
- data/spec/api/indexer/attributes_spec.rb +1 -1
- data/spec/api/indexer/removal_spec.rb +87 -0
- data/spec/api/query/connective_boost_examples.rb +85 -0
- data/spec/api/query/geo_examples.rb +1 -1
- data/spec/api/query/join_spec.rb +2 -2
- data/spec/api/query/standard_spec.rb +10 -0
- data/spec/api/query/types_spec.rb +2 -2
- data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +1 -1
- data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +9 -5
- data/spec/api/session_spec.rb +1 -1
- data/spec/api/setup_spec.rb +99 -0
- data/spec/helpers/indexer_helper.rb +22 -0
- data/spec/integration/atomic_updates_spec.rb +169 -5
- data/spec/integration/faceting_spec.rb +68 -34
- data/spec/integration/join_spec.rb +22 -3
- data/spec/integration/scoped_search_spec.rb +78 -0
- data/spec/mocks/comment.rb +1 -1
- data/spec/mocks/connection.rb +6 -0
- data/spec/mocks/photo.rb +11 -7
- data/spec/mocks/post.rb +35 -1
- data/sunspot.gemspec +4 -6
- metadata +33 -15
data/lib/sunspot/util.rb
CHANGED
@@ -190,22 +190,15 @@ module Sunspot
|
|
190
190
|
|
191
191
|
def parse_json_facet(field_name, options, setup)
|
192
192
|
field = setup.field(field_name)
|
193
|
-
if options[:time_range]
|
194
|
-
unless field.type.is_a?(Sunspot::Type::TimeType)
|
195
|
-
raise(
|
196
|
-
ArgumentError,
|
197
|
-
':time_range can only be specified for Date or Time fields'
|
198
|
-
)
|
199
|
-
end
|
200
|
-
Sunspot::Query::DateFieldJsonFacet.new(field, options, setup)
|
201
|
-
elsif options[:range]
|
193
|
+
if options[:range] || options[:time_range]
|
202
194
|
unless [Sunspot::Type::TimeType, Sunspot::Type::FloatType, Sunspot::Type::IntegerType ].find{|type| field.type.is_a?(type)}
|
203
195
|
raise(
|
204
196
|
ArgumentError,
|
205
|
-
':range can only be specified for date or numeric fields'
|
197
|
+
':range can only be specified for date, time, or numeric fields'
|
206
198
|
)
|
207
199
|
end
|
208
|
-
Sunspot::Query::
|
200
|
+
facet_klass = field.type.is_a?(Sunspot::Type::TimeType) ? Sunspot::Query::DateFieldJsonFacet : Sunspot::Query::RangeJsonFacet
|
201
|
+
facet_klass.new(field, options, setup)
|
209
202
|
else
|
210
203
|
Sunspot::Query::FieldJsonFacet.new(field, options, setup)
|
211
204
|
end
|
@@ -255,7 +248,7 @@ module Sunspot
|
|
255
248
|
Coordinates = Struct.new(:lat, :lng)
|
256
249
|
|
257
250
|
class ContextBoundDelegate
|
258
|
-
class <<self
|
251
|
+
class << self
|
259
252
|
def instance_eval_with_context(receiver, &block)
|
260
253
|
calling_context = eval('self', block.binding)
|
261
254
|
if parent_calling_context = calling_context.instance_eval{@__calling_context__ if defined?(@__calling_context__)}
|
@@ -296,21 +289,31 @@ module Sunspot
|
|
296
289
|
__proxy_method__(:sub, *args, &block)
|
297
290
|
end
|
298
291
|
|
299
|
-
def method_missing(method, *args, &block)
|
300
|
-
__proxy_method__(method, *args, &block)
|
292
|
+
def method_missing(method, *args, **kwargs, &block)
|
293
|
+
__proxy_method__(method, *args, **kwargs, &block)
|
301
294
|
end
|
302
295
|
|
303
|
-
def
|
304
|
-
|
296
|
+
def respond_to_missing?(method, _)
|
297
|
+
@__receiver__.respond_to?(method, true) || super
|
298
|
+
end
|
299
|
+
|
300
|
+
def __proxy_method__(method, *args, **kwargs, &block)
|
301
|
+
if kwargs.empty?
|
305
302
|
@__receiver__.__send__(method.to_sym, *args, &block)
|
306
|
-
|
307
|
-
|
303
|
+
else
|
304
|
+
@__receiver__.__send__(method.to_sym, *args, **kwargs, &block)
|
305
|
+
end
|
306
|
+
rescue ::NoMethodError => e
|
307
|
+
begin
|
308
|
+
if kwargs.empty?
|
308
309
|
@__calling_context__.__send__(method.to_sym, *args, &block)
|
309
|
-
|
310
|
-
|
310
|
+
else
|
311
|
+
@__calling_context__.__send__(method.to_sym, *args, **kwargs, &block)
|
311
312
|
end
|
313
|
+
rescue ::NoMethodError
|
314
|
+
raise(e)
|
312
315
|
end
|
313
|
-
end
|
316
|
+
end
|
314
317
|
end
|
315
318
|
end
|
316
319
|
end
|
data/lib/sunspot/version.rb
CHANGED
data/lib/sunspot.rb
CHANGED
@@ -40,6 +40,12 @@ module Sunspot
|
|
40
40
|
NoSetupError = Class.new(StandardError)
|
41
41
|
IllegalSearchError = Class.new(StandardError)
|
42
42
|
NotImplementedError = Class.new(StandardError)
|
43
|
+
AtomicUpdateRequireInstanceForCompositeIdMessage = lambda do |class_name|
|
44
|
+
"WARNING: `id_prefix` is defined for #{class_name}. Use instance as key for `atomic_update` instead of ID."
|
45
|
+
end
|
46
|
+
RemoveByIdNotSupportCompositeIdMessage = lambda do |class_name|
|
47
|
+
"WARNING: `id_prefix` is defined for #{class_name}. `remove_by_id` does not support it. Use `remove` instead."
|
48
|
+
end
|
43
49
|
|
44
50
|
autoload :Installer, File.join(File.dirname(__FILE__), 'sunspot', 'installer')
|
45
51
|
|
@@ -208,6 +214,8 @@ module Sunspot
|
|
208
214
|
#
|
209
215
|
# post1, post2 = new Array(2) { Post.create }
|
210
216
|
# Sunspot.atomic_update(Post, post1.id => {title: 'New Title'}, post2.id => {description: 'new description'})
|
217
|
+
# Or
|
218
|
+
# Sunspot.atomic_update(Post, post1 => {title: 'New Title'}, post2 => {description: 'new description'})
|
211
219
|
#
|
212
220
|
# Note that indexed objects won't be reflected in search until a commit is
|
213
221
|
# sent - see Sunspot.index! and Sunspot.commit
|
@@ -223,7 +231,7 @@ module Sunspot
|
|
223
231
|
# ==== Parameters
|
224
232
|
#
|
225
233
|
# clazz<Class>:: the class of the objects to be updated
|
226
|
-
# updates<Hash>:: hash of updates where keys are model ids
|
234
|
+
# updates<Hash>:: hash of updates where keys are models or model ids
|
227
235
|
# and values are hash with property name/values to be updated
|
228
236
|
#
|
229
237
|
def atomic_update!(clazz, updates = {})
|
data/spec/api/binding_spec.rb
CHANGED
@@ -36,6 +36,17 @@ describe "DSL bindings" do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
|
+
expect(value).to eq('value')
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should give access to calling context\'s methods with keyword arguments' do
|
43
|
+
value = nil
|
44
|
+
session.search(Post) do
|
45
|
+
any_of do
|
46
|
+
value = kwargs_method(a: 10, b: 20)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
expect(value).to eq({ a: 10, b: 20 })
|
39
50
|
end
|
40
51
|
|
41
52
|
private
|
@@ -47,4 +58,8 @@ describe "DSL bindings" do
|
|
47
58
|
def id
|
48
59
|
16
|
49
60
|
end
|
61
|
+
|
62
|
+
def kwargs_method(a:, b:)
|
63
|
+
{ a: a, b: b }
|
64
|
+
end
|
50
65
|
end
|
@@ -98,7 +98,7 @@ describe 'indexing attribute fields', :type => :indexer do
|
|
98
98
|
|
99
99
|
it 'should index latitude and longitude passed as non-Floats' do
|
100
100
|
coordinates = Sunspot::Util::Coordinates.new(
|
101
|
-
BigDecimal
|
101
|
+
BigDecimal('40.7'), BigDecimal('-73.5'))
|
102
102
|
session.index(post(:coordinates => coordinates))
|
103
103
|
expect(connection).to have_add_with(:coordinates_s => 'dr5xx3nytvgs')
|
104
104
|
end
|
@@ -60,4 +60,91 @@ describe 'document removal', :type => :indexer do
|
|
60
60
|
end
|
61
61
|
expect(connection).to have_delete_by_query("(type:Post AND title_ss:monkeys)")
|
62
62
|
end
|
63
|
+
|
64
|
+
context 'when call #remove_by_id' do
|
65
|
+
let(:post) { clazz.new(title: 'A Title') }
|
66
|
+
before(:each) { index_post(post) }
|
67
|
+
|
68
|
+
context 'and `id_prefix` is defined on model' do
|
69
|
+
context 'as Proc' do
|
70
|
+
let(:clazz) { PostWithProcPrefixId }
|
71
|
+
let(:id_prefix) { lambda { |post| "USERDATA-#{post.id}!" } }
|
72
|
+
|
73
|
+
it 'prints warning' do
|
74
|
+
expect do
|
75
|
+
session.remove_by_id(clazz, post.id)
|
76
|
+
end.to output(Sunspot::RemoveByIdNotSupportCompositeIdMessage.call(clazz) + "\n").to_stderr
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'does not remove record' do
|
80
|
+
session.remove_by_id(clazz, post.id)
|
81
|
+
expect(connection).to have_no_delete(post_solr_id)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'as Symbol' do
|
86
|
+
let(:clazz) { PostWithSymbolPrefixId }
|
87
|
+
let(:id_prefix) { lambda { |post| "#{post.title}!" } }
|
88
|
+
|
89
|
+
it 'prints warning' do
|
90
|
+
expect do
|
91
|
+
session.remove_by_id(clazz, post.id)
|
92
|
+
end.to output(Sunspot::RemoveByIdNotSupportCompositeIdMessage.call(clazz) + "\n").to_stderr
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'does not remove record' do
|
96
|
+
session.remove_by_id(clazz, post.id)
|
97
|
+
expect(connection).to have_no_delete(post_solr_id)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'as String' do
|
102
|
+
let(:clazz) { PostWithStringPrefixId }
|
103
|
+
let(:id_prefix) { 'USERDATA!' }
|
104
|
+
|
105
|
+
it 'does not print warning' do
|
106
|
+
expect do
|
107
|
+
session.remove_by_id(clazz, post.id)
|
108
|
+
end.to_not output(Sunspot::RemoveByIdNotSupportCompositeIdMessage.call(clazz) + "\n").to_stderr
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'removes record' do
|
112
|
+
session.remove_by_id(clazz, post.id)
|
113
|
+
expect(connection).to have_delete(post_solr_id)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'and `id_prefix` is not defined on model' do
|
119
|
+
let(:clazz) { PostWithoutPrefixId }
|
120
|
+
let(:id_prefix) { nil }
|
121
|
+
|
122
|
+
it 'does not print warning' do
|
123
|
+
expect do
|
124
|
+
session.remove_by_id(clazz, post.id)
|
125
|
+
end.to_not output(Sunspot::RemoveByIdNotSupportCompositeIdMessage.call(clazz) + "\n").to_stderr
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'removes record' do
|
129
|
+
session.remove_by_id(clazz, post.id)
|
130
|
+
expect(connection).to have_delete(post_solr_id)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'and `id_prefix` is passed along with `class_name`' do
|
135
|
+
let(:clazz) { PostWithProcPrefixId }
|
136
|
+
let(:id_prefix) { lambda { |post| "USERDATA-#{post.id}!" } }
|
137
|
+
|
138
|
+
it 'does not print warning' do
|
139
|
+
expect do
|
140
|
+
session.remove_by_id("USERDATA-#{post.id}!#{clazz.name}", post.id)
|
141
|
+
end.to_not output(Sunspot::RemoveByIdNotSupportCompositeIdMessage.call(clazz) + "\n").to_stderr
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'removes record' do
|
145
|
+
session.remove_by_id("USERDATA-#{post.id}!#{clazz.name}", post.id)
|
146
|
+
expect(connection).to have_delete(post_solr_id)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
63
150
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
shared_examples_for "query with connective scope and boost" do
|
2
|
+
it 'creates a boost query' do
|
3
|
+
search do
|
4
|
+
boost(10) do
|
5
|
+
any_of do
|
6
|
+
with(:coordinates_new).in_bounding_box([23, -46], [25, -44])
|
7
|
+
with(:coordinates_new).in_bounding_box([42, 56], [43, 58])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
expect(connection).to have_last_search_including(
|
13
|
+
:bq, '(coordinates_new_ll:[23,-46 TO 25,-44] OR coordinates_new_ll:[42,56 TO 43,58])^10'
|
14
|
+
)
|
15
|
+
|
16
|
+
expect(connection).to have_last_search_including(
|
17
|
+
:defType, 'edismax'
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'creates a boost function' do
|
22
|
+
search do
|
23
|
+
boost(function() { field(:average_rating) })
|
24
|
+
end
|
25
|
+
|
26
|
+
expect(connection).to have_last_search_including(
|
27
|
+
:bf, 'field(average_rating_ft)'
|
28
|
+
)
|
29
|
+
|
30
|
+
expect(connection).to have_last_search_including(
|
31
|
+
:defType, 'edismax'
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'creates a multiplicative boost function' do
|
36
|
+
search do
|
37
|
+
boost_multiplicative(function() { field(:average_rating) })
|
38
|
+
end
|
39
|
+
|
40
|
+
expect(connection).to have_last_search_including(
|
41
|
+
:boost, 'field(average_rating_ft)'
|
42
|
+
)
|
43
|
+
|
44
|
+
expect(connection).to have_last_search_including(
|
45
|
+
:defType, 'edismax'
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'creates combined boost search' do
|
50
|
+
search do
|
51
|
+
boost(10) do
|
52
|
+
any_of do
|
53
|
+
with(:coordinates_new).in_bounding_box([23, -46], [25, -44])
|
54
|
+
with(:coordinates_new).in_bounding_box([42, 56], [43, 58])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
boost(function() { field(:average_rating) })
|
59
|
+
boost_multiplicative(function() { field(:average_rating) })
|
60
|
+
end
|
61
|
+
|
62
|
+
expect(connection).to have_last_search_including(
|
63
|
+
:bq, '(coordinates_new_ll:[23,-46 TO 25,-44] OR coordinates_new_ll:[42,56 TO 43,58])^10'
|
64
|
+
)
|
65
|
+
|
66
|
+
expect(connection).to have_last_search_including(
|
67
|
+
:bf, 'field(average_rating_ft)'
|
68
|
+
)
|
69
|
+
|
70
|
+
expect(connection).to have_last_search_including(
|
71
|
+
:boost, 'field(average_rating_ft)'
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'avoids duplicate boost functions' do
|
76
|
+
search do
|
77
|
+
boost(function() { field(:average_rating) })
|
78
|
+
boost(function() { field(:average_rating) })
|
79
|
+
boost_multiplicative(function() { field(:average_rating) })
|
80
|
+
end
|
81
|
+
|
82
|
+
expect(connection.searches.last[:bf]).to eq ['field(average_rating_ft)']
|
83
|
+
expect(connection.searches.last[:boost]).to eq ['field(average_rating_ft)']
|
84
|
+
end
|
85
|
+
end
|
@@ -10,7 +10,7 @@ shared_examples_for 'geohash query' do
|
|
10
10
|
|
11
11
|
it 'searches for nearby points with non-Float arguments' do
|
12
12
|
search do
|
13
|
-
with(:coordinates).near(BigDecimal
|
13
|
+
with(:coordinates).near(BigDecimal('40.7'), BigDecimal('-73.5'))
|
14
14
|
end
|
15
15
|
expect(connection).to have_last_search_including(:q, build_geo_query)
|
16
16
|
end
|
data/spec/api/query/join_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe 'join' do
|
|
6
6
|
with(:caption, 'blah')
|
7
7
|
end
|
8
8
|
expect(connection).to have_last_search_including(
|
9
|
-
:fq, "{!join from=photo_container_id_i to=id_i
|
9
|
+
:fq, "{!join from=photo_container_id_i to=id_i v='type:\"Photo\" AND caption_s:\"blah\"'}")
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'should greater_than search by join' do
|
@@ -14,6 +14,6 @@ describe 'join' do
|
|
14
14
|
with(:photo_rating).greater_than(3)
|
15
15
|
end
|
16
16
|
expect(connection).to have_last_search_including(
|
17
|
-
:fq, "{!join from=photo_container_id_i to=id_i
|
17
|
+
:fq, "{!join from=photo_container_id_i to=id_i v='type:\"Photo\" AND average_rating_ft:{3\\.0 TO *}'}")
|
18
18
|
end
|
19
19
|
end
|
@@ -4,6 +4,7 @@ describe 'standard query', :type => :query do
|
|
4
4
|
it_should_behave_like "scoped query"
|
5
5
|
it_should_behave_like "query with advanced manipulation"
|
6
6
|
it_should_behave_like "query with connective scope"
|
7
|
+
it_should_behave_like "query with connective scope and boost"
|
7
8
|
it_should_behave_like "query with dynamic field support"
|
8
9
|
it_should_behave_like "facetable query"
|
9
10
|
it_should_behave_like "fulltext query"
|
@@ -22,6 +23,15 @@ describe 'standard query', :type => :query do
|
|
22
23
|
expect(connection).to have_last_search_with(:q => '*:*')
|
23
24
|
end
|
24
25
|
|
26
|
+
it 'adds a no-op query to :q parameter when only a boost query provided' do
|
27
|
+
session.search Post do
|
28
|
+
boost(2) do
|
29
|
+
with :title, 'My Pet Post'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
expect(connection).to have_last_search_with(:q => '*:*')
|
33
|
+
end
|
34
|
+
|
25
35
|
private
|
26
36
|
|
27
37
|
def search(*classes, &block)
|
@@ -1,12 +1,12 @@
|
|
1
1
|
describe 'typed query' do
|
2
2
|
it 'properly escapes namespaced type names' do
|
3
3
|
session.search(Namespaced::Comment)
|
4
|
-
expect(connection).to have_last_search_with(:fq => ['type:Namespaced\:\:Comment'])
|
4
|
+
expect(connection).to have_last_search_with(:fq => ['type:"Namespaced\:\:Comment"'])
|
5
5
|
end
|
6
6
|
|
7
7
|
it 'builds search for multiple types' do
|
8
8
|
session.search(Post, Namespaced::Comment)
|
9
|
-
expect(connection).to have_last_search_with(:fq => ['type:(Post OR Namespaced\:\:Comment)'])
|
9
|
+
expect(connection).to have_last_search_with(:fq => ['type:(Post OR "Namespaced\:\:Comment")'])
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'searches type of subclass when superclass is configured' do
|
@@ -38,7 +38,7 @@ describe Sunspot::SessionProxy::MasterSlaveSessionProxy do
|
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'should raise ArgumentError when bogus config specified' do
|
41
|
-
expect { @proxy.config(:bogus) }.to raise_error
|
41
|
+
expect { @proxy.config(:bogus) }.to raise_error(ArgumentError)
|
42
42
|
end
|
43
43
|
|
44
44
|
it_should_behave_like 'session proxy'
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
require 'uri'
|
2
3
|
|
3
4
|
describe Sunspot::SessionProxy::Retry5xxSessionProxy do
|
4
|
-
|
5
|
+
|
5
6
|
before :each do
|
6
7
|
Sunspot::Session.connection_class = Mock::ConnectionFactory.new
|
7
8
|
@sunspot_session = Sunspot.session
|
@@ -21,11 +22,14 @@ describe Sunspot::SessionProxy::Retry5xxSessionProxy do
|
|
21
22
|
end
|
22
23
|
|
23
24
|
let :fake_rsolr_request do
|
24
|
-
{:uri => 'http://solr.test/uri'}
|
25
|
+
{:uri => URI('http://solr.test/uri')}
|
25
26
|
end
|
26
27
|
|
27
28
|
def fake_rsolr_response(status)
|
28
|
-
{
|
29
|
+
{
|
30
|
+
:status => status.to_s,
|
31
|
+
:body => ''
|
32
|
+
}
|
29
33
|
end
|
30
34
|
|
31
35
|
let :post do
|
@@ -67,12 +71,12 @@ describe Sunspot::SessionProxy::Retry5xxSessionProxy do
|
|
67
71
|
it "should not retry a 4xx" do
|
68
72
|
e = FakeRSolrErrorHttp.new(fake_rsolr_request, fake_rsolr_response(400))
|
69
73
|
expect(@sunspot_session).to receive(:index).and_raise(e)
|
70
|
-
expect { Sunspot.index(post) }.to raise_error
|
74
|
+
expect { Sunspot.index(post) }.to raise_error(FakeRSolrErrorHttp)
|
71
75
|
end
|
72
76
|
|
73
77
|
# TODO: try against more than just Sunspot.index? but that's just testing the
|
74
78
|
# invocation of delegate, so probably not important. -nz 11Apr12
|
75
79
|
|
76
80
|
it_should_behave_like 'session proxy'
|
77
|
-
|
81
|
+
|
78
82
|
end
|
data/spec/api/session_spec.rb
CHANGED
@@ -109,7 +109,7 @@ describe 'Session' do
|
|
109
109
|
it 'should open a connection with custom read timeout' do
|
110
110
|
Sunspot.config.solr.read_timeout = 0.5
|
111
111
|
Sunspot.commit
|
112
|
-
expect(connection.opts[:
|
112
|
+
expect(connection.opts[:timeout]).to eq(0.5)
|
113
113
|
end
|
114
114
|
|
115
115
|
it 'should open a connection with custom open timeout' do
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Sunspot::Setup do
|
4
|
+
context '#id_prefix_for_class' do
|
5
|
+
subject { Sunspot::Setup.for(clazz).id_prefix_for_class }
|
6
|
+
|
7
|
+
context 'when `id_prefix` is defined on model' do
|
8
|
+
context 'as Proc' do
|
9
|
+
let(:clazz) { PostWithProcPrefixId }
|
10
|
+
|
11
|
+
it 'returns nil' do
|
12
|
+
is_expected.to be_nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'as Symbol' do
|
17
|
+
let(:clazz) { PostWithSymbolPrefixId }
|
18
|
+
|
19
|
+
it 'returns nil' do
|
20
|
+
is_expected.to be_nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'as String' do
|
25
|
+
let(:clazz) { PostWithStringPrefixId }
|
26
|
+
|
27
|
+
it 'returns `id_prefix` value' do
|
28
|
+
is_expected.to eq('USERDATA!')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when `id_prefix` is not defined on model' do
|
34
|
+
let(:clazz) { PostWithoutPrefixId }
|
35
|
+
|
36
|
+
it 'returns nil' do
|
37
|
+
is_expected.to be_nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context '#id_prefix_defined?' do
|
43
|
+
subject { Sunspot::Setup.for(clazz).id_prefix_defined? }
|
44
|
+
|
45
|
+
context 'when `id_prefix` is defined on model' do
|
46
|
+
let(:clazz) { PostWithProcPrefixId }
|
47
|
+
|
48
|
+
it 'returns true' do
|
49
|
+
is_expected.to be_truthy
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when `id_prefix` is not defined on model' do
|
54
|
+
let(:clazz) { PostWithoutPrefixId }
|
55
|
+
|
56
|
+
it 'returns false' do
|
57
|
+
is_expected.to be_falsey
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context '#id_prefix_requires_instance?' do
|
63
|
+
subject { Sunspot::Setup.for(clazz).id_prefix_requires_instance? }
|
64
|
+
|
65
|
+
context 'when `id_prefix` is defined on model' do
|
66
|
+
context 'as Proc' do
|
67
|
+
let(:clazz) { PostWithProcPrefixId }
|
68
|
+
|
69
|
+
it 'returns true' do
|
70
|
+
is_expected.to be_truthy
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'as Symbol' do
|
75
|
+
let(:clazz) { PostWithSymbolPrefixId }
|
76
|
+
|
77
|
+
it 'returns true' do
|
78
|
+
is_expected.to be_truthy
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'as String' do
|
83
|
+
let(:clazz) { PostWithStringPrefixId }
|
84
|
+
|
85
|
+
it 'returns false' do
|
86
|
+
is_expected.to be_falsey
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'when `id_prefix` is not defined on model' do
|
92
|
+
let(:clazz) { PostWithoutPrefixId }
|
93
|
+
|
94
|
+
it 'returns false' do
|
95
|
+
is_expected.to be_falsey
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -14,4 +14,26 @@ module IndexerHelper
|
|
14
14
|
def values_in_last_document_for(field_name)
|
15
15
|
@connection.adds.last.last.fields_by_name(field_name).map { |field| field.value }
|
16
16
|
end
|
17
|
+
|
18
|
+
def index_post(post)
|
19
|
+
Sunspot.index!(post)
|
20
|
+
hit = find_post(post)
|
21
|
+
expect(hit).not_to be_nil
|
22
|
+
hit
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_post(post)
|
26
|
+
Sunspot.search(clazz).hits.find { |h| h.primary_key.to_i == post.id && h.id_prefix == id_prefix_value(post, id_prefix) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def id_prefix_value(post, id_prefix)
|
30
|
+
return unless id_prefix
|
31
|
+
return id_prefix if id_prefix.is_a?(String)
|
32
|
+
|
33
|
+
id_prefix.call(post)
|
34
|
+
end
|
35
|
+
|
36
|
+
def post_solr_id
|
37
|
+
"#{id_prefix_value(post, id_prefix)}#{clazz} #{post.id}"
|
38
|
+
end
|
17
39
|
end
|