rsolr 0.12.0 → 2.6.0
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 +7 -0
- data/.github/workflows/ruby.yml +29 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/CHANGES.txt +63 -260
- data/Gemfile +13 -0
- data/README.rdoc +177 -63
- data/Rakefile +19 -0
- data/lib/rsolr/char.rb +6 -0
- data/lib/rsolr/client.rb +344 -86
- data/lib/rsolr/document.rb +66 -0
- data/lib/rsolr/error.rb +182 -0
- data/lib/rsolr/field.rb +87 -0
- data/lib/rsolr/generator.rb +5 -0
- data/lib/rsolr/json.rb +60 -0
- data/lib/rsolr/response.rb +95 -0
- data/lib/rsolr/uri.rb +25 -0
- data/lib/rsolr/version.rb +7 -0
- data/lib/rsolr/xml.rb +150 -0
- data/lib/rsolr.rb +47 -35
- data/rsolr.gemspec +44 -31
- data/spec/api/client_spec.rb +423 -0
- data/spec/api/document_spec.rb +48 -0
- data/spec/api/error_spec.rb +158 -0
- data/spec/api/json_spec.rb +248 -0
- data/spec/api/pagination_spec.rb +31 -0
- data/spec/api/rsolr_spec.rb +31 -0
- data/spec/api/uri_spec.rb +37 -0
- data/spec/api/xml_spec.rb +255 -0
- data/spec/fixtures/basic_configs/_rest_managed.json +1 -0
- data/spec/fixtures/basic_configs/currency.xml +67 -0
- data/spec/fixtures/basic_configs/lang/stopwords_en.txt +54 -0
- data/spec/fixtures/basic_configs/protwords.txt +21 -0
- data/spec/fixtures/basic_configs/schema.xml +530 -0
- data/spec/fixtures/basic_configs/solrconfig.xml +572 -0
- data/spec/fixtures/basic_configs/stopwords.txt +14 -0
- data/spec/fixtures/basic_configs/synonyms.txt +29 -0
- data/spec/integration/solr5_spec.rb +38 -0
- data/spec/lib/rsolr/client_spec.rb +19 -0
- data/spec/spec_helper.rb +94 -0
- metadata +228 -54
- data/lib/rsolr/connection/net_http.rb +0 -48
- data/lib/rsolr/connection/requestable.rb +0 -43
- data/lib/rsolr/connection/utils.rb +0 -73
- data/lib/rsolr/connection.rb +0 -9
- data/lib/rsolr/message/document.rb +0 -48
- data/lib/rsolr/message/field.rb +0 -20
- data/lib/rsolr/message/generator.rb +0 -89
- data/lib/rsolr/message.rb +0 -8
data/lib/rsolr.rb
CHANGED
@@ -1,40 +1,52 @@
|
|
1
|
-
|
2
|
-
require 'rubygems'
|
3
|
-
$:.unshift File.dirname(__FILE__) unless $:.include?(File.dirname(__FILE__))
|
4
|
-
|
5
1
|
module RSolr
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
autoload :Message, 'rsolr/message'
|
2
|
+
require 'rsolr/version'
|
3
|
+
|
4
|
+
autoload :Char, 'rsolr/char'
|
10
5
|
autoload :Client, 'rsolr/client'
|
11
|
-
autoload :
|
12
|
-
|
13
|
-
|
14
|
-
|
6
|
+
autoload :Document, 'rsolr/document'
|
7
|
+
autoload :Error, 'rsolr/error'
|
8
|
+
autoload :Field, 'rsolr/field'
|
9
|
+
autoload :Generator, 'rsolr/generator'
|
10
|
+
autoload :HashWithResponse, 'rsolr/response'
|
11
|
+
autoload :JSON, 'rsolr/json'
|
12
|
+
autoload :Response, 'rsolr/response'
|
13
|
+
autoload :Uri, 'rsolr/uri'
|
14
|
+
autoload :Xml, 'rsolr/xml'
|
15
|
+
|
16
|
+
def self.connect *args
|
17
|
+
opts = args.pop if args.last.is_a?(::Hash)
|
18
|
+
opts ||= {}
|
19
|
+
|
20
|
+
connection = args.first
|
21
|
+
|
22
|
+
Client.new connection, opts
|
23
|
+
end
|
24
|
+
|
25
|
+
# backslash escape characters that have special meaning to Solr query parser
|
26
|
+
# per http://lucene.apache.org/core/4_0_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Escaping_Special_Characters
|
27
|
+
# + - & | ! ( ) { } [ ] ^ " ~ * ? : \ /
|
28
|
+
# see also http://svn.apache.org/repos/asf/lucene/dev/tags/lucene_solr_4_9_1/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
|
29
|
+
# escapeQueryChars method
|
30
|
+
# @return [String] str with special chars preceded by a backslash
|
31
|
+
def self.solr_escape(str)
|
32
|
+
# note that the gsub will parse the escaped backslashes, as will the ruby code sending the query to Solr
|
33
|
+
# so the result sent to Solr is ultimately a single backslash in front of the particular character
|
34
|
+
str.gsub(/([+\-&|!\(\)\{\}\[\]\^"~\*\?:\\\/])/, '\\\\\1')
|
15
35
|
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
36
|
+
|
37
|
+
module Array
|
38
|
+
def self.wrap(object)
|
39
|
+
if object.nil?
|
40
|
+
[nil]
|
41
|
+
elsif object.respond_to?(:to_ary)
|
42
|
+
object.to_ary || [object]
|
43
|
+
elsif object.is_a? Hash
|
44
|
+
[object]
|
45
|
+
elsif object.is_a? Enumerable
|
46
|
+
object
|
47
|
+
else
|
48
|
+
[object]
|
49
|
+
end
|
25
50
|
end
|
26
|
-
|
27
51
|
end
|
28
|
-
|
29
|
-
# send the escape method into the Connection class ->
|
30
|
-
# solr = RSolr.connect
|
31
|
-
# solr.escape('asdf')
|
32
|
-
RSolr::Client.send(:include, Char)
|
33
|
-
|
34
|
-
# bring escape into this module (RSolr) -> RSolr.escape('asdf')
|
35
|
-
extend Char
|
36
|
-
|
37
|
-
# RequestError is a common/generic exception class used by the adapters
|
38
|
-
class RequestError < RuntimeError; end
|
39
|
-
|
40
|
-
end
|
52
|
+
end
|
data/rsolr.gemspec
CHANGED
@@ -1,32 +1,45 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
require "rsolr/version"
|
5
|
+
|
1
6
|
Gem::Specification.new do |s|
|
2
|
-
|
3
|
-
s.
|
4
|
-
s.
|
5
|
-
s.
|
6
|
-
s.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
"
|
21
|
-
|
22
|
-
"
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
s.
|
32
|
-
|
7
|
+
s.name = "rsolr"
|
8
|
+
s.summary = "A Ruby client for Apache Solr"
|
9
|
+
s.description = %q{RSolr aims to provide a simple and extensible library for working with Solr}
|
10
|
+
s.version = RSolr::VERSION
|
11
|
+
s.authors = ["Antoine Latter", "Dmitry Lihachev",
|
12
|
+
"Lucas Souza", "Peter Kieltyka",
|
13
|
+
"Rob Di Marco", "Magnus Bergmark",
|
14
|
+
"Jonathan Rochkind", "Chris Beer",
|
15
|
+
"Craig Smith", "Randy Souza",
|
16
|
+
"Colin Steele", "Peter Kieltyka",
|
17
|
+
"Lorenzo Riccucci", "Mike Perham",
|
18
|
+
"Mat Brown", "Shairon Toledo",
|
19
|
+
"Matthew Rudy", "Fouad Mardini",
|
20
|
+
"Jeremy Hinegardner", "Nathan Witmer",
|
21
|
+
"Naomi Dushay",
|
22
|
+
"\"shima\""]
|
23
|
+
s.email = ["goodieboy@gmail.com"]
|
24
|
+
s.license = 'Apache-2.0'
|
25
|
+
s.homepage = "https://github.com/rsolr/rsolr"
|
26
|
+
s.files = `git ls-files`.split("\n")
|
27
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
28
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
29
|
+
s.require_paths = ["lib"]
|
30
|
+
|
31
|
+
s.required_ruby_version = '>= 1.9.3'
|
32
|
+
|
33
|
+
s.requirements << 'Apache Solr'
|
34
|
+
|
35
|
+
s.add_dependency 'builder', '>= 2.1.2'
|
36
|
+
s.add_dependency 'faraday', '>= 0.9', '!= 2.0.0', '< 3'
|
37
|
+
|
38
|
+
s.add_development_dependency 'activesupport'
|
39
|
+
s.add_development_dependency 'nokogiri', '>= 1.4.0'
|
40
|
+
s.add_development_dependency 'rake', '>= 10.0'
|
41
|
+
s.add_development_dependency 'rdoc', '>= 4.0'
|
42
|
+
s.add_development_dependency 'rspec', '~> 3.0'
|
43
|
+
s.add_development_dependency 'simplecov'
|
44
|
+
s.add_development_dependency 'solr_wrapper'
|
45
|
+
end
|
@@ -0,0 +1,423 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe RSolr::Client do
|
4
|
+
let(:connection) { nil }
|
5
|
+
let(:url) { "http://localhost:9999/solr" }
|
6
|
+
let(:connection_options) { { url: url, update_format: :xml } }
|
7
|
+
|
8
|
+
let(:client) do
|
9
|
+
RSolr::Client.new connection, connection_options
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:client_with_proxy) do
|
13
|
+
RSolr::Client.new connection, connection_options.merge(proxy: 'http://localhost:8080')
|
14
|
+
end
|
15
|
+
|
16
|
+
context "initialize" do
|
17
|
+
it "should accept whatevs and set it as the @connection" do
|
18
|
+
expect(RSolr::Client.new(:whatevs).connection).to eq(:whatevs)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should use :update_path from options" do
|
22
|
+
client = RSolr::Client.new(:whatevs, { update_path: 'update_test' })
|
23
|
+
expect(client.update_path).to eql('update_test')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should use 'update' for update_path by default" do
|
27
|
+
client = RSolr::Client.new(:whatevs)
|
28
|
+
expect(client.update_path).to eql('update')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should use :proxy from options" do
|
32
|
+
client = RSolr::Client.new(:whatevs, { proxy: 'http://my.proxy/' })
|
33
|
+
expect(client.proxy.to_s).to eql('http://my.proxy/')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should use 'nil' for proxy by default" do
|
37
|
+
client = RSolr::Client.new(:whatevs)
|
38
|
+
expect(client.proxy).to be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should use 'false' for proxy if passed 'false'" do
|
42
|
+
client = RSolr::Client.new(:whatevs, { proxy: false })
|
43
|
+
expect(client.proxy).to eq(false)
|
44
|
+
end
|
45
|
+
|
46
|
+
context "with an non-HTTP url" do
|
47
|
+
let(:url) { "fake://localhost:9999/solr" }
|
48
|
+
|
49
|
+
it "raises an argument error" do
|
50
|
+
expect { client }.to raise_error ArgumentError, "You must provide an HTTP(S) url."
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "with an HTTPS url" do
|
55
|
+
let(:url) { "https://localhost:9999/solr" }
|
56
|
+
|
57
|
+
it "creates a connection" do
|
58
|
+
expect(client.uri).to be_kind_of URI::HTTPS
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
context "send_and_receive" do
|
65
|
+
it "should forward these method calls the #connection object" do
|
66
|
+
[:get, :post, :head].each do |meth|
|
67
|
+
expect(client).to receive(:execute).
|
68
|
+
and_return({:status => 200, :body => "{}", :headers => {}})
|
69
|
+
client.send_and_receive '', :method => meth, :params => {}, :data => nil, :headers => {}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "execute" do
|
75
|
+
it "maps Faraday::TimeoutError to an RSolr::Error::Timeout" do
|
76
|
+
allow(client.connection).to receive(:send).and_raise(Faraday::TimeoutError)
|
77
|
+
|
78
|
+
expect{ client.execute({}) }.to raise_error RSolr::Error::Timeout
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when an Errno::ECONNREFUSED error is raised' do
|
82
|
+
let(:uri) { URI.parse('http://admin:secret@hostname.local:8983/solr/admin/update?wt=json&q=test') }
|
83
|
+
|
84
|
+
before do
|
85
|
+
allow(client.connection).to receive(:send).and_raise(Errno::ECONNREFUSED)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "maps error to RSolr::Error:ConnectionRefused" do
|
89
|
+
expect { client.execute({ uri: uri }) }.to raise_error RSolr::Error::ConnectionRefused
|
90
|
+
end
|
91
|
+
|
92
|
+
it "removes credentials from uri" do
|
93
|
+
expect {
|
94
|
+
client.execute({ uri: uri })
|
95
|
+
}.to raise_error(RSolr::Error::ConnectionRefused, /http:\/\/REDACTED:REDACTED@hostname\.local:8983/)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "post" do
|
101
|
+
it "should pass the expected params to the connection's #execute method" do
|
102
|
+
request_opts = {:data => "the data", :method=>:post, :headers => {"Content-Type" => "text/plain"}}
|
103
|
+
expect(client).to receive(:execute).
|
104
|
+
with(hash_including(request_opts)).
|
105
|
+
and_return(
|
106
|
+
:body => "",
|
107
|
+
:status => 200,
|
108
|
+
:headers => {"Content-Type"=>"text/plain"}
|
109
|
+
)
|
110
|
+
client.post "update", request_opts
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "add" do
|
115
|
+
it "should send xml to the connection's #post method" do
|
116
|
+
expect(client).to receive(:execute).
|
117
|
+
with(
|
118
|
+
hash_including({
|
119
|
+
:path => "update",
|
120
|
+
:headers => {"Content-Type"=>"text/xml"},
|
121
|
+
:method => :post,
|
122
|
+
:data => "<xml/>"
|
123
|
+
})
|
124
|
+
).
|
125
|
+
and_return(
|
126
|
+
:body => "",
|
127
|
+
:status => 200,
|
128
|
+
:headers => {"Content-Type"=>"text/xml"}
|
129
|
+
)
|
130
|
+
expect(client.builder).to receive(:add).
|
131
|
+
with({:id=>1}, {:commitWith=>10}).
|
132
|
+
and_return("<xml/>")
|
133
|
+
client.add({:id=>1}, :add_attributes => {:commitWith=>10})
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'when the client is configured for json updates' do
|
137
|
+
let(:client) do
|
138
|
+
RSolr::Client.new nil, :url => "http://localhost:9999/solr", :update_format => :json
|
139
|
+
end
|
140
|
+
it "should send json to the connection's #post method" do
|
141
|
+
expect(client).to receive(:execute).
|
142
|
+
with(hash_including({
|
143
|
+
:path => 'update',
|
144
|
+
:headers => {"Content-Type" => 'application/json'},
|
145
|
+
:method => :post,
|
146
|
+
:data => '{"hello":"this is json"}'
|
147
|
+
})
|
148
|
+
).
|
149
|
+
and_return(
|
150
|
+
:body => "",
|
151
|
+
:status => 200,
|
152
|
+
:headers => {"Content-Type"=>"text/xml"}
|
153
|
+
)
|
154
|
+
expect(client.builder).to receive(:add).
|
155
|
+
with({:id => 1}, {:commitWith=>10}).
|
156
|
+
and_return('{"hello":"this is json"}')
|
157
|
+
client.add({:id=>1}, :add_attributes => {:commitWith=>10})
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should send json to the connection's #post method" do
|
161
|
+
expect(client).to receive(:execute).
|
162
|
+
with(hash_including({
|
163
|
+
:path => 'update',
|
164
|
+
:headers => {'Content-Type'=>'application/json'},
|
165
|
+
:method => :post,
|
166
|
+
:data => '{"optimise" : {}}'
|
167
|
+
})
|
168
|
+
).
|
169
|
+
and_return(
|
170
|
+
:body => "",
|
171
|
+
:status => 200,
|
172
|
+
:headers => {"Content-Type"=>"text/xml"}
|
173
|
+
)
|
174
|
+
client.update(:data => '{"optimise" : {}}')
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "update" do
|
180
|
+
it "should send data to the connection's #post method" do
|
181
|
+
expect(client).to receive(:execute).
|
182
|
+
with(hash_including({
|
183
|
+
:path => "update",
|
184
|
+
:headers => {"Content-Type"=>"text/xml"},
|
185
|
+
:method => :post,
|
186
|
+
:data => "<optimize/>"
|
187
|
+
})
|
188
|
+
).
|
189
|
+
and_return(
|
190
|
+
:body => "",
|
191
|
+
:status => 200,
|
192
|
+
:headers => {"Content-Type"=>"text/xml"}
|
193
|
+
)
|
194
|
+
client.update(:data => "<optimize/>")
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should use #update_path" do
|
198
|
+
expect(client).to receive(:post).with('update_test', any_args)
|
199
|
+
expect(client).to receive(:update_path).and_return('update_test')
|
200
|
+
client.update({})
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should use path from opts" do
|
204
|
+
expect(client).to receive(:post).with('update_opts', any_args)
|
205
|
+
allow(client).to receive(:update_path).and_return('update_test')
|
206
|
+
client.update({path: 'update_opts'})
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context "post based helper methods:" do
|
211
|
+
[:commit, :optimize, :rollback].each do |meth|
|
212
|
+
it "should send a #{meth} message to the connection's #post method" do
|
213
|
+
expect(client).to receive(:execute).
|
214
|
+
with(hash_including({
|
215
|
+
:path => "update",
|
216
|
+
:headers => {"Content-Type"=>"text/xml"},
|
217
|
+
:method => :post,
|
218
|
+
:data => "<?xml version=\"1.0\" encoding=\"UTF-8\"?><#{meth}/>"
|
219
|
+
})
|
220
|
+
).
|
221
|
+
and_return(
|
222
|
+
:body => "",
|
223
|
+
:status => 200,
|
224
|
+
:headers => {"Content-Type"=>"text/xml"}
|
225
|
+
)
|
226
|
+
client.send meth
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context "delete_by_id" do
|
232
|
+
it "should send data to the connection's #post method" do
|
233
|
+
expect(client).to receive(:execute).
|
234
|
+
with(
|
235
|
+
hash_including({
|
236
|
+
:path => "update",
|
237
|
+
:headers => {"Content-Type"=>"text/xml"},
|
238
|
+
:method => :post,
|
239
|
+
:data => "<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><id>1</id></delete>"
|
240
|
+
})
|
241
|
+
).
|
242
|
+
and_return(
|
243
|
+
:body => "",
|
244
|
+
:status => 200,
|
245
|
+
:headers => {"Content-Type"=>"text/xml"}
|
246
|
+
)
|
247
|
+
client.delete_by_id 1
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context "delete_by_query" do
|
252
|
+
it "should send data to the connection's #post method" do
|
253
|
+
expect(client).to receive(:execute).
|
254
|
+
with(
|
255
|
+
hash_including({
|
256
|
+
:path => "update",
|
257
|
+
:headers => {"Content-Type"=>"text/xml"},
|
258
|
+
:method => :post,
|
259
|
+
:data => "<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><query fq=\"category:"trash"\"/></delete>"
|
260
|
+
})
|
261
|
+
).
|
262
|
+
and_return(
|
263
|
+
:body => "",
|
264
|
+
:status => 200,
|
265
|
+
:headers => {"Content-Type"=>"text/xml"}
|
266
|
+
)
|
267
|
+
client.delete_by_query :fq => "category:\"trash\""
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
context "adapt_response" do
|
272
|
+
it 'should not try to evaluate ruby when the :qt is not :ruby' do
|
273
|
+
body = '{"time"=>"NOW"}'
|
274
|
+
result = client.adapt_response({:params=>{}}, {:status => 200, :body => body, :headers => {}})
|
275
|
+
expect(result).to eq(body)
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'should evaluate ruby responses when the :wt is :ruby' do
|
279
|
+
body = '{"time"=>"NOW"}'
|
280
|
+
result = client.adapt_response({:params=>{:wt=>:ruby}}, {:status => 200, :body => body, :headers => {}})
|
281
|
+
expect(result).to eq({"time"=>"NOW"})
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'should evaluate json responses when the :wt is :json' do
|
285
|
+
body = '{"time": "NOW"}'
|
286
|
+
result = client.adapt_response({:params=>{:wt=>:json}}, {:status => 200, :body => body, :headers => {}})
|
287
|
+
if defined? JSON
|
288
|
+
expect(result).to eq({"time"=>"NOW"})
|
289
|
+
else
|
290
|
+
# ruby 1.8 without the JSON gem
|
291
|
+
expect(result).to eq('{"time": "NOW"}')
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'should return a response for a head request' do
|
296
|
+
result = client.adapt_response({:method=>:head,:params=>{}}, {:status => 200, :body => nil, :headers => {}})
|
297
|
+
expect(result.response[:status]).to eq 200
|
298
|
+
end
|
299
|
+
|
300
|
+
it "ought raise a RSolr::Error::InvalidRubyResponse when the ruby is indeed frugged, or even fruggified" do
|
301
|
+
expect {
|
302
|
+
client.adapt_response({:params=>{:wt => :ruby}}, {:status => 200, :body => "<woops/>", :headers => {}})
|
303
|
+
}.to raise_error RSolr::Error::InvalidRubyResponse
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
308
|
+
context "commit" do
|
309
|
+
it "should add hard commit params for hard commit request" do
|
310
|
+
expect(client).to receive(:execute).
|
311
|
+
with(
|
312
|
+
hash_including({
|
313
|
+
:path => "update",
|
314
|
+
:headers => {"Content-Type"=>"text/xml"},
|
315
|
+
:method => :post,
|
316
|
+
:data => "<?xml version=\"1.0\" encoding=\"UTF-8\"?><commit/>",
|
317
|
+
:params => {:wt=>:json},
|
318
|
+
:query => "wt=json"
|
319
|
+
})
|
320
|
+
).
|
321
|
+
and_return(
|
322
|
+
:body => "",
|
323
|
+
:status => 200,
|
324
|
+
:headers => {"Content-Type"=>"text/xml"}
|
325
|
+
)
|
326
|
+
client.commit
|
327
|
+
end
|
328
|
+
|
329
|
+
it "should add soft commit params for soft commit request" do
|
330
|
+
expect(client).to receive(:execute).
|
331
|
+
with(
|
332
|
+
hash_including({
|
333
|
+
:path => "update",
|
334
|
+
:headers => {"Content-Type"=>"text/xml"},
|
335
|
+
:method => :post,
|
336
|
+
:data => "<?xml version=\"1.0\" encoding=\"UTF-8\"?><commit/>",
|
337
|
+
:params => {:softCommit=>true, :wt=>:json},
|
338
|
+
:query => "wt=json&softCommit=true"
|
339
|
+
})
|
340
|
+
).
|
341
|
+
and_return(
|
342
|
+
:body => "",
|
343
|
+
:status => 200,
|
344
|
+
:headers => {"Content-Type"=>"text/xml"}
|
345
|
+
)
|
346
|
+
client.soft_commit
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
context "indifferent access" do
|
351
|
+
it "should raise a RuntimeError if the #with_indifferent_access extension isn't loaded" do
|
352
|
+
hide_const("::RSolr::HashWithIndifferentAccessWithResponse")
|
353
|
+
hide_const("ActiveSupport::HashWithIndifferentAccess")
|
354
|
+
body = "{'foo'=>'bar'}"
|
355
|
+
result = client.adapt_response({:params=>{:wt=>:ruby}}, {:status => 200, :body => body, :headers => {}})
|
356
|
+
expect { result.with_indifferent_access }.to raise_error RuntimeError
|
357
|
+
end
|
358
|
+
|
359
|
+
it "should provide indifferent access" do
|
360
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
361
|
+
body = "{'foo'=>'bar'}"
|
362
|
+
result = client.adapt_response({:params=>{:wt=>:ruby}}, {:status => 200, :body => body, :headers => {}})
|
363
|
+
indifferent_result = result.with_indifferent_access
|
364
|
+
|
365
|
+
expect(result).to be_a(RSolr::Response)
|
366
|
+
expect(result['foo']).to eq('bar')
|
367
|
+
expect(result[:foo]).to be_nil
|
368
|
+
|
369
|
+
expect(indifferent_result).to be_a(RSolr::Response)
|
370
|
+
expect(indifferent_result['foo']).to eq('bar')
|
371
|
+
expect(indifferent_result[:foo]).to eq('bar')
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
context "build_request" do
|
376
|
+
let(:data) { 'data' }
|
377
|
+
let(:params) { { q: 'test', fq: [0,1] } }
|
378
|
+
let(:options) { { method: :post, params: params, data: data, headers: {} } }
|
379
|
+
subject { client.build_request('select', options) }
|
380
|
+
|
381
|
+
context "when params are symbols" do
|
382
|
+
it 'should return a request context array' do
|
383
|
+
[/fq=0/, /fq=1/, /q=test/, /wt=json/].each do |pattern|
|
384
|
+
expect(subject[:query]).to match pattern
|
385
|
+
end
|
386
|
+
expect(subject[:data]).to eq("data")
|
387
|
+
expect(subject[:headers]).to eq({})
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
context "when params are strings" do
|
392
|
+
let(:params) { { 'q' => 'test', 'wt' => 'json' } }
|
393
|
+
it 'should return a request context array' do
|
394
|
+
expect(subject[:query]).to eq 'q=test&wt=json'
|
395
|
+
expect(subject[:data]).to eq("data")
|
396
|
+
expect(subject[:headers]).to eq({})
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
context "when a Hash is passed in as data" do
|
401
|
+
let(:data) { { q: 'test', fq: [0,1] } }
|
402
|
+
let(:options) { { method: :post, data: data, headers: {} } }
|
403
|
+
|
404
|
+
it "sets the Content-Type header to application/x-www-form-urlencoded; charset=UTF-8" do
|
405
|
+
expect(subject[:query]).to eq("wt=json")
|
406
|
+
[/fq=0/, /fq=1/, /q=test/].each do |pattern|
|
407
|
+
expect(subject[:data]).to match pattern
|
408
|
+
end
|
409
|
+
expect(subject[:data]).not_to match(/wt=json/)
|
410
|
+
expect(subject[:headers]).to eq({"Content-Type" => "application/x-www-form-urlencoded; charset=UTF-8"})
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
it "should properly handle proxy configuration" do
|
415
|
+
result = client_with_proxy.build_request('select',
|
416
|
+
:method => :post,
|
417
|
+
:data => {:q=>'test', :fq=>[0,1]},
|
418
|
+
:headers => {}
|
419
|
+
)
|
420
|
+
expect(result[:uri].to_s).to match %r{^http://localhost:9999/solr/}
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe RSolr::Document do
|
4
|
+
describe RSolr::Field do
|
5
|
+
describe ".instance" do
|
6
|
+
subject { RSolr::Field }
|
7
|
+
|
8
|
+
it "uses the class name of the field value" do
|
9
|
+
expect(subject.instance({}, Time.new)).to be_a_kind_of(RSolr::TimeField)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "uses the provided type option when it is a class" do
|
13
|
+
expect(subject.instance({:type => RSolr::TimeField}, nil)).to be_a_kind_of(RSolr::TimeField)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "uses the provided type option when it is a string" do
|
17
|
+
expect(subject.instance({:type => 'Time'}, nil)).to be_a_kind_of(RSolr::TimeField)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "falls back to the base Field class" do
|
21
|
+
expect(subject.instance({:type => 'UndefinedType'}, nil)).to be_a_kind_of(RSolr::Field)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "defaults to the base Field class" do
|
25
|
+
expect(subject.instance({}, nil)).to be_a_kind_of(RSolr::Field)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe RSolr::TimeField do
|
31
|
+
it "convert value to string" do
|
32
|
+
time_value = Time.utc(2013, 9, 11, 18, 10, 0)
|
33
|
+
expect(RSolr::Field.instance({}, time_value).value).to eq '2013-09-11T18:10:00Z'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "convert time to UTC" do
|
37
|
+
time_value = Time.new(2013, 9, 11, 18, 10, 0, '+02:00')
|
38
|
+
expect(RSolr::Field.instance({}, time_value).value).to eq '2013-09-11T16:10:00Z'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe RSolr::DateField do
|
43
|
+
it "convert value to string" do
|
44
|
+
date_value = Date.new(2013, 9, 11)
|
45
|
+
expect(RSolr::Field.instance({}, date_value).value).to eq '2013-09-11T00:00:00Z'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|