mwmitchell-rsolr 0.8.4 → 0.8.5
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/CHANGES.txt +8 -0
- data/LICENSE +0 -0
- data/Rakefile +0 -0
- data/examples/direct.rb +0 -0
- data/examples/http.rb +6 -5
- data/lib/core_ext.rb +0 -0
- data/lib/mash.rb +0 -0
- data/lib/rsolr/adapter/direct.rb +0 -2
- data/lib/rsolr/adapter/http.rb +1 -5
- data/lib/rsolr/adapter.rb +0 -0
- data/lib/rsolr/http_client/adapter.rb +0 -0
- data/lib/rsolr/http_client.rb +27 -4
- data/lib/rsolr/message.rb +19 -6
- data/lib/rsolr.rb +3 -1
- data/test/connection/direct_test.rb +0 -0
- data/test/connection/http_test.rb +0 -0
- data/test/connection/test_methods.rb +0 -0
- data/test/http_client/curb_test.rb +0 -0
- data/test/http_client/net_http_test.rb +0 -0
- data/test/http_client/test_methods.rb +0 -0
- data/test/http_client/util_test.rb +0 -0
- data/test/message_test.rb +29 -1
- metadata +2 -5
- data/spec/connection_spec.rb +0 -151
- data/spec/helper.rb +0 -4
- data/spec/rsolr_spec.rb +0 -29
data/CHANGES.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
0.8.5 - April 7, 2009
|
2
|
+
The RSolr::Message #add method now accepts a single Message::Document or an array of Message::Document objects
|
3
|
+
The Message::Document class has a new method: #add_field
|
4
|
+
Tests added for both changes
|
5
|
+
Permissions of files changed to non-executable
|
6
|
+
-- the above changes were made by Mat Brown, thank you Mat!
|
7
|
+
Added CannedSolrResponse module for mocks in the specs... not used yet
|
8
|
+
|
1
9
|
0.8.4 - April 3, 2009
|
2
10
|
New test suite using RSpec and mocks coming. Run "rake spec"
|
3
11
|
- added specs for RSolr and RSolr::Connection
|
data/LICENSE
CHANGED
File without changes
|
data/Rakefile
CHANGED
File without changes
|
data/examples/direct.rb
CHANGED
File without changes
|
data/examples/http.rb
CHANGED
@@ -12,11 +12,12 @@ end
|
|
12
12
|
|
13
13
|
puts
|
14
14
|
|
15
|
-
solr.select(:q=>'ipod', :fq=>'price:[0 TO 50]', :rows=>2, :start=>0)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
response = solr.select(:q=>'ipod', :fq=>'price:[0 TO 50]', :rows=>2, :start=>0)
|
16
|
+
|
17
|
+
puts "URL : #{response.adapter_response[:url]} -> #{response.adapter_response[:status_code]}"
|
18
|
+
|
19
|
+
solr_response[:response][:docs].each do |doc|
|
20
|
+
puts doc[:timestamp]
|
20
21
|
end
|
21
22
|
|
22
23
|
solr.delete_by_query('*:*') and solr.commit
|
data/lib/core_ext.rb
CHANGED
File without changes
|
data/lib/mash.rb
CHANGED
File without changes
|
data/lib/rsolr/adapter/direct.rb
CHANGED
data/lib/rsolr/adapter/http.rb
CHANGED
@@ -7,10 +7,6 @@ class RSolr::Adapter::HTTP
|
|
7
7
|
|
8
8
|
# opts can have:
|
9
9
|
# :url => 'http://localhost:8080/solr'
|
10
|
-
# :select_path => '/the/url/path/to/the/select/handler'
|
11
|
-
# :update_path => '/the/url/path/to/the/update/handler'
|
12
|
-
# :luke_path => '/admin/luke'
|
13
|
-
#
|
14
10
|
def initialize(opts={}, &block)
|
15
11
|
opts[:url]||='http://127.0.0.1:8983/solr'
|
16
12
|
@opts = opts
|
@@ -36,7 +32,7 @@ class RSolr::Adapter::HTTP
|
|
36
32
|
|
37
33
|
protected
|
38
34
|
|
39
|
-
# The standard
|
35
|
+
# The standard POST headers
|
40
36
|
def post_headers
|
41
37
|
{"Content-Type" => 'text/xml; charset=utf-8'}
|
42
38
|
end
|
data/lib/rsolr/adapter.rb
CHANGED
File without changes
|
File without changes
|
data/lib/rsolr/http_client.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# A simple wrapper for different http client implementations.
|
2
2
|
# Supports #get and #post
|
3
3
|
# This was motivated by: http://apocryph.org/2008/11/09/more_indepth_analysis_ruby_http_client_performance/
|
4
|
-
# Curb is the default adapter
|
5
4
|
|
6
|
-
# Each adapters response should be a hash with the following keys:
|
5
|
+
# Each adapters' response should be a hash with the following keys:
|
7
6
|
# :status_code
|
8
7
|
# :url
|
9
8
|
# :body
|
@@ -36,6 +35,13 @@ module RSolr::HTTPClient
|
|
36
35
|
@adapter_name = adapter_name
|
37
36
|
end
|
38
37
|
|
38
|
+
# Creates and returns an instance of RSolr::HTTPClient::Adapter::*
|
39
|
+
# The "url" is a full/valid url.
|
40
|
+
# Example:
|
41
|
+
# connector = RSolr::HTTPClient::Connector.new
|
42
|
+
# client = connector.connect('http://google.com')
|
43
|
+
#
|
44
|
+
# TODO: this should be less verbose... something like RSolr:HTTPClient.connect(url, adapter=:curb)
|
39
45
|
def connect(url)
|
40
46
|
case adapter_name
|
41
47
|
when :curb
|
@@ -54,14 +60,19 @@ module RSolr::HTTPClient
|
|
54
60
|
|
55
61
|
end
|
56
62
|
|
63
|
+
# The base class for interacting with one of the HTTP client adapters
|
57
64
|
class Base
|
58
65
|
|
59
66
|
attr_reader :adapter
|
60
67
|
|
68
|
+
# requires an instace of RSolr::HTTPClient::*
|
61
69
|
def initialize(adapter)
|
62
70
|
@adapter = adapter
|
63
71
|
end
|
64
72
|
|
73
|
+
# sends a GET reqest to the "path" variable
|
74
|
+
# an optional hash of "params" can be used,
|
75
|
+
# which is later transformed into a GET query string
|
65
76
|
def get(path, params={})
|
66
77
|
begin
|
67
78
|
http_context = @adapter.get(path, params)
|
@@ -71,6 +82,10 @@ module RSolr::HTTPClient
|
|
71
82
|
http_context
|
72
83
|
end
|
73
84
|
|
85
|
+
# sends a POST request to the "path" variable
|
86
|
+
# "data" is required, and must be a string
|
87
|
+
# "params" is an optional hash for query string params...
|
88
|
+
# "headers" is a hash for setting request header values.
|
74
89
|
def post(path, data, params={}, headers={})
|
75
90
|
begin
|
76
91
|
http_context = @adapter.post(path, data, params, headers)
|
@@ -90,14 +105,22 @@ module RSolr::HTTPClient
|
|
90
105
|
'%'+$1.unpack('H2'*$1.size).join('%').upcase
|
91
106
|
}.tr(' ', '+')
|
92
107
|
end
|
93
|
-
|
108
|
+
|
109
|
+
# creates and returns a url as a string
|
110
|
+
# "url" is the base url
|
111
|
+
# "params" is an optional hash of GET style query params
|
112
|
+
# "string_query" is an extra query string that will be appended to the
|
113
|
+
# result of "url" and "params".
|
94
114
|
def build_url(url='', params={}, string_query='')
|
95
115
|
queries = [string_query, hash_to_params(params)]
|
96
116
|
queries.delete_if{|i| i.to_s.empty?}
|
97
117
|
url += "?#{queries.join('&')}" unless queries.empty?
|
98
118
|
url
|
99
119
|
end
|
100
|
-
|
120
|
+
|
121
|
+
# converts a key value pair to an escaped string:
|
122
|
+
# Example:
|
123
|
+
# build_param(:id, 1) == "id=1"
|
101
124
|
def build_param(k,v)
|
102
125
|
"#{escape(k)}=#{escape(v)}"
|
103
126
|
end
|
data/lib/rsolr/message.rb
CHANGED
@@ -16,7 +16,7 @@ class RSolr::Message
|
|
16
16
|
# "doc_hash" must be a Hash/Mash object
|
17
17
|
# If a value in the "doc_hash" is an array,
|
18
18
|
# a field object is created for each value...
|
19
|
-
def initialize(doc_hash)
|
19
|
+
def initialize(doc_hash = {})
|
20
20
|
@fields = []
|
21
21
|
doc_hash.each_pair do |field,values|
|
22
22
|
# create a new field for each value (multi-valued)
|
@@ -35,11 +35,24 @@ class RSolr::Message
|
|
35
35
|
@fields.select{|f|f.name==name}
|
36
36
|
end
|
37
37
|
|
38
|
-
# returns the first field that matches the "name" arg
|
38
|
+
# returns the *first* field that matches the "name" arg
|
39
39
|
def field_by_name(name)
|
40
40
|
@fields.detect{|f|f.name==name}
|
41
41
|
end
|
42
42
|
|
43
|
+
#
|
44
|
+
# Add a field value to the document. Options map directly to
|
45
|
+
# XML attributes in the Solr <field> node.
|
46
|
+
# See http://wiki.apache.org/solr/UpdateXmlMessages#head-8315b8028923d028950ff750a57ee22cbf7977c6
|
47
|
+
#
|
48
|
+
# === Example:
|
49
|
+
#
|
50
|
+
# document.add_field('title', 'A Title', :boost => 2.0)
|
51
|
+
#
|
52
|
+
def add_field(name, value, options = {})
|
53
|
+
@fields << Field.new(options.merge({:name=>name}), value)
|
54
|
+
end
|
55
|
+
|
43
56
|
end
|
44
57
|
|
45
58
|
# A class that represents a "doc"/"field" xml element for a solr update
|
@@ -96,11 +109,11 @@ class RSolr::Message
|
|
96
109
|
# if the doc had a "nickname" field with the value of "Tim".
|
97
110
|
#
|
98
111
|
def add(data, add_attrs={}, &blk)
|
99
|
-
data = [data]
|
112
|
+
data = [data] unless data.is_a?(Array)
|
100
113
|
xml.add(add_attrs) do |add_node|
|
101
|
-
data.each do |
|
114
|
+
data.each do |doc|
|
102
115
|
# create doc, passing in fields
|
103
|
-
doc = Document.new(
|
116
|
+
doc = Document.new(doc) if doc.respond_to?(:each_pair)
|
104
117
|
yield doc if block_given?
|
105
118
|
add_node.doc(doc.attrs) do |doc_node|
|
106
119
|
doc.fields.each do |field_obj|
|
@@ -150,4 +163,4 @@ class RSolr::Message
|
|
150
163
|
|
151
164
|
end
|
152
165
|
|
153
|
-
end
|
166
|
+
end
|
data/lib/rsolr.rb
CHANGED
@@ -9,7 +9,7 @@ require 'mash'
|
|
9
9
|
|
10
10
|
module RSolr
|
11
11
|
|
12
|
-
VERSION = '0.8.
|
12
|
+
VERSION = '0.8.5'
|
13
13
|
|
14
14
|
autoload :Message, 'rsolr/message'
|
15
15
|
autoload :Connection, 'rsolr/connection'
|
@@ -30,6 +30,7 @@ module RSolr
|
|
30
30
|
RSolr::Connection.new(adapter, options)
|
31
31
|
end
|
32
32
|
|
33
|
+
# A module that contains string related methods
|
33
34
|
module Char
|
34
35
|
|
35
36
|
# escape - from the solr-ruby library
|
@@ -49,6 +50,7 @@ module RSolr
|
|
49
50
|
# bring escape into this module (RSolr) -> RSolr.escape('asdf')
|
50
51
|
extend Char
|
51
52
|
|
53
|
+
# RequestError is a common/generic exception class used by the adapters
|
52
54
|
class RequestError < RuntimeError; end
|
53
55
|
|
54
56
|
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/test/message_test.rb
CHANGED
@@ -104,4 +104,32 @@ class MessageTest < RSolrBaseTest
|
|
104
104
|
assert result.to_s =~ /<field name="name">matt2<\/field>/
|
105
105
|
end
|
106
106
|
|
107
|
-
|
107
|
+
def test_add_single_document
|
108
|
+
document = RSolr::Message::Document.new
|
109
|
+
document.add_field('id', 1)
|
110
|
+
document.add_field('name', 'matt', :boost => 2.0)
|
111
|
+
result = RSolr::Message.add(document)
|
112
|
+
|
113
|
+
assert result.to_s =~ /<field name="id">1<\/field>/
|
114
|
+
|
115
|
+
# depending on which ruby version, the attributes can be out of place
|
116
|
+
# so we need to test both... there's gotta be a better way to do this?
|
117
|
+
assert(
|
118
|
+
result.to_s =~ /<field name="name" boost="2.0">matt<\/field>/ ||
|
119
|
+
result.to_s =~ /<field boost="2.0" name="name">matt<\/field>/
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_add_multiple_documents
|
124
|
+
documents = (1..2).map do |i|
|
125
|
+
doc = RSolr::Message::Document.new
|
126
|
+
doc.add_field('id', i)
|
127
|
+
doc.add_field('name', "matt#{i}")
|
128
|
+
doc
|
129
|
+
end
|
130
|
+
result = RSolr::Message.add(documents)
|
131
|
+
|
132
|
+
assert result.to_s =~ /<field name="name">matt1<\/field>/
|
133
|
+
assert result.to_s =~ /<field name="name">matt2<\/field>/
|
134
|
+
end
|
135
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mwmitchell-rsolr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Mitchell
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
12
|
+
date: 2009-04-07 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -91,6 +91,3 @@ test_files:
|
|
91
91
|
- test/message_test.rb
|
92
92
|
- test/rsolr_test
|
93
93
|
- test/test_helpers.rb
|
94
|
-
- spec/connection_spec.rb
|
95
|
-
- spec/helper.rb
|
96
|
-
- spec/rsolr_spec.rb
|
data/spec/connection_spec.rb
DELETED
@@ -1,151 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
describe RSolr::Connection do
|
4
|
-
|
5
|
-
context 'the initialize method' do
|
6
|
-
|
7
|
-
it 'should require one argument' do
|
8
|
-
lambda{RSolr::Connection.new}.should raise_error(ArgumentError)
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
before(:each) do
|
14
|
-
@adapter = mock('RSolr::Adapter::HTTP')
|
15
|
-
@connection = RSolr::Connection.new(@adapter)
|
16
|
-
end
|
17
|
-
|
18
|
-
context '#map_params method' do
|
19
|
-
it 'should merge :wt=>:ruby to the incoming params' do
|
20
|
-
result = @connection.send(:map_params, {})
|
21
|
-
result[:wt].should == :ruby
|
22
|
-
end
|
23
|
-
it 'should not overwrite an existing :wt param' do
|
24
|
-
result = @connection.send(:map_params, {:wt=>'xml'})
|
25
|
-
result[:wt].should == 'xml'
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context '#adapt_response method' do
|
30
|
-
it 'should evaluate the :body value if the :wt param IS :ruby' do
|
31
|
-
response_from_adapter = {:body=>'{}', :params=>{:wt=>:ruby}}
|
32
|
-
result = @connection.send(:adapt_response, response_from_adapter)
|
33
|
-
result.should be_a(Hash)
|
34
|
-
end
|
35
|
-
it 'should not evaluate the :body value if the :wt is NOT :ruby' do
|
36
|
-
response_from_adapter = {:body=>'</xml>', :params=>{:wt=>:xml}}
|
37
|
-
result = @connection.send(:adapt_response, response_from_adapter)
|
38
|
-
result.should be_a(String)
|
39
|
-
end
|
40
|
-
it 'should return an object that will respond_to?(:adapter_response)' do
|
41
|
-
response_from_adapter = {:body=>'</xml>', :params=>{:wt=>:xml}}
|
42
|
-
result = @connection.send(:adapt_response, response_from_adapter)
|
43
|
-
result.should respond_to(:adapter_response)
|
44
|
-
end
|
45
|
-
it 'should return the original adapter response from #adapter_response method' do
|
46
|
-
response_from_adapter = {:body=>'</xml>', :params=>{:wt=>:xml}}
|
47
|
-
result = @connection.send(:adapt_response, response_from_adapter)
|
48
|
-
result.adapter_response.should == response_from_adapter
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should have an adapter' do
|
53
|
-
@connection.adapter.should == @adapter
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'should send requests to the adapter' do
|
57
|
-
params = {:wt=>:ruby, :q=>'test'}
|
58
|
-
expected_return = {:params=>params, :body=>'{}'}
|
59
|
-
@adapter.should_receive(:send_request).with(
|
60
|
-
'/documents',
|
61
|
-
params,
|
62
|
-
nil
|
63
|
-
).once.and_return(expected_return)
|
64
|
-
@connection.send_request('/documents', :q=>'test')
|
65
|
-
end
|
66
|
-
|
67
|
-
context '#select method' do
|
68
|
-
|
69
|
-
it 'should set the solr request path to /select' do
|
70
|
-
params = {:wt=>:ruby, :q=>'test'}
|
71
|
-
expected_return = {:params=>params, :body=>'{}'}
|
72
|
-
@adapter.should_receive(:send_request).with(
|
73
|
-
'/select',
|
74
|
-
params,
|
75
|
-
nil
|
76
|
-
).once.and_return(expected_return)
|
77
|
-
@connection.select(:q=>'test')
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'should add a :qt=>:ruby to the params, then pass the params to the adapter' do
|
81
|
-
input_params = {:q=>'test', :fq=>'filter:one', :fq=>'documents'}
|
82
|
-
expected_modified_params = input_params.merge({:wt=>:ruby})
|
83
|
-
expected_return = {:body=>'{}', :params=>expected_modified_params}
|
84
|
-
@adapter.should_receive(:send_request).with(
|
85
|
-
'/select',
|
86
|
-
hash_including(expected_modified_params),
|
87
|
-
nil
|
88
|
-
).once.and_return(expected_return)
|
89
|
-
@connection.select(input_params)
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'should return a hash' do
|
93
|
-
@adapter.should_receive(:send_request).and_return(
|
94
|
-
{:body=>'{}', :params=>{:wt=>:ruby}}
|
95
|
-
)
|
96
|
-
@connection.select(:q=>'test').should be_a(Hash)
|
97
|
-
end
|
98
|
-
|
99
|
-
end
|
100
|
-
|
101
|
-
context '#update method' do
|
102
|
-
|
103
|
-
it 'should set the solr request path to /update' do
|
104
|
-
expected_params = {:name=>'test', :wt=>:ruby}
|
105
|
-
@adapter.should_receive(:send_request).with(
|
106
|
-
'/update',
|
107
|
-
hash_including(expected_params),
|
108
|
-
'</optimize>'
|
109
|
-
).once.and_return(
|
110
|
-
{:body=>'{}', :params=>expected_params}
|
111
|
-
)
|
112
|
-
@connection.update('</optimize>', :name=>'test')
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'should accept a solr params hash' do
|
116
|
-
@adapter.should_receive(:send_request).with(
|
117
|
-
'/update',
|
118
|
-
hash_including(:xyz=>123, :wt=>:ruby),
|
119
|
-
'</optimize>'
|
120
|
-
).once.and_return(
|
121
|
-
{:body=>'{}', :params=>{:xyz=>123, :wt=>:ruby}}
|
122
|
-
)
|
123
|
-
@connection.update('</optimize>', :xyz=>123)
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
|
128
|
-
context '#send_request method' do
|
129
|
-
|
130
|
-
it 'should send the request path to the adapter' do
|
131
|
-
@adapter.should_receive(:send_request).with(
|
132
|
-
'/documents',
|
133
|
-
hash_including(:q=>'test', :wt=>:ruby),
|
134
|
-
nil
|
135
|
-
).once.and_return({:body=>'{}', :params=>{:wt=>:ruby, :q=>'test'}})
|
136
|
-
@connection.send_request('/documents', :q=>'test')
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'should return an object will respond_to :adapter_response' do
|
140
|
-
@adapter.should_receive(:send_request).with(
|
141
|
-
'/select',
|
142
|
-
hash_including(:q=>'test', :wt=>:ruby),
|
143
|
-
nil
|
144
|
-
).once.and_return({:body=>'{}', :params=>{:q=>'test', :wt=>:ruby}})
|
145
|
-
response = @connection.select(:q=>'test')
|
146
|
-
response.should respond_to(:adapter_response)
|
147
|
-
end
|
148
|
-
|
149
|
-
end
|
150
|
-
|
151
|
-
end
|
data/spec/helper.rb
DELETED
data/spec/rsolr_spec.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
describe RSolr::Connection do
|
4
|
-
|
5
|
-
context 'the #connect method' do
|
6
|
-
|
7
|
-
it 'should exist' do
|
8
|
-
RSolr.should respond_to(:connect)
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'should return an RSolr::Connection object' do
|
12
|
-
RSolr.connect.should be_a(RSolr::Connection)
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
context "the #escape method" do
|
18
|
-
|
19
|
-
it "should exist" do
|
20
|
-
RSolr.should respond_to(:escape)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should escape properly" do
|
24
|
-
RSolr.escape('Trying & % different "characters" here!').should == "Trying\\ \\&\\ \\%\\ different\\ \\\"characters\\\"\\ here\\!"
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|