gsolr 0.12.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/.gitignore +3 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +30 -0
- data/LICENSE +13 -0
- data/README.md +160 -0
- data/Rakefile +40 -0
- data/gsolr.gemspec +25 -0
- data/lib/gsolr/client.rb +121 -0
- data/lib/gsolr/connection/net_http.rb +56 -0
- data/lib/gsolr/connection/requestable.rb +48 -0
- data/lib/gsolr/connection/utils.rb +82 -0
- data/lib/gsolr/connection.rb +9 -0
- data/lib/gsolr/message/document.rb +52 -0
- data/lib/gsolr/message/field.rb +23 -0
- data/lib/gsolr/message/generator.rb +94 -0
- data/lib/gsolr/message.rb +8 -0
- data/lib/gsolr/version.rb +3 -0
- data/lib/gsolr.rb +39 -0
- data/spec/api/client_spec.rb +97 -0
- data/spec/api/connection/net_http_spec.rb +148 -0
- data/spec/api/connection/requestable_spec.rb +92 -0
- data/spec/api/connection/utils_spec.rb +84 -0
- data/spec/api/gsolr_spec.rb +29 -0
- data/spec/api/message_spec.rb +120 -0
- data/spec/spec_helper.rb +1 -0
- data/tasks/spec.rake +35 -0
- metadata +123 -0
@@ -0,0 +1,94 @@
|
|
1
|
+
module GSolr
|
2
|
+
module Message
|
3
|
+
class Generator
|
4
|
+
|
5
|
+
def build(&block)
|
6
|
+
require 'builder'
|
7
|
+
b = ::Builder::XmlMarkup.new(:indent=>0, :margin=>0, :encoding => 'UTF-8')
|
8
|
+
b.instruct!
|
9
|
+
block_given? ? yield(b) : b
|
10
|
+
end
|
11
|
+
|
12
|
+
# generates "add" xml for updating solr
|
13
|
+
# "data" can be a hash or an array of hashes.
|
14
|
+
# - each hash should be a simple key=>value pair representing a solr doc.
|
15
|
+
# If a value is an array, multiple fields will be created.
|
16
|
+
#
|
17
|
+
# "add_attrs" can be a hash for setting the add xml element attributes.
|
18
|
+
#
|
19
|
+
# This method can also accept a block.
|
20
|
+
# The value yielded to the block is a Message::Document; for each solr doc in "data".
|
21
|
+
# You can set xml element attributes for each "doc" element or individual "field" elements.
|
22
|
+
#
|
23
|
+
# For example:
|
24
|
+
#
|
25
|
+
# solr.add({:id=>1, :nickname=>'Tim'}, {:boost=>5.0, :commitWithin=>1.0}) do |doc_msg|
|
26
|
+
# doc_msg.attrs[:boost] = 10.00 # boost the document
|
27
|
+
# nickname = doc_msg.field_by_name(:nickname)
|
28
|
+
# nickname.attrs[:boost] = 20 if nickname.value=='Tim' # boost a field
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# would result in an add element having the attributes boost="10.0"
|
32
|
+
# and a commitWithin="1.0".
|
33
|
+
# Each doc element would have a boost="10.0".
|
34
|
+
# The "nickname" field would have a boost="20.0"
|
35
|
+
# if the doc had a "nickname" field with the value of "Tim".
|
36
|
+
#
|
37
|
+
def add(data, add_attrs={}, &block)
|
38
|
+
data = [data] unless data.is_a?(Array)
|
39
|
+
|
40
|
+
build do |xml|
|
41
|
+
xml.add(add_attrs) do |add_node|
|
42
|
+
data.each do |doc|
|
43
|
+
doc = GSolr::Message::Document.new(doc) if doc.respond_to?(:each_pair)
|
44
|
+
yield doc if block_given?
|
45
|
+
add_node.doc(doc.attrs) do |doc_node|
|
46
|
+
doc.fields.each do |field_obj|
|
47
|
+
doc_node.field field_obj.value, field_obj.attrs
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# generates a <commit/> message
|
56
|
+
def commit(opts={})
|
57
|
+
build {|xml| xml.commit opts}
|
58
|
+
end
|
59
|
+
|
60
|
+
# generates a <optimize/> message
|
61
|
+
def optimize(opts={})
|
62
|
+
build {|xml| xml.optimize opts}
|
63
|
+
end
|
64
|
+
|
65
|
+
# generates a <rollback/> message
|
66
|
+
def rollback opts={}
|
67
|
+
build {|xml| xml.rollback opts}
|
68
|
+
end
|
69
|
+
|
70
|
+
# generates a <delete><id>ID</id></delete> message
|
71
|
+
# "ids" can be a single value or array of values
|
72
|
+
def delete_by_id(ids)
|
73
|
+
ids = [ids] unless ids.is_a?(Array)
|
74
|
+
build do |xml|
|
75
|
+
xml.delete do |delete_node|
|
76
|
+
ids.each { |id| delete_node.id(id) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# generates a <delete><query>ID</query></delete> message
|
82
|
+
# "queries" can be a single value or an array of values
|
83
|
+
def delete_by_query(queries)
|
84
|
+
queries = [queries] unless queries.is_a?(Array)
|
85
|
+
build do |xml|
|
86
|
+
xml.delete do |delete_node|
|
87
|
+
queries.each { |query| delete_node.query query }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end # class Generator
|
93
|
+
end # module Message
|
94
|
+
end # module GSolr
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# The Solr::Message::Generator class is the XML generation module for sending updates to Solr.
|
2
|
+
module GSolr
|
3
|
+
module Message
|
4
|
+
autoload :Document, 'gsolr/message/document'
|
5
|
+
autoload :Field, 'gsolr/message/field'
|
6
|
+
autoload :Generator, 'gsolr/message/generator'
|
7
|
+
end
|
8
|
+
end
|
data/lib/gsolr.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module GSolr
|
7
|
+
autoload :Message, 'gsolr/message'
|
8
|
+
autoload :Client, 'gsolr/client'
|
9
|
+
autoload :Connection, 'gsolr/connection'
|
10
|
+
|
11
|
+
module Connectable
|
12
|
+
def connect(opts={})
|
13
|
+
Client.new Connection::NetHttp.new(opts)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
extend Connectable
|
17
|
+
|
18
|
+
# A module that contains string related methods
|
19
|
+
module Char
|
20
|
+
# escape - from the solr-ruby library
|
21
|
+
# GSolr.escape('asdf')
|
22
|
+
# backslash everything that isn't a word character
|
23
|
+
def escape(value)
|
24
|
+
value.gsub(/(\W)/, '\\\\\1')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# send the escape method into the Connection class ->
|
29
|
+
# solr = GSolr.connect
|
30
|
+
# solr.escape('asdf')
|
31
|
+
GSolr::Client.send(:include, Char)
|
32
|
+
|
33
|
+
# bring escape into this module (GSolr) -> GSolr.escape('asdf')
|
34
|
+
extend Char
|
35
|
+
|
36
|
+
# RequestError is a common/generic exception class used by the adapters
|
37
|
+
class RequestError < RuntimeError
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe GSolr::Client do
|
4
|
+
|
5
|
+
let(:client) {
|
6
|
+
GSolr::Client.new('')
|
7
|
+
}
|
8
|
+
|
9
|
+
context :method_missing do
|
10
|
+
|
11
|
+
it 'a non-existent method should be forwarded to #method_missing and then to #request' do
|
12
|
+
client.should_receive(:request).
|
13
|
+
with('/music', :q=>'Coltrane')
|
14
|
+
client.music :q=>'Coltrane'
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
context :update do
|
20
|
+
|
21
|
+
it 'should forward /update to #request("/update")' do
|
22
|
+
client.should_receive(:request)#.
|
23
|
+
# with('/update', {:wt=>:json}, "my xml message")
|
24
|
+
client.update "my xml message"
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should forward #add calls to #update' do
|
28
|
+
client.should_receive(:update) {|value,params|
|
29
|
+
value.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?><add><doc><field name=\"id\">1</field></doc></add>"
|
30
|
+
}
|
31
|
+
client.add(:id=>1)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should forward #commit calls to #update' do
|
35
|
+
client.should_receive(:update).
|
36
|
+
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><commit/>")
|
37
|
+
client.commit
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should forward #optimize calls to #update' do
|
41
|
+
client.should_receive(:update).
|
42
|
+
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><optimize/>")
|
43
|
+
client.optimize
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should forward #rollback calls to #update' do
|
47
|
+
client.should_receive(:update).
|
48
|
+
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><rollback/>")
|
49
|
+
client.rollback
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should forward #delete_by_id calls to #update' do
|
53
|
+
client.should_receive(:update).
|
54
|
+
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><id>1</id></delete>")
|
55
|
+
client.delete_by_id 1
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should forward #delete_by_query calls to #update' do
|
59
|
+
client.should_receive(:update).
|
60
|
+
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><query>blah</query></delete>")
|
61
|
+
client.delete_by_query 'blah'
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
context :request do
|
67
|
+
|
68
|
+
it 'should forward #request calls to the connection' do
|
69
|
+
client.connection.should_receive(:request).
|
70
|
+
with('/music', :q=>'Coltrane', :wt=>:json).
|
71
|
+
# empty params so that Client doesn't try to evalulate to Ruby;
|
72
|
+
# -- this happens if the :wt equal :ruby
|
73
|
+
and_return(:params=>{})
|
74
|
+
client.request '/music', :q=>'Coltrane'
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
context :adapt_response do
|
80
|
+
|
81
|
+
it 'should not try to evaluate ruby when the :qt is not :ruby' do
|
82
|
+
body = '{:time=>"NOW"}'
|
83
|
+
result = client.send(:adapt_response, {:body=>body, :params=>{}})
|
84
|
+
result.should be_a(String)
|
85
|
+
result.should == body
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should evaluate ruby responses when the :wt is :ruby' do
|
89
|
+
body = '{:time=>"NOW"}'
|
90
|
+
result = client.send(:adapt_response, {:body=>body, :params=>{:wt=>:ruby}})
|
91
|
+
result.should be_a(Hash)
|
92
|
+
result.should == {:time=>"NOW"}
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
describe GSolr::Connection::NetHttp do
|
2
|
+
|
3
|
+
# calls #let to set "net_http" as method accessor
|
4
|
+
module NetHttpHelper
|
5
|
+
def self.included base
|
6
|
+
base.let(:net_http){ GSolr::Connection::NetHttp.new }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context '#request' do
|
11
|
+
|
12
|
+
include NetHttpHelper
|
13
|
+
|
14
|
+
it 'should forward simple, non-data calls to #get' do
|
15
|
+
net_http.should_receive(:get).
|
16
|
+
with('/select', :q=>'a').
|
17
|
+
and_return({:status_code=>200})
|
18
|
+
net_http.request('/select', :q=>'a')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should forward :method=>:post calls to #post with a special header' do
|
22
|
+
net_http.should_receive(:post).
|
23
|
+
with('/select', 'q=a', {}, {"Content-Type"=>"application/x-www-form-urlencoded"}).
|
24
|
+
and_return({:status_code=>200})
|
25
|
+
net_http.request('/select', {:q=>'a'}, :method=>:post)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should forward data calls to #post' do
|
29
|
+
net_http.should_receive(:post).
|
30
|
+
with("/update", "<optimize/>", {}, {"Content-Type"=>"text/xml; charset=utf-8"}).
|
31
|
+
and_return({:status_code=>200})
|
32
|
+
net_http.request('/update', {}, '<optimize/>')
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'connection' do
|
38
|
+
|
39
|
+
include NetHttpHelper
|
40
|
+
|
41
|
+
it 'will create an instance of Net::HTTP' do
|
42
|
+
net_http.send(:connection).should be_a(Net::HTTP)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'get/post' do
|
48
|
+
|
49
|
+
include NetHttpHelper
|
50
|
+
|
51
|
+
it 'should make a GET request as expected' do
|
52
|
+
net_http_response = mock('net_http_response')
|
53
|
+
net_http_response.should_receive(:code).
|
54
|
+
and_return(200)
|
55
|
+
net_http_response.should_receive(:body).
|
56
|
+
and_return('The Response')
|
57
|
+
net_http_response.should_receive(:message).
|
58
|
+
and_return('OK')
|
59
|
+
c = net_http.send(:connection)
|
60
|
+
c.should_receive(:get).
|
61
|
+
with('/solr/select?q=1').
|
62
|
+
and_return(net_http_response)
|
63
|
+
|
64
|
+
context = net_http.send(:get, '/select', :q=>1)
|
65
|
+
context.should be_a(Hash)
|
66
|
+
|
67
|
+
keys = [:data, :body, :status_code, :path, :url, :headers, :params, :message]
|
68
|
+
context.keys.size.should == keys.size
|
69
|
+
context.keys.all?{|key| keys.include?(key) }.should == true
|
70
|
+
|
71
|
+
context[:data].should == nil
|
72
|
+
context[:body].should == 'The Response'
|
73
|
+
context[:status_code].should == 200
|
74
|
+
context[:path].should == '/select'
|
75
|
+
context[:url].should == 'http://127.0.0.1:8983/solr/select?q=1'
|
76
|
+
context[:headers].should == {}
|
77
|
+
context[:params].should == {:q=>1}
|
78
|
+
context[:message].should == 'OK'
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should make a POST request as expected' do
|
82
|
+
net_http_response = mock('net_http_response')
|
83
|
+
net_http_response.should_receive(:code).
|
84
|
+
and_return(200)
|
85
|
+
net_http_response.should_receive(:body).
|
86
|
+
and_return('The Response')
|
87
|
+
net_http_response.should_receive(:message).
|
88
|
+
and_return('OK')
|
89
|
+
c = net_http.send(:connection)
|
90
|
+
c.should_receive(:post).
|
91
|
+
with('/solr/update', '<rollback/>', {}).
|
92
|
+
and_return(net_http_response)
|
93
|
+
context = net_http.send(:post, '/update', '<rollback/>')
|
94
|
+
context.should be_a(Hash)
|
95
|
+
|
96
|
+
keys = [:data, :body, :status_code, :path, :url, :headers, :params, :message]
|
97
|
+
context.keys.size.should == keys.size
|
98
|
+
context.keys.all?{|key| keys.include?(key) }.should == true
|
99
|
+
|
100
|
+
context[:data].should == '<rollback/>'
|
101
|
+
context[:body].should == 'The Response'
|
102
|
+
context[:status_code].should == 200
|
103
|
+
context[:path].should == '/update'
|
104
|
+
context[:url].should == 'http://127.0.0.1:8983/solr/update'
|
105
|
+
context[:headers].should == {}
|
106
|
+
context[:params].should == {}
|
107
|
+
context[:message].should == 'OK'
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'build_url' do
|
113
|
+
|
114
|
+
include NetHttpHelper
|
115
|
+
|
116
|
+
it 'should incude the base path to solr' do
|
117
|
+
result = net_http.send(:build_url, '/select', :q=>'*:*', :check=>'{!}')
|
118
|
+
# this is a non-ordered hash work around,
|
119
|
+
# -- the order of the parameters in the resulting url will be different depending on the ruby distribution/platform
|
120
|
+
# yuk.
|
121
|
+
begin
|
122
|
+
result.should == '/solr/select?check=%7B%21%7D&q=%2A%3A%2A'
|
123
|
+
rescue
|
124
|
+
result.should == '/solr/select?q=%2A%3A%2A&check=%7B%21%7D'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'encode_utf8' do
|
131
|
+
|
132
|
+
include NetHttpHelper
|
133
|
+
|
134
|
+
it 'should encode response body as utf-8' do
|
135
|
+
string = 'testing'
|
136
|
+
if RUBY_VERSION =~ /1\.9/
|
137
|
+
string.encoding.should == Encoding::US_ASCII
|
138
|
+
encoded_string = net_http.send(:encode_utf8, string)
|
139
|
+
string.encoding.should == Encoding::UTF_8
|
140
|
+
else
|
141
|
+
encoded_string = net_http.send(:encode_utf8, string)
|
142
|
+
encoded_string.should == string
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
describe GSolr::Connection::Requestable do
|
2
|
+
|
3
|
+
# calls #let to set "net_http" as method accessor
|
4
|
+
class R
|
5
|
+
include GSolr::Connection::Requestable
|
6
|
+
end
|
7
|
+
|
8
|
+
module RequestableHelper
|
9
|
+
def self.included base
|
10
|
+
base.let(:requestable){R.new}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'new' do
|
15
|
+
|
16
|
+
include RequestableHelper
|
17
|
+
|
18
|
+
it 'should define an intialize method that accepts a hash argument' do
|
19
|
+
lambda{R.new({})}.should_not raise_error
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should have an #opts attribute after creation' do
|
23
|
+
requestable.should respond_to(:opts)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should have an #uri attribute after creation' do
|
27
|
+
requestable.should respond_to(:uri)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'opts and uri' do
|
33
|
+
|
34
|
+
it 'should allow setting the opts' do
|
35
|
+
opts = {:url=>'blah'}
|
36
|
+
r = R.new(opts)
|
37
|
+
r.opts.should == opts
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should parser the url option into a URI object' do
|
41
|
+
opts = {:url => 'http://xyz:1010/solr'}
|
42
|
+
r = R.new(opts)
|
43
|
+
r.uri.should be_a(URI)
|
44
|
+
r.uri.host.should == 'xyz'
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
context :request do
|
50
|
+
|
51
|
+
include RequestableHelper
|
52
|
+
|
53
|
+
it 'should send a get to itself' do
|
54
|
+
expected_response = {:status_code => 200}
|
55
|
+
requestable.should_receive(:get).
|
56
|
+
with('/blah', {:id=>1}).
|
57
|
+
and_return(expected_response)
|
58
|
+
requestable.request('/blah', :id=>1).should == expected_response
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should raise an error if the status_code is not 200' do
|
62
|
+
expected_response = {:status_code => 503}
|
63
|
+
requestable.should_receive(:get).
|
64
|
+
with('/blah', {:id=>1}).
|
65
|
+
and_return(expected_response)
|
66
|
+
lambda{
|
67
|
+
requestable.request('/blah', :id=>1)
|
68
|
+
}.should raise_error
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should send a post to itself if data is supplied' do
|
72
|
+
expected_response = {:status_code => 200}
|
73
|
+
my_data = "<commit/>"
|
74
|
+
post_headers = {"Content-Type"=>"text/xml; charset=utf-8"}
|
75
|
+
requestable.should_receive(:post).
|
76
|
+
with('/blah', my_data, {:id=>1}, post_headers).
|
77
|
+
and_return(expected_response)
|
78
|
+
requestable.request('/blah', {:id=>1}, my_data).should == expected_response
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should send a post to itself when :method=>:post is set even if no POST data is supplied' do
|
82
|
+
expected_response = {:status_code => 200}
|
83
|
+
post_headers = {"Content-Type"=>"application/x-www-form-urlencoded"}
|
84
|
+
requestable.should_receive(:post).
|
85
|
+
with('/blah', "", {}, post_headers).
|
86
|
+
and_return(expected_response)
|
87
|
+
requestable.request('/blah', {}, :method => :post).should == expected_response
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
describe GSolr::Connection::Utils do
|
2
|
+
|
3
|
+
# calls #let to set "utils" as a method accessor
|
4
|
+
module UtilsHelper
|
5
|
+
def self.included base
|
6
|
+
base.let(:utils){ nil.extend GSolr::Connection::Utils }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'hash_to_query method' do
|
11
|
+
|
12
|
+
include UtilsHelper
|
13
|
+
|
14
|
+
it "should build a query string from a hash, converting arrays to multi-params and removing nils/emptys" do
|
15
|
+
test_params = {
|
16
|
+
:z=>'should be whatever',
|
17
|
+
:q=>'test',
|
18
|
+
:item => [1, 2, 3, nil],
|
19
|
+
:nil=>nil
|
20
|
+
}
|
21
|
+
result = utils.hash_to_query(test_params)
|
22
|
+
[/z=should\+be\+whatever/, /q=test/, /item=1/, /item=2/, /item=3/].each do |regexp|
|
23
|
+
result.should match(regexp)
|
24
|
+
end
|
25
|
+
result.split('&').size.should == 5
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should escape &' do
|
29
|
+
utils.hash_to_query(:fq => "&").should == 'fq=%26'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should convert spaces to +' do
|
33
|
+
utils.hash_to_query(:fq => "me and you").should == 'fq=me+and+you'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should escape comlex queries, part 1' do
|
37
|
+
my_params = {'fq' => '{!raw f=field_name}crazy+\"field+value'}
|
38
|
+
expected = 'fq=%7B%21raw+f%3Dfield_name%7Dcrazy%2B%5C%22field%2Bvalue'
|
39
|
+
utils.hash_to_query(my_params).should == expected
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should escape comlex queries, part 2' do
|
43
|
+
my_params = {'q' => '+popularity:[10 TO *] +section:0'}
|
44
|
+
expected = 'q=%2Bpopularity%3A%5B10+TO+%2A%5D+%2Bsection%3A0'
|
45
|
+
utils.hash_to_query(my_params).should == expected
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'escape method' do
|
51
|
+
|
52
|
+
include UtilsHelper
|
53
|
+
|
54
|
+
it 'should escape properly' do
|
55
|
+
utils.escape('+').should == '%2B'
|
56
|
+
utils.escape('This is a test').should == 'This+is+a+test'
|
57
|
+
utils.escape('<>/\\').should == '%3C%3E%2F%5C'
|
58
|
+
utils.escape('"').should == '%22'
|
59
|
+
utils.escape(':').should == '%3A'
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should escape brackets' do
|
63
|
+
utils.escape('{').should == '%7B'
|
64
|
+
utils.escape('}').should == '%7D'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should escape exclamation marks!' do
|
68
|
+
utils.escape('!').should == '%21'
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'build_url method' do
|
74
|
+
|
75
|
+
include UtilsHelper
|
76
|
+
|
77
|
+
it 'should build correctly' do
|
78
|
+
url = utils.build_url '/solr/select', {:q=>'test'}, 'blah=blah'
|
79
|
+
url.should == '/solr/select?blah=blah&q=test'
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
describe GSolr do
|
2
|
+
|
3
|
+
context :connect do
|
4
|
+
|
5
|
+
it 'does not care about valid/live URLs yet' do
|
6
|
+
lambda{GSolr.connect :url=>'http://blah.blah.blah:666/solr'}.should_not raise_error
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should create an instance of GSolr::Connection::NetHttp as the #connection' do
|
10
|
+
expected_class = GSolr::Connection::NetHttp
|
11
|
+
GSolr.connect.connection.should be_a(expected_class)
|
12
|
+
GSolr.connect(:url=>'blah').connection.should be_a(expected_class)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
context :escape do
|
18
|
+
|
19
|
+
it "should escape properly" do
|
20
|
+
GSolr.escape('Trying & % different "characters" here!').should == "Trying\\ \\&\\ \\%\\ different\\ \\\"characters\\\"\\ here\\!"
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should escape' do
|
24
|
+
expected = "http\\:\\/\\/lucene\\.apache\\.org\\/solr"
|
25
|
+
GSolr.escape("http://lucene.apache.org/solr").should == expected
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|