mwmitchell-rsolr 0.8.4 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
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) do |solr_response,adapter_response|
16
- puts "URL : #{adapter_response[:url]}"
17
- solr_response[:response][:docs].each do |doc|
18
- puts doc[:timestamp]
19
- end
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
@@ -57,13 +57,11 @@ class RSolr::Adapter::Direct
57
57
  raise RSolr::RequestError.new($!.message)
58
58
  end
59
59
  {
60
- :status_code=>nil,
61
60
  :body=>body,
62
61
  :url=>url,
63
62
  :path=>path,
64
63
  :params=>params,
65
64
  :data=>data,
66
- :headers=>nil
67
65
  }
68
66
  end
69
67
 
@@ -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 post headers
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
@@ -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] if data.respond_to?(:each_pair)
112
+ data = [data] unless data.is_a?(Array)
100
113
  xml.add(add_attrs) do |add_node|
101
- data.each do |item|
114
+ data.each do |doc|
102
115
  # create doc, passing in fields
103
- doc = Document.new(item)
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.4'
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
- end
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
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-03 00:00:00 -07:00
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
@@ -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
@@ -1,4 +0,0 @@
1
- require 'rubygems'
2
- require 'spec'
3
-
4
- require File.join(File.dirname(__FILE__), '..', 'lib', 'rsolr')
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