rsolr 0.13.0.pre → 1.0.0.beta
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/README.rdoc +48 -29
- data/VERSION +1 -1
- data/lib/rsolr/char.rb +9 -0
- data/lib/rsolr/client.rb +80 -58
- data/lib/rsolr/error.rb +122 -0
- data/lib/rsolr/http.rb +106 -0
- data/lib/rsolr/uri.rb +55 -0
- data/lib/rsolr/xml.rb +161 -0
- data/lib/rsolr.rb +18 -39
- data/spec/api/rsolr_client_spec.rb +195 -0
- data/spec/api/rsolr_error_spec.rb +4 -0
- data/spec/api/rsolr_http_spec.rb +4 -0
- data/spec/api/rsolr_spec.rb +11 -23
- data/spec/api/rsolr_uri_spec.rb +70 -0
- data/spec/api/{message_spec.rb → rsolr_xml_spec.rb} +5 -4
- metadata +14 -18
- data/lib/rsolr/connection/httpable.rb +0 -101
- data/lib/rsolr/connection/net_http.rb +0 -30
- data/lib/rsolr/connection/utils.rb +0 -74
- 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/spec/api/client_spec.rb +0 -115
- data/spec/api/connection/httpable_spec.rb +0 -157
- data/spec/api/connection/net_http_spec.rb +0 -137
- data/spec/api/connection/utils_spec.rb +0 -84
- data/spec/integration/http_errors_spec.rb +0 -12
data/lib/rsolr/xml.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
module RSolr::Xml
|
2
|
+
|
3
|
+
class Document
|
4
|
+
|
5
|
+
# "attrs" is a hash for setting the "doc" xml attributes
|
6
|
+
# "fields" is an array of Field objects
|
7
|
+
attr_accessor :attrs, :fields
|
8
|
+
|
9
|
+
# "doc_hash" must be a Hash/Mash object
|
10
|
+
# If a value in the "doc_hash" is an array,
|
11
|
+
# a field object is created for each value...
|
12
|
+
def initialize(doc_hash = {})
|
13
|
+
@fields = []
|
14
|
+
doc_hash.each_pair do |field,values|
|
15
|
+
# create a new field for each value (multi-valued)
|
16
|
+
# put non-array values into an array
|
17
|
+
values = [values] unless values.is_a?(Array)
|
18
|
+
values.each do |v|
|
19
|
+
next if v.to_s.empty?
|
20
|
+
@fields << RSolr::Xml::Field.new({:name=>field}, v.to_s)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
@attrs={}
|
24
|
+
end
|
25
|
+
|
26
|
+
# returns an array of fields that match the "name" arg
|
27
|
+
def fields_by_name(name)
|
28
|
+
@fields.select{|f|f.name==name}
|
29
|
+
end
|
30
|
+
|
31
|
+
# returns the *first* field that matches the "name" arg
|
32
|
+
def field_by_name(name)
|
33
|
+
@fields.detect{|f|f.name==name}
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Add a field value to the document. Options map directly to
|
38
|
+
# XML attributes in the Solr <field> node.
|
39
|
+
# See http://wiki.apache.org/solr/UpdateXmlMessages#head-8315b8028923d028950ff750a57ee22cbf7977c6
|
40
|
+
#
|
41
|
+
# === Example:
|
42
|
+
#
|
43
|
+
# document.add_field('title', 'A Title', :boost => 2.0)
|
44
|
+
#
|
45
|
+
def add_field(name, value, options = {})
|
46
|
+
@fields << RSolr::Xml::Field.new(options.merge({:name=>name}), value)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class Field
|
52
|
+
|
53
|
+
# "attrs" is a hash for setting the "doc" xml attributes
|
54
|
+
# "value" is the text value for the node
|
55
|
+
attr_accessor :attrs, :value
|
56
|
+
|
57
|
+
# "attrs" must be a hash
|
58
|
+
# "value" should be something that responds to #_to_s
|
59
|
+
def initialize(attrs, value)
|
60
|
+
@attrs = attrs
|
61
|
+
@value = value
|
62
|
+
end
|
63
|
+
|
64
|
+
# the value of the "name" attribute
|
65
|
+
def name
|
66
|
+
@attrs[:name]
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
class Generator
|
72
|
+
|
73
|
+
def build &block
|
74
|
+
require 'builder'
|
75
|
+
b = ::Builder::XmlMarkup.new(:indent=>0, :margin=>0, :encoding => 'UTF-8')
|
76
|
+
b.instruct!
|
77
|
+
block_given? ? yield(b) : b
|
78
|
+
end
|
79
|
+
|
80
|
+
# generates "add" xml for updating solr
|
81
|
+
# "data" can be a hash or an array of hashes.
|
82
|
+
# - each hash should be a simple key=>value pair representing a solr doc.
|
83
|
+
# If a value is an array, multiple fields will be created.
|
84
|
+
#
|
85
|
+
# "add_attrs" can be a hash for setting the add xml element attributes.
|
86
|
+
#
|
87
|
+
# This method can also accept a block.
|
88
|
+
# The value yielded to the block is a Message::Document; for each solr doc in "data".
|
89
|
+
# You can set xml element attributes for each "doc" element or individual "field" elements.
|
90
|
+
#
|
91
|
+
# For example:
|
92
|
+
#
|
93
|
+
# solr.add({:id=>1, :nickname=>'Tim'}, {:boost=>5.0, :commitWithin=>1.0}) do |doc_msg|
|
94
|
+
# doc_msg.attrs[:boost] = 10.00 # boost the document
|
95
|
+
# nickname = doc_msg.field_by_name(:nickname)
|
96
|
+
# nickname.attrs[:boost] = 20 if nickname.value=='Tim' # boost a field
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# would result in an add element having the attributes boost="10.0"
|
100
|
+
# and a commitWithin="1.0".
|
101
|
+
# Each doc element would have a boost="10.0".
|
102
|
+
# The "nickname" field would have a boost="20.0"
|
103
|
+
# if the doc had a "nickname" field with the value of "Tim".
|
104
|
+
#
|
105
|
+
def add data, add_attrs={}, &block
|
106
|
+
data = [data] unless data.is_a?(Array)
|
107
|
+
build do |xml|
|
108
|
+
xml.add(add_attrs) do |add_node|
|
109
|
+
data.each do |doc|
|
110
|
+
doc = RSolr::Xml::Document.new(doc) if doc.respond_to?(:each_pair)
|
111
|
+
yield doc if block_given?
|
112
|
+
add_node.doc(doc.attrs) do |doc_node|
|
113
|
+
doc.fields.each do |field_obj|
|
114
|
+
doc_node.field field_obj.value, field_obj.attrs
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# generates a <commit/> message
|
123
|
+
def commit(opts={})
|
124
|
+
build {|xml| xml.commit opts}
|
125
|
+
end
|
126
|
+
|
127
|
+
# generates a <optimize/> message
|
128
|
+
def optimize(opts={})
|
129
|
+
build {|xml| xml.optimize opts}
|
130
|
+
end
|
131
|
+
|
132
|
+
# generates a <rollback/> message
|
133
|
+
def rollback opts={}
|
134
|
+
build {|xml| xml.rollback opts}
|
135
|
+
end
|
136
|
+
|
137
|
+
# generates a <delete><id>ID</id></delete> message
|
138
|
+
# "ids" can be a single value or array of values
|
139
|
+
def delete_by_id(ids)
|
140
|
+
ids = [ids] unless ids.is_a?(Array)
|
141
|
+
build do |xml|
|
142
|
+
xml.delete do |delete_node|
|
143
|
+
ids.each { |id| delete_node.id(id) }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# generates a <delete><query>ID</query></delete> message
|
149
|
+
# "queries" can be a single value or an array of values
|
150
|
+
def delete_by_query(queries)
|
151
|
+
queries = [queries] unless queries.is_a?(Array)
|
152
|
+
build do |xml|
|
153
|
+
xml.delete do |delete_node|
|
154
|
+
queries.each { |query| delete_node.query query }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
data/lib/rsolr.rb
CHANGED
@@ -1,53 +1,32 @@
|
|
1
|
-
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/https'
|
2
4
|
require 'rubygems'
|
3
|
-
|
5
|
+
require 'builder'
|
6
|
+
|
7
|
+
$: << "#{File.dirname(__FILE__)}"
|
4
8
|
|
5
9
|
module RSolr
|
6
10
|
|
11
|
+
%W(Char Client Error Http Uri Xml).each{|n|autoload n.to_sym, "rsolr/#{n.downcase}"}
|
12
|
+
|
7
13
|
def self.version
|
8
|
-
@version ||= File.read(File.join(File.dirname(__FILE__), '..', 'VERSION'))
|
14
|
+
@version ||= File.read(File.join(File.dirname(__FILE__), '..', 'VERSION')).chomp
|
9
15
|
end
|
10
16
|
|
11
17
|
VERSION = self.version
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
module Connectable
|
18
|
-
|
19
|
-
def connect opts={}
|
20
|
-
Client.new Connection::NetHttp.new(opts)
|
21
|
-
end
|
22
|
-
|
19
|
+
def self.connect *args
|
20
|
+
opts = parse_options *args
|
21
|
+
Client.new Http.new(opts[0], opts[1])
|
23
22
|
end
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
# RSolr.escape('asdf')
|
32
|
-
# backslash everything that isn't a word character
|
33
|
-
def escape(value)
|
34
|
-
value.gsub(/(\W)/, '\\\\\1')
|
35
|
-
end
|
36
|
-
|
24
|
+
def self.parse_options *args
|
25
|
+
opts = args[-1].kind_of?(Hash) ? args.pop : {}
|
26
|
+
url = args.empty? ? 'http://127.0.0.1:8983/solr/' : args[0]
|
27
|
+
uri = Uri.create url
|
28
|
+
proxy = Uri.create opts[:proxy] if opts[:proxy]
|
29
|
+
[uri, {:proxy => proxy}]
|
37
30
|
end
|
38
31
|
|
39
|
-
# send the escape method into the Connection class ->
|
40
|
-
# solr = RSolr.connect
|
41
|
-
# solr.escape('asdf')
|
42
|
-
RSolr::Client.send(:include, Char)
|
43
|
-
|
44
|
-
# bring escape into this module (RSolr) -> RSolr.escape('asdf')
|
45
|
-
extend Char
|
46
|
-
|
47
|
-
# RequestError is a common/generic exception class used by the adapters
|
48
|
-
class RequestError < RuntimeError; end
|
49
|
-
|
50
|
-
# TODO: The connection drivers need to start raising this...
|
51
|
-
class ConnectionError < RuntimeError; end
|
52
|
-
|
53
32
|
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "RSolr::Client" do
|
3
|
+
|
4
|
+
module ClientHelper
|
5
|
+
def client
|
6
|
+
@client ||= (
|
7
|
+
connection = RSolr::Http.new URI.parse("http://localhost:9999/solr")
|
8
|
+
RSolr::Client.new(connection)
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "initialize" do
|
14
|
+
it "should accept whatevs and set it as the @connection" do
|
15
|
+
RSolr::Client.new(:whatevs).connection.should == :whatevs
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "adapt_response" do
|
20
|
+
|
21
|
+
include ClientHelper
|
22
|
+
|
23
|
+
it 'should not try to evaluate ruby when the :qt is not :ruby' do
|
24
|
+
body = '{:time=>"NOW"}'
|
25
|
+
result = client.send(:adapt_response, {:params=>{}}, {:body => body})
|
26
|
+
result.should be_a(String)
|
27
|
+
result.should == body
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should evaluate ruby responses when the :wt is :ruby' do
|
31
|
+
body = '{:time=>"NOW"}'
|
32
|
+
result = client.send(:adapt_response, {:params=>{:wt=>:ruby}}, {:body=>body})
|
33
|
+
result.should be_a(Hash)
|
34
|
+
result.should == {:time=>"NOW"}
|
35
|
+
end
|
36
|
+
|
37
|
+
["nil", :ruby].each do |wt|
|
38
|
+
it "should return an object that responds to :request and :response when :wt == #{wt}" do
|
39
|
+
req = {:params=>{:wt=>wt}}
|
40
|
+
res = {:body=>""}
|
41
|
+
result = client.send(:adapt_response, req, res)
|
42
|
+
result.request.should == req
|
43
|
+
result.response.should == res
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "ought raise a RSolr::Error::InvalidRubyResponse when the ruby is indeed frugged" do
|
48
|
+
lambda {
|
49
|
+
client.send(:adapt_response, {:params=>{:wt => :ruby}}, {:body => "<woops/>"})
|
50
|
+
}.should raise_error RSolr::Error::InvalidRubyResponse
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
context "build_request" do
|
56
|
+
include ClientHelper
|
57
|
+
it 'should return a request context array' do
|
58
|
+
result = client.build_request 'select', {:q=>'test', :fq=>[0,1]}, "data", headers = {}
|
59
|
+
["select?fq=0&fq=1&q=test", "select?q=test&fq=0&fq=1"].should include(result[0].to_s)
|
60
|
+
result[1].should == "data"
|
61
|
+
result[2].should == headers
|
62
|
+
end
|
63
|
+
it "should set the Content-Type header to application/x-www-form-urlencoded if a hash is passed in to the data arg" do
|
64
|
+
result = client.build_request 'select', nil, {:q=>'test', :fq=>[0,1]}, headers = {}
|
65
|
+
result[0].to_s.should == "select"
|
66
|
+
["fq=0&fq=1&q=test", "q=test&fq=0&fq=1"].should include(result[1])
|
67
|
+
result[2].should == headers
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "map_params" do
|
72
|
+
include ClientHelper
|
73
|
+
it "should return a hash if nil is passed in" do
|
74
|
+
client.map_params(nil).should == {:wt => :ruby}
|
75
|
+
end
|
76
|
+
it "should set the :wt to ruby if blank" do
|
77
|
+
r = client.map_params({:q=>"q"})
|
78
|
+
r[:q].should == "q"
|
79
|
+
r[:wt].should == :ruby
|
80
|
+
end
|
81
|
+
it "should not override the :wt to ruby if set" do
|
82
|
+
r = client.map_params({:q=>"q", :wt => :json})
|
83
|
+
r[:q].should == "q"
|
84
|
+
r[:wt].should == :json
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "send_request" do
|
89
|
+
include ClientHelper
|
90
|
+
it "should forward these method calls the #connection object" do
|
91
|
+
[:get, :post, :head].each do |meth|
|
92
|
+
client.connection.should_receive(meth).
|
93
|
+
and_return({:status => 200})
|
94
|
+
client.send_request meth, '', {}, nil, {}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
it "should extend any exception raised by the #connection object with a RSolr::Error::SolrContext" do
|
98
|
+
client.connection.should_receive(:get).
|
99
|
+
and_raise(RuntimeError)
|
100
|
+
lambda {
|
101
|
+
client.send_request :get, '', {}, nil, {}
|
102
|
+
}.should raise_error(RuntimeError){|error|
|
103
|
+
error.should be_a(RSolr::Error::SolrContext)
|
104
|
+
error.should respond_to(:request)
|
105
|
+
error.request.keys.should include(:connection, :method, :uri, :data, :headers, :params)
|
106
|
+
}
|
107
|
+
end
|
108
|
+
it "should raise an Http error if the response status code aint right" do
|
109
|
+
client.connection.should_receive(:get).
|
110
|
+
and_return({:status_code => 404})
|
111
|
+
lambda{
|
112
|
+
client.send_request :get, '', {}, nil, {}
|
113
|
+
}.should raise_error(RSolr::Error::Http) {|error|
|
114
|
+
error.should be_a(RSolr::Error::Http)
|
115
|
+
error.should respond_to(:request)
|
116
|
+
error.should respond_to(:response)
|
117
|
+
}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "post" do
|
122
|
+
include ClientHelper
|
123
|
+
it "should pass the expected params to the connection's #post method" do
|
124
|
+
client.connection.should_receive(:post).
|
125
|
+
with("update?wt=ruby", "the data", {"Content-Type" => "text/plain"}).
|
126
|
+
and_return(:status => 200)
|
127
|
+
client.post "update", "the data", nil, {"Content-Type" => "text/plain"}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "xml" do
|
132
|
+
include ClientHelper
|
133
|
+
it "should return an instance of RSolr::Xml::Generator" do
|
134
|
+
client.xml.should be_a RSolr::Xml::Generator
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "add" do
|
139
|
+
include ClientHelper
|
140
|
+
it "should send xml to the connection's #post method" do
|
141
|
+
client.connection.should_receive(:post).
|
142
|
+
with("update?wt=ruby", "<xml/>", {"Content-Type"=>"text/xml"}).
|
143
|
+
and_return(:status => 200)
|
144
|
+
# the :xml attr is lazy loaded... so load it up first
|
145
|
+
client.xml
|
146
|
+
client.xml.should_receive(:add).
|
147
|
+
with({:id=>1}, :commitWith=>1.0).
|
148
|
+
and_return("<xml/>")
|
149
|
+
client.add({:id=>1}, {:commitWith=>1.0})
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "update" do
|
154
|
+
include ClientHelper
|
155
|
+
it "should send data to the connection's #post method" do
|
156
|
+
client.connection.should_receive(:post).
|
157
|
+
with("update?wt=xml", instance_of(String), {"Content-Type"=>"text/xml"}).
|
158
|
+
and_return(:status => 200)
|
159
|
+
client.update("<optimize/>", {:wt=>:xml})
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "post based helper methods:" do
|
164
|
+
include ClientHelper
|
165
|
+
[:commit, :optimize, :rollback].each do |meth|
|
166
|
+
it "should send a #{meth} message to the connection's #post method" do
|
167
|
+
client.connection.should_receive(:post).
|
168
|
+
with("update?wt=ruby", "<?xml version=\"1.0\" encoding=\"UTF-8\"?><#{meth}/>", {"Content-Type"=>"text/xml"}).
|
169
|
+
and_return(:status => 200)
|
170
|
+
client.send meth
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context "delete_by_id" do
|
176
|
+
include ClientHelper
|
177
|
+
it "should send data to the connection's #post method" do
|
178
|
+
client.connection.should_receive(:post).
|
179
|
+
with("update?wt=ruby", instance_of(String), {"Content-Type"=>"text/xml"}).
|
180
|
+
and_return(:status => 200)
|
181
|
+
client.delete_by_id 1
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context "delete_by_query" do
|
186
|
+
include ClientHelper
|
187
|
+
it "should send data to the connection's #post method" do
|
188
|
+
client.connection.should_receive(:post).
|
189
|
+
with("update?wt=ruby", instance_of(String), {"Content-Type"=>"text/xml"}).
|
190
|
+
and_return(:status => 200)
|
191
|
+
client.delete_by_query :fq => "category:\"trash\""
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
data/spec/api/rsolr_spec.rb
CHANGED
@@ -1,29 +1,17 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "RSolr class methods" do
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
it 'should create an instance of RSolr::Connection::NetHttp as the #connection' do
|
10
|
-
expected_class = RSolr::Connection::NetHttp
|
11
|
-
RSolr.connect.connection.should be_a(expected_class)
|
12
|
-
RSolr.connect(:url=>'blah').connection.should be_a(expected_class)
|
13
|
-
end
|
14
|
-
|
4
|
+
it "should parse these here options" do
|
5
|
+
result = RSolr.parse_options "http://localhost:8983/solr/blah", :proxy => "http://qtpaglzvm.com"
|
6
|
+
result[0].should be_a(URI)
|
7
|
+
result[1].should be_a(Hash)
|
8
|
+
result[1][:proxy].should be_a(URI)
|
15
9
|
end
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'should escape' do
|
24
|
-
expected = "http\\:\\/\\/lucene\\.apache\\.org\\/solr"
|
25
|
-
RSolr.escape("http://lucene.apache.org/solr").should == expected
|
26
|
-
end
|
11
|
+
it "should not create a URI instance for :proxy => nil" do
|
12
|
+
result = RSolr.parse_options "http://localhost:8983/solr/blah"
|
13
|
+
result[0].should be_a(URI)
|
14
|
+
result[1].should == {:proxy => nil}
|
27
15
|
end
|
28
16
|
|
29
17
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "RSolr::Uri" do
|
3
|
+
|
4
|
+
context "class-level methods" do
|
5
|
+
|
6
|
+
let(:uri){ RSolr::Uri }
|
7
|
+
|
8
|
+
it "should return a URI object with a trailing slash" do
|
9
|
+
u = uri.create 'http://apache.org'
|
10
|
+
u.path[0].should == ?/
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return the bytesize of a string" do
|
14
|
+
uri.bytesize("test").should == 4
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should convert a solr query string from a hash w/o a starting ?" do
|
18
|
+
hash = {:q => "gold", :fq => ["mode:one", "level:2"]}
|
19
|
+
query = uri.params_to_solr hash
|
20
|
+
query[0].should_not == ??
|
21
|
+
[/q=gold/, /fq=mode%3Aone/, /fq=level%3A2/].each do |p|
|
22
|
+
query.should match p
|
23
|
+
end
|
24
|
+
query.split('&').size.should == 3
|
25
|
+
end
|
26
|
+
|
27
|
+
context "escape_query_value" do
|
28
|
+
|
29
|
+
it 'should escape &' do
|
30
|
+
uri.params_to_solr(:fq => "&").should == 'fq=%26'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should convert spaces to +' do
|
34
|
+
uri.params_to_solr(:fq => "me and you").should == 'fq=me+and+you'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should escape comlex queries, part 1' do
|
38
|
+
my_params = {'fq' => '{!raw f=field_name}crazy+\"field+value'}
|
39
|
+
expected = 'fq=%7B%21raw+f%3Dfield_name%7Dcrazy%2B%5C%22field%2Bvalue'
|
40
|
+
uri.params_to_solr(my_params).should == expected
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should escape complex queries, part 2' do
|
44
|
+
my_params = {'q' => '+popularity:[10 TO *] +section:0'}
|
45
|
+
expected = 'q=%2Bpopularity%3A%5B10+TO+%2A%5D+%2Bsection%3A0'
|
46
|
+
uri.params_to_solr(my_params).should == expected
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should escape properly' do
|
50
|
+
uri.escape_query_value('+').should == '%2B'
|
51
|
+
uri.escape_query_value('This is a test').should == 'This+is+a+test'
|
52
|
+
uri.escape_query_value('<>/\\').should == '%3C%3E%2F%5C'
|
53
|
+
uri.escape_query_value('"').should == '%22'
|
54
|
+
uri.escape_query_value(':').should == '%3A'
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should escape brackets' do
|
58
|
+
uri.escape_query_value('{').should == '%7B'
|
59
|
+
uri.escape_query_value('}').should == '%7D'
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should escape exclamation marks!' do
|
63
|
+
uri.escape_query_value('!').should == '%21'
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "RSolr::Xml" do
|
2
3
|
|
3
|
-
let(:generator){ RSolr::
|
4
|
+
let(:generator){ RSolr::Xml::Generator.new }
|
4
5
|
|
5
6
|
# call all of the simple methods...
|
6
7
|
# make sure the xml string is valid
|
@@ -70,7 +71,7 @@ describe RSolr::Message do
|
|
70
71
|
end
|
71
72
|
|
72
73
|
it 'should create an add from a single Message::Document' do
|
73
|
-
document = RSolr::
|
74
|
+
document = RSolr::Xml::Document.new
|
74
75
|
document.add_field('id', 1)
|
75
76
|
document.add_field('name', 'matt', :boost => 2.0)
|
76
77
|
result = generator.add(document)
|
@@ -83,7 +84,7 @@ describe RSolr::Message do
|
|
83
84
|
|
84
85
|
it 'should create adds from multiple Message::Documents' do
|
85
86
|
documents = (1..2).map do |i|
|
86
|
-
doc = RSolr::
|
87
|
+
doc = RSolr::Xml::Document.new
|
87
88
|
doc.add_field('id', i)
|
88
89
|
doc.add_field('name', "matt#{i}")
|
89
90
|
doc
|
metadata
CHANGED
@@ -3,11 +3,11 @@ name: rsolr
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: true
|
5
5
|
segments:
|
6
|
+
- 1
|
6
7
|
- 0
|
7
|
-
- 13
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.
|
9
|
+
- beta
|
10
|
+
version: 1.0.0.beta
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matt Mitchell
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-06-29 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -46,15 +46,12 @@ files:
|
|
46
46
|
- README.rdoc
|
47
47
|
- VERSION
|
48
48
|
- lib/rsolr.rb
|
49
|
+
- lib/rsolr/char.rb
|
49
50
|
- lib/rsolr/client.rb
|
50
|
-
- lib/rsolr/
|
51
|
-
- lib/rsolr/
|
52
|
-
- lib/rsolr/
|
53
|
-
- lib/rsolr/
|
54
|
-
- lib/rsolr/message.rb
|
55
|
-
- lib/rsolr/message/document.rb
|
56
|
-
- lib/rsolr/message/field.rb
|
57
|
-
- lib/rsolr/message/generator.rb
|
51
|
+
- lib/rsolr/error.rb
|
52
|
+
- lib/rsolr/http.rb
|
53
|
+
- lib/rsolr/uri.rb
|
54
|
+
- lib/rsolr/xml.rb
|
58
55
|
has_rdoc: true
|
59
56
|
homepage: http://github.com/mwmitchell/rsolr
|
60
57
|
licenses: []
|
@@ -88,13 +85,12 @@ signing_key:
|
|
88
85
|
specification_version: 3
|
89
86
|
summary: A Ruby client for Apache Solr
|
90
87
|
test_files:
|
91
|
-
- spec/api/
|
92
|
-
- spec/api/
|
93
|
-
- spec/api/
|
94
|
-
- spec/api/connection/utils_spec.rb
|
95
|
-
- spec/api/message_spec.rb
|
88
|
+
- spec/api/rsolr_client_spec.rb
|
89
|
+
- spec/api/rsolr_error_spec.rb
|
90
|
+
- spec/api/rsolr_http_spec.rb
|
96
91
|
- spec/api/rsolr_spec.rb
|
97
|
-
- spec/
|
92
|
+
- spec/api/rsolr_uri_spec.rb
|
93
|
+
- spec/api/rsolr_xml_spec.rb
|
98
94
|
- spec/spec_helper.rb
|
99
95
|
- Rakefile
|
100
96
|
- tasks/spec.rake
|