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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +29 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +2 -0
  5. data/CHANGES.txt +63 -260
  6. data/Gemfile +13 -0
  7. data/README.rdoc +177 -63
  8. data/Rakefile +19 -0
  9. data/lib/rsolr/char.rb +6 -0
  10. data/lib/rsolr/client.rb +344 -86
  11. data/lib/rsolr/document.rb +66 -0
  12. data/lib/rsolr/error.rb +182 -0
  13. data/lib/rsolr/field.rb +87 -0
  14. data/lib/rsolr/generator.rb +5 -0
  15. data/lib/rsolr/json.rb +60 -0
  16. data/lib/rsolr/response.rb +95 -0
  17. data/lib/rsolr/uri.rb +25 -0
  18. data/lib/rsolr/version.rb +7 -0
  19. data/lib/rsolr/xml.rb +150 -0
  20. data/lib/rsolr.rb +47 -35
  21. data/rsolr.gemspec +44 -31
  22. data/spec/api/client_spec.rb +423 -0
  23. data/spec/api/document_spec.rb +48 -0
  24. data/spec/api/error_spec.rb +158 -0
  25. data/spec/api/json_spec.rb +248 -0
  26. data/spec/api/pagination_spec.rb +31 -0
  27. data/spec/api/rsolr_spec.rb +31 -0
  28. data/spec/api/uri_spec.rb +37 -0
  29. data/spec/api/xml_spec.rb +255 -0
  30. data/spec/fixtures/basic_configs/_rest_managed.json +1 -0
  31. data/spec/fixtures/basic_configs/currency.xml +67 -0
  32. data/spec/fixtures/basic_configs/lang/stopwords_en.txt +54 -0
  33. data/spec/fixtures/basic_configs/protwords.txt +21 -0
  34. data/spec/fixtures/basic_configs/schema.xml +530 -0
  35. data/spec/fixtures/basic_configs/solrconfig.xml +572 -0
  36. data/spec/fixtures/basic_configs/stopwords.txt +14 -0
  37. data/spec/fixtures/basic_configs/synonyms.txt +29 -0
  38. data/spec/integration/solr5_spec.rb +38 -0
  39. data/spec/lib/rsolr/client_spec.rb +19 -0
  40. data/spec/spec_helper.rb +94 -0
  41. metadata +228 -54
  42. data/lib/rsolr/connection/net_http.rb +0 -48
  43. data/lib/rsolr/connection/requestable.rb +0 -43
  44. data/lib/rsolr/connection/utils.rb +0 -73
  45. data/lib/rsolr/connection.rb +0 -9
  46. data/lib/rsolr/message/document.rb +0 -48
  47. data/lib/rsolr/message/field.rb +0 -20
  48. data/lib/rsolr/message/generator.rb +0 -89
  49. 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
- VERSION = '0.12.0'
8
-
9
- autoload :Message, 'rsolr/message'
2
+ require 'rsolr/version'
3
+
4
+ autoload :Char, 'rsolr/char'
10
5
  autoload :Client, 'rsolr/client'
11
- autoload :Connection, 'rsolr/connection'
12
-
13
- def self.connect opts={}
14
- Client.new Connection::NetHttp.new(opts)
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
- # A module that contains string related methods
18
- module Char
19
-
20
- # escape - from the solr-ruby library
21
- # RSolr.escape('asdf')
22
- # backslash everything that isn't a word character
23
- def escape(value)
24
- value.gsub(/(\W)/, '\\\\\1')
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.name = "rsolr"
4
- s.version = "0.12.0"
5
- s.date = "2010-02-03"
6
- s.summary = "A Ruby client for Apache Solr"
7
- s.email = "goodieboy@gmail.com"
8
- s.homepage = "http://github.com/mwmitchell/rsolr"
9
- s.description = "RSolr is a Ruby gem for working with Apache Solr!"
10
- s.has_rdoc = true
11
- s.authors = ["Matt Mitchell"]
12
-
13
- s.files = [
14
- "CHANGES.txt",
15
- "lib/rsolr/client.rb",
16
- "lib/rsolr/connection/net_http.rb",
17
- "lib/rsolr/connection/requestable.rb",
18
- "lib/rsolr/connection/utils.rb",
19
- "lib/rsolr/connection.rb",
20
- "lib/rsolr/message/document.rb",
21
- "lib/rsolr/message/field.rb",
22
- "lib/rsolr/message/generator.rb",
23
- "lib/rsolr/message.rb",
24
- "lib/rsolr.rb",
25
- "LICENSE",
26
- "README.rdoc",
27
- "rsolr.gemspec"
28
- ]
29
-
30
- #s.rdoc_options = ["--main", "README.rdoc"]
31
- s.extra_rdoc_files = %w(LICENSE README.rdoc CHANGES.txt)
32
- end
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:&quot;trash&quot;\"/></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