rsolr 0.9.7.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.txt CHANGED
@@ -1,3 +1,24 @@
1
+ 0.9.10 - November 13, 2009
2
+ Changed RSolr.connect to return Http connection only:
3
+ RSolr.connect :url=>'xxx'
4
+ Added RSolr.direct_connect to handle the creation of SolrDirectConnections
5
+ rsolr = RSolr.direct_connect :home_dir=>''
6
+
7
+ # can also use a block so the connection will get closed automatically:
8
+ RSolr.direct_connect :home_dir=>'' do |rsolr|
9
+ # query...
10
+ end
11
+ Added paginate method to RSolr::Client
12
+ - This method requires 2 new arguments: current page and per page:
13
+ solr.paginate 1, 10, :q=>''
14
+ - handler paths can be set:
15
+ solr.paginate 1, 10, '/music', :q=>''
16
+ - handler paths can also be set by method names:
17
+ solr.paginate_music 1, 10
18
+ Added required java libs to RSolr gem
19
+ Removed :dist_dir option from Direct connection options -- you gotta load your own java libs. See examples/direct.rb
20
+ Updated specs
21
+
1
22
  0.9.7.2 - November 6, 2009
2
23
  fixed gem spec, added client.rb
3
24
 
data/README.rdoc CHANGED
@@ -30,12 +30,25 @@ A Ruby client for Apache Solr. RSolr has been developed to be simple and extenda
30
30
 
31
31
  To use a DirectSolrConnection (no http) in JRuby:
32
32
 
33
- solr = RSolr.connect(:direct,
34
- :home_dir=>'/path/to/solr/home',
35
- :dist_dir=>'/path/to/solr/distribution'
36
- )
33
+ # "apache-solr" should be a path to a solr build.
34
+ Dir['apache-solr/dist/*.jar'].each{|jar|require jar}
35
+ Dir['apache-solr/lib/*.jar'].each{|jar|require jar}
36
+
37
+ opts = {:home_dir=>'/path/to/solr/home'}
38
+
39
+ # note: you'll have to close the direct connection yourself unless using a block.
40
+ solr = RSolr.direct_connect(opts)
41
+ solr.select :q=>'*:*'
42
+ solr.connection.close
43
+
44
+ # OR using a block for automatic connection closing:
45
+ RSolr.direct_connect opts do |solr|
46
+ solr.select :q=>'*:*'
47
+ end
48
+
49
+ In general, the direct connection is less than ideal in most applications. You'll be missing out on Http caching, and it'll be impossible to do distributed searches. The direct connection could possibly come in handy though, for quickly indexing large numbers of documents.
37
50
 
38
- For more information about DirecSolrConnection, see the {API}[http://lucene.apache.org/solr/api/org/apache/solr/servlet/DirectSolrConnection.html].
51
+ For more information about DirectSolrConnection, see the {API}[http://lucene.apache.org/solr/api/org/apache/solr/servlet/DirectSolrConnection.html].
39
52
 
40
53
 
41
54
  == Querying
@@ -61,6 +74,27 @@ A shortcut for the above example:
61
74
  response = solr.documents :q=>'test'
62
75
 
63
76
 
77
+ ===Doc Pagination
78
+ RSolr is compatible with WillPaginate. To use pagination, call the "paginate" method:
79
+ response = solr.paginate current_page, per_page, :q=>'*:*'
80
+
81
+ You can also set a handler path:
82
+ response = solr.paginate current_page, per_page, '/music', :q=>'*:*'
83
+
84
+ Handler paths can also be set using a paginate_* method call like so:
85
+ response = solr.paginate_music current_page, per_page, :q=>'testing'
86
+
87
+ ====Pagination Responses
88
+ The response['docs'] array from a paginate method has the following methods:
89
+ start, per_page, total, current_page, total_pages, previous_page, next_page, has_next?, has_previous?
90
+
91
+ For example:
92
+ result = solr.paginate 1, 2, :q=>'*:*'
93
+ result['response']['docs'].has_next?
94
+
95
+ To use with WillPaginate:
96
+ <%= will_paginate result['response']['docs'] %>
97
+
64
98
  == Updating Solr
65
99
  Updating can be done using native Ruby structures. Hashes are used for single documents and arrays are used for a collection of documents (hashes). These structures get turned into simple XML "messages". Raw XML strings can also be used.
66
100
 
data/lib/rsolr/client.rb CHANGED
@@ -1,18 +1,41 @@
1
1
  class RSolr::Client
2
2
 
3
- attr_reader :adapter
3
+ attr_reader :connection
4
4
 
5
- # "adapter" is instance of:
5
+ # "connection" is instance of:
6
6
  # RSolr::Adapter::HTTP
7
7
  # RSolr::Adapter::Direct (jRuby only)
8
8
  # or any other class that uses the connection "interface"
9
- def initialize(adapter)
10
- @adapter = adapter
9
+ def initialize(connection)
10
+ @connection = connection
11
11
  end
12
-
12
+
13
13
  # Send a request to a request handler using the method name.
14
+ # Also proxies to the #paginate method if the method starts with "paginate_"
14
15
  def method_missing(method_name, *args, &blk)
15
- request("/#{method_name}", *args, &blk)
16
+ handler = method_name.to_s
17
+ if handler =~ /^paginate_/
18
+ handler = handler.sub(/^paginate_/, '')
19
+ page, per_page = args[0..1]
20
+ paginate(page, per_page, "/#{handler}", *args[2..-1], &blk)
21
+ else
22
+ request("/#{handler}", *args, &blk)
23
+ end
24
+ end
25
+
26
+ # Accepts a page/per-page value for paginating docs
27
+ # Example:
28
+ # solr.paginate 1, 10, :q=>'blah'
29
+ def paginate page, per_page, *request_args
30
+ if request_args.size == 2
31
+ params = request_args.last
32
+ elsif request_args.last.is_a? Hash
33
+ params = request_args.last
34
+ else
35
+ params = request_args.push({}).last
36
+ end
37
+ params[:start], params[:rows] = RSolr::Pagination.page_and_per_page_to_start_and_rows page, per_page
38
+ self.request(*request_args).extend RSolr::Pagination
16
39
  end
17
40
 
18
41
  # sends data to the update handler
@@ -30,7 +53,7 @@ class RSolr::Client
30
53
  #
31
54
  #
32
55
  def request(path, params={}, *extra)
33
- response = @adapter.request(path, map_params(params), *extra)
56
+ response = @connection.request(path, map_params(params), *extra)
34
57
  adapt_response(response)
35
58
  end
36
59
 
@@ -89,24 +112,24 @@ class RSolr::Client
89
112
  {:wt=>:ruby}.merge(params)
90
113
  end
91
114
 
92
- # "adapter_response" must be a hash with the following keys:
115
+ # "connection_response" must be a hash with the following keys:
93
116
  # :params - a sub hash of standard solr params
94
117
  # : body - the raw response body from the solr server
95
118
  # This method will evaluate the :body value if the params[:wt] == :ruby
96
119
  # otherwise, the body is returned
97
- # The return object has a special method attached called #adapter_response
98
- # This method gives you access to the original response from the adapter,
120
+ # The return object has a special method attached called #connection_response
121
+ # This method gives you access to the original response from the connection,
99
122
  # so you can access things like the actual :url sent to solr,
100
123
  # the raw :body, original :params and original :data
101
- def adapt_response(adapter_response)
102
- data = adapter_response[:body]
124
+ def adapt_response(connection_response)
125
+ data = connection_response[:body]
103
126
  # if the wt is :ruby, evaluate the ruby string response
104
- if adapter_response[:params][:wt] == :ruby
127
+ if connection_response[:params][:wt] == :ruby
105
128
  data = Kernel.eval(data)
106
129
  end
107
- # attach a method called #adapter_response that returns the original adapter response value
130
+ # attach a method called #connection_response that returns the original connection response value
108
131
  def data.raw; @raw end
109
- data.send(:instance_variable_set, '@raw', adapter_response)
132
+ data.send(:instance_variable_set, '@raw', connection_response)
110
133
  data
111
134
  end
112
135
 
@@ -15,13 +15,9 @@ class RSolr::Connection::Direct
15
15
  # if opts is NOT an instance of org.apache.solr.servlet.DirectSolrConnection
16
16
  # then...
17
17
  # required: opts[:home_dir] is absolute path to solr home (the directory with "data", "config" etc.)
18
- # opts must also contain either
19
- # :dist_dir => 'absolute path to solr distribution root
20
- # or
21
- # :jar_paths => ['array of directories containing the solr lib/jars']
22
- # OTHER OPTS:
23
- # :select_path => 'the/select/handler'
24
- # :update_path => 'the/update/handler'
18
+ #
19
+ # You can load your own solr java libs by setting :autoload_jars to false.
20
+ # When set to true (default), RSolr loads its own set of solr java libs.
25
21
  def initialize(opts, &block)
26
22
  if defined?(Java::OrgApacheSolrCore::SolrCore) and opts.is_a?(Java::OrgApacheSolrCore::SolrCore)
27
23
  @connection = org.apache.solr.servlet.DirectSolrConnection.new(opts)
@@ -29,19 +25,13 @@ class RSolr::Connection::Direct
29
25
  @connection = opts
30
26
  else
31
27
  opts[:data_dir] ||= File.join(opts[:home_dir].to_s, 'data')
32
- if opts[:dist_dir] and ! opts[:jar_paths]
33
- # add the standard lib and dist directories to the :jar_paths
34
- opts[:jar_paths] = [File.join(opts[:dist_dir], 'lib'), File.join(opts[:dist_dir], 'dist')]
35
- end
36
28
  @opts = opts
37
29
  end
38
30
  end
39
31
 
40
- # loads/imports the java dependencies
41
32
  # sets the @connection instance variable if it has not yet been set
42
33
  def connection
43
34
  @connection ||= (
44
- require_jars(@opts[:jar_paths]) if @opts[:jar_paths]
45
35
  org.apache.solr.servlet.DirectSolrConnection.new(opts[:home_dir], @opts[:data_dir], nil)
46
36
  )
47
37
  end
@@ -65,24 +55,15 @@ class RSolr::Connection::Direct
65
55
  raise RSolr::RequestError.new($!.message)
66
56
  end
67
57
  {
68
- :body=>body,
58
+ :status_code => 200,
69
59
  :url=>url,
60
+ :body=>body,
70
61
  :path=>path,
71
62
  :params=>params,
72
63
  :data=>data,
64
+ :headers => {},
65
+ :message => ''
73
66
  }
74
67
  end
75
68
 
76
- protected
77
-
78
- # require the jar files
79
- def require_jars(paths)
80
- paths = [paths] unless paths.is_a?(Array)
81
- paths.each do |path|
82
- raise "Invalid jar path: #{path}" unless File.exists?(path)
83
- jar_pattern = File.join(path,"**", "*.jar")
84
- Dir[jar_pattern].each {|jar_file| require jar_file }
85
- end
86
- end
87
-
88
69
  end
@@ -34,7 +34,7 @@ class RSolr::Connection::NetHttp
34
34
  http_context = self.get(path, params)
35
35
  end
36
36
  end
37
- raise RSolr::RequestError.new(http_context[:body]) unless http_context[:status_code] == 200
37
+ raise RSolr::RequestError.new("Solr Response: #{http_context[:message]}") unless http_context[:status_code] == 200
38
38
  http_context
39
39
  end
40
40
 
@@ -63,14 +63,23 @@ class RSolr::Connection::NetHttp
63
63
  {
64
64
  :status_code=>net_http_response.code.to_i,
65
65
  :url=>full_url,
66
- :body=>net_http_response.body,
66
+ :body=> encode_utf8(net_http_response.body),
67
67
  :path=>path,
68
68
  :params=>params,
69
69
  :data=>data,
70
- :headers=>headers
70
+ :headers=>headers,
71
+ :message => net_http_response.message
71
72
  }
72
73
  end
73
74
 
75
+ # encodes the string as utf-8 in Ruby 1.9
76
+ # returns the unaltered string in Ruby 1.8
77
+ def encode_utf8 string
78
+ (string.respond_to?(:force_encoding) and string.respond_to?(:encoding)) ?
79
+ string.force_encoding(Encoding::UTF_8) : string
80
+ end
81
+
82
+ # accepts a path/string and optional hash of query params
74
83
  def build_url path, params={}
75
84
  full_path = @uri.path + path
76
85
  super full_path, params, @uri.query
@@ -0,0 +1,59 @@
1
+ module RSolr::Pagination
2
+
3
+ def self.extended solr_response
4
+ d = solr_response['response']['docs']
5
+ d.extend Paginator
6
+ d.per_page = solr_response['responseHeader']['params']['rows'].to_s.to_i
7
+ d.start = solr_response['response']['start'].to_s.to_i
8
+ d.total = solr_response['response']['numFound'].to_s.to_i
9
+ end
10
+
11
+ def self.page_and_per_page_to_start_and_rows page, per_page
12
+ rows = per_page.to_s.to_i
13
+ page = page.to_s.to_i-1
14
+ page = page < 1 ? 0 : page
15
+ start = page * rows
16
+ [start, rows]
17
+ end
18
+
19
+ module Paginator
20
+
21
+ attr_accessor :start, :per_page, :total
22
+
23
+ # Returns the current page calculated from 'rows' and 'start'
24
+ # WillPaginate hook
25
+ def current_page
26
+ return 1 if start < 1
27
+ per_page_normalized = per_page < 1 ? 1 : per_page
28
+ @current_page ||= (start / per_page_normalized).ceil + 1
29
+ end
30
+
31
+ # Calcuates the total pages from 'numFound' and 'rows'
32
+ # WillPaginate hook
33
+ def total_pages
34
+ @total_pages ||= per_page > 0 ? (total / per_page.to_f).ceil : 1
35
+ end
36
+
37
+ # returns the previous page number or 1
38
+ # WillPaginate hook
39
+ def previous_page
40
+ @previous_page ||= (current_page > 1) ? current_page - 1 : 1
41
+ end
42
+
43
+ # returns the next page number or the last
44
+ # WillPaginate hook
45
+ def next_page
46
+ @next_page ||= (current_page == total_pages) ? total_pages : current_page+1
47
+ end
48
+
49
+ def has_next?
50
+ current_page < total_pages
51
+ end
52
+
53
+ def has_previous?
54
+ current_page > 1
55
+ end
56
+
57
+ end
58
+
59
+ end
data/lib/rsolr.rb CHANGED
@@ -8,38 +8,37 @@ require 'xout'
8
8
 
9
9
  module RSolr
10
10
 
11
- VERSION = '0.9.7.2'
11
+ VERSION = '0.10.0'
12
12
 
13
13
  autoload :Message, 'rsolr/message'
14
14
  autoload :Client, 'rsolr/client'
15
15
  autoload :Connection, 'rsolr/connection'
16
+ autoload :Pagination, 'rsolr/pagination'
16
17
 
17
- # Factory for creating connections.
18
- # 2 modes of argument operations:
19
- # 1. first argument is solr-adapter type, second arg is options hash for solr-adapter instance.
20
- # 2. options hash for solr-adapter only (no adapter type as first arg)
21
- #
22
- # Examples:
23
- # # default http connection
24
- # RSolr.connect
25
- # # http connection with custom url
26
- # RSolr.connect :url=>'http://solr.web100.org'
27
- # # direct connection
28
- # RSolr.connect :direct, :home_dir=>'solr', :dist_dir=>'solr-nightly'
29
- def self.connect(*args)
30
- type = args.first.is_a?(Symbol) ? args.shift : :http
31
- opts = args
32
- type_class = case type
33
- when :net_http,:http,nil
34
- 'NetHttp'
35
- when :direct
36
- 'Direct'
37
- else
38
- raise "Invalid connection type: #{type} - use :http, :direct or leave nil for :http/default"
39
- end
40
- adapter_class = RSolr::Connection.const_get(type_class)
41
- adapter = adapter_class.new(*opts)
42
- RSolr::Client.new(adapter)
18
+ # returns path to this file directory
19
+ def self.dir
20
+ File.expand_path(File.dirname(__FILE__))
21
+ end
22
+
23
+ # Http connection. Example:
24
+ # RSolr.connect
25
+ # RSolr.connect 'http://solr.web100.org'
26
+ def self.connect *args
27
+ Client.new(Connection::NetHttp.new(*args))
28
+ end
29
+
30
+ # DirectSolrConnection (jruby only). Example:
31
+ # RSolr.direct_connect 'path/to/solr/distribution'
32
+ # RSolr.direct_connect :dist_dir=>'path/to/solr/distribution', :home_dir=>'/path/to/solrhome'
33
+ # RSolr.direct_connect opts do |rsolr|
34
+ # ###
35
+ # end
36
+ # Note:
37
+ # if a block is used, the client is yielded and the solr core will be closed for you.
38
+ # if a block is NOT used, the the client is returned and the core is NOT closed.
39
+ def self.direct_connect *args, &blk
40
+ rsolr = Client.new(Connection::Direct.new(*args))
41
+ block_given? ? (yield rsolr and rsolr.connection.close) : rsolr
43
42
  end
44
43
 
45
44
  # A module that contains string related methods
data/rsolr.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "rsolr"
3
+ s.version = "0.10.0"
4
+ s.date = "2009-11-13"
5
+ s.summary = "A Ruby client for Apache Solr"
6
+ s.email = "goodieboy@gmail.com"
7
+ s.homepage = "http://github.com/mwmitchell/rsolr"
8
+ s.description = "RSolr is a Ruby gem for working with Apache Solr!"
9
+ s.has_rdoc = true
10
+ s.authors = ["Matt Mitchell"]
11
+
12
+ s.files = [
13
+ "CHANGES.txt",
14
+ "lib/rsolr/client.rb",
15
+ "lib/rsolr/connection/direct.rb",
16
+ "lib/rsolr/connection/net_http.rb",
17
+ "lib/rsolr/connection.rb",
18
+ "lib/rsolr/message.rb",
19
+ "lib/rsolr/pagination.rb",
20
+ "lib/rsolr.rb",
21
+ "lib/xout.rb",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "rsolr.gemspec"
25
+ ]
26
+
27
+ #s.rdoc_options = ["--main", "README.rdoc"]
28
+ s.extra_rdoc_files = %w(LICENSE README.rdoc CHANGES.txt)
29
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rsolr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7.2
4
+ version: 0.10.0
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-11-06 00:00:00 -05:00
12
+ date: 2009-11-13 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -21,23 +21,21 @@ extensions: []
21
21
 
22
22
  extra_rdoc_files:
23
23
  - LICENSE
24
- - Rakefile
25
24
  - README.rdoc
26
25
  - CHANGES.txt
27
26
  files:
28
- - examples/direct.rb
29
- - examples/http.rb
27
+ - CHANGES.txt
30
28
  - lib/rsolr/client.rb
31
29
  - lib/rsolr/connection/direct.rb
32
30
  - lib/rsolr/connection/net_http.rb
33
31
  - lib/rsolr/connection.rb
34
32
  - lib/rsolr/message.rb
33
+ - lib/rsolr/pagination.rb
35
34
  - lib/rsolr.rb
36
35
  - lib/xout.rb
37
36
  - LICENSE
38
- - Rakefile
39
37
  - README.rdoc
40
- - CHANGES.txt
38
+ - rsolr.gemspec
41
39
  has_rdoc: true
42
40
  homepage: http://github.com/mwmitchell/rsolr
43
41
  licenses: []
@@ -66,11 +64,5 @@ rubygems_version: 1.3.5
66
64
  signing_key:
67
65
  specification_version: 3
68
66
  summary: A Ruby client for Apache Solr
69
- test_files:
70
- - test/connection/direct_test.rb
71
- - test/connection/net_http_test.rb
72
- - test/connection/test_methods.rb
73
- - test/connection/utils_test.rb
74
- - test/helper.rb
75
- - test/message_test.rb
76
- - test/rsolr_test.rb
67
+ test_files: []
68
+
data/Rakefile DELETED
@@ -1,14 +0,0 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/rdoctask'
4
- require 'rake/gempackagetask'
5
-
6
- ENV['RUBYOPT'] = '-W1'
7
-
8
- task :environment do
9
- require File.dirname(__FILE__) + '/lib/rsolr'
10
- end
11
-
12
- Dir['tasks/**/*.rake'].each { |t| load t }
13
-
14
- task :default => ['spec:api']
data/examples/direct.rb DELETED
@@ -1,29 +0,0 @@
1
- # Must be executed using jruby
2
- require File.join(File.dirname(__FILE__), '..', 'lib', 'rsolr')
3
-
4
- base = File.expand_path( File.dirname(__FILE__) )
5
- dist = File.join(base, '..', 'apache-solr')
6
- home = File.join(dist, 'example', 'solr')
7
-
8
- solr = RSolr.connect(:direct, :home_dir=>home, :dist_dir=>dist)
9
-
10
- Dir['../apache-solr/example/exampledocs/*.xml'].each do |xml_file|
11
- puts "Updating with #{xml_file}"
12
- solr.update File.read(xml_file)
13
- end
14
-
15
- solr.commit
16
-
17
- puts
18
-
19
- response = solr.select :q=>'ipod', :fq=>'price:[0 TO 50]', :rows=>2, :start=>0
20
-
21
- docs = response['response']['docs']
22
-
23
- docs.each do |doc|
24
- puts doc['timestamp']
25
- end
26
-
27
- solr.delete_by_query('*:*') and solr.commit
28
-
29
- solr.adapter.close
data/examples/http.rb DELETED
@@ -1,24 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', 'lib', 'rsolr')
2
-
3
- solr = RSolr.connect
4
-
5
- Dir['../apache-solr/example/exampledocs/*.xml'].each do |xml_file|
6
- puts "Updating with #{xml_file}"
7
- solr.update File.read(xml_file)
8
- end
9
-
10
- solr.commit
11
-
12
- puts
13
-
14
- response = solr.select(:q=>'ipod', :fq=>['price:[0 TO 50]'], :rows=>2, :start=>0)
15
-
16
- puts "URL : #{response.raw[:url]} -> #{response.raw[:status_code]}"
17
-
18
- puts
19
-
20
- response['response']['docs'].each do |doc|
21
- puts doc['timestamp']
22
- end
23
-
24
- solr.delete_by_query('*:*') and solr.commit
@@ -1,37 +0,0 @@
1
- if defined?(JRUBY_VERSION)
2
-
3
- require 'helper'
4
- require 'connection/test_methods'
5
-
6
- class ConnectionDirectTest < RSolrBaseTest
7
-
8
- include ConnectionTestMethods
9
-
10
- attr :dist
11
- attr :home
12
-
13
- def setup
14
- base = File.expand_path( File.dirname(__FILE__) )
15
- @dist = File.join(base, '..', '..', 'solr')
16
- @home = File.join(dist, 'example', 'solr')
17
- @solr = RSolr.connect(:direct, :home_dir=>@home, :dist_dir=>@dist)
18
- @solr.delete_by_query('*:*')
19
- @solr.commit
20
- end
21
-
22
- def teardown
23
- @solr.adapter.close
24
- end
25
-
26
- def test_new_connection_with_existing_core
27
- Dir["#{@dist}/dist/*.jar"].each { |p| require p }
28
- dc = org.apache.solr.servlet.DirectSolrConnection.new(@home, "#{@home}/data", nil)
29
- adapter = RSolr::Connection::Direct.new dc
30
- s = RSolr::Connection::Base.new(adapter)
31
- assert_equal Hash, s.request('/admin/ping').class
32
- adapter.close
33
- end
34
-
35
- end
36
-
37
- end
@@ -1,29 +0,0 @@
1
- unless defined?(JRUBY_VERSION)
2
-
3
- require 'helper'
4
- require 'connection/test_methods'
5
-
6
- class NetHttpTest < RSolrBaseTest
7
-
8
- include ConnectionTestMethods
9
-
10
- def setup
11
- @solr = RSolr.connect
12
- @solr.delete_by_query('*:*')
13
- @solr.commit
14
- end
15
-
16
- # http://www.w3.org/TR/html4/interact/forms.html#submit-format
17
-
18
- # due to the way some servers implement their query string parsing,
19
- # POST is sometimes needed for large query strings.
20
- # This test simply shows that a large q value will not blow up solr.
21
- def test_post_for_select
22
- big_honkin_q = (['ipod']*1000).join(' OR ')
23
- response = @solr.adapter.request '/select', {:q=>big_honkin_q}, :method=>:post
24
- assert response
25
- end
26
-
27
- end
28
-
29
- end
@@ -1,97 +0,0 @@
1
- # These are all of the test methods used by the various connection + adapter tests
2
- # Currently: Direct and HTTP
3
- # By sharing these tests, we can make sure the adapters are doing what they're suppossed to
4
- # while staying "dry"
5
-
6
- module ConnectionTestMethods
7
-
8
-
9
- def teardown
10
- @solr.delete_by_query('id:[* TO *]')
11
- @solr.commit
12
- assert_equal 0, @solr.select(:q=>'*:*')['response']['docs'].size
13
- end
14
-
15
- # If :wt is NOT :ruby, the format doesn't get converted into a Mash (special Hash; see lib/mash.rb)
16
- # Raw ruby can be returned by using :wt=>'ruby', not :ruby
17
- def test_raw_response_formats
18
- ruby_response = @solr.select(:q=>'*:*', :wt=>'ruby')
19
- assert ruby_response.is_a?(String)
20
- assert ruby_response =~ %r('wt'=>'ruby')
21
- # xml?
22
- xml_response = @solr.select(:q=>'*:*', :wt=>'xml')
23
- assert xml_response.is_a?(String)
24
- assert xml_response =~ %r(<str name="wt">xml</str>)
25
- # json?
26
- json_response = @solr.select(:q=>'*:*', :wt=>'json')
27
- assert json_response.is_a?(String)
28
- assert json_response =~ %r("wt":"json")
29
- end
30
-
31
- def test_raise_on_invalid_query
32
- assert_raise RSolr::RequestError do
33
- @solr.select(:q=>'!')
34
- end
35
- end
36
-
37
- def test_select_response_docs
38
- @solr.add(:id=>1, :price=>1.00, :cat=>['electronics', 'something else'])
39
- @solr.commit
40
- r = @solr.select(:q=>'*:*')
41
- assert r.is_a?(Hash)
42
-
43
- docs = r['response']['docs']
44
- assert_equal Array, docs.class
45
- first = docs.first
46
-
47
- # test the has? method
48
- assert_equal 1.00, first['price']
49
-
50
- assert_equal Array, first['cat'].class
51
- assert first['cat'].include?('electronics')
52
- assert first['cat'].include?('something else')
53
- assert first['cat'].include?('something else')
54
-
55
- end
56
-
57
- def test_add
58
- assert_equal 0, @solr.select(:q=>'*:*')['response']['numFound']
59
- update_response = @solr.add({:id=>100})
60
- assert update_response.is_a?(Hash)
61
- #
62
- @solr.commit
63
- assert_equal 1, @solr.select(:q=>'*:*')['response']['numFound']
64
- end
65
-
66
- def test_delete_by_id
67
- @solr.add(:id=>100)
68
- @solr.commit
69
- total = @solr.select(:q=>'*:*')['response']['numFound']
70
- assert_equal 1, total
71
- delete_response = @solr.delete_by_id(100)
72
- @solr.commit
73
- assert delete_response.is_a?(Hash)
74
- total = @solr.select(:q=>'*:*')['response']['numFound']
75
- assert_equal 0, total
76
- end
77
-
78
- def test_delete_by_query
79
- @solr.add(:id=>1, :name=>'BLAH BLAH BLAH')
80
- @solr.commit
81
- assert_equal 1, @solr.select(:q=>'*:*')['response']['numFound']
82
- response = @solr.delete_by_query('name:"BLAH BLAH BLAH"')
83
- @solr.commit
84
- assert response.is_a?(Hash)
85
- assert_equal 0, @solr.select(:q=>'*:*')['response']['numFound']
86
- end
87
-
88
- def test_admin_luke_index_info
89
- response = @solr.request('/admin/luke', :numTerms=>0)
90
- assert response.is_a?(Hash)
91
- # make sure the ? methods are true/false
92
- assert [true, false].include?(response['index']['current'])
93
- assert [true, false].include?(response['index']['optimized'])
94
- assert [true, false].include?(response['index']['hasDeletions'])
95
- end
96
-
97
- end
@@ -1,83 +0,0 @@
1
- require 'helper'
2
-
3
- class HTTPUtilTest < RSolrBaseTest
4
-
5
- class DummyClass
6
- include RSolr::Connection::Utils
7
- end
8
-
9
- def setup
10
- @c = DummyClass.new
11
- end
12
-
13
- def test_build_url
14
- assert_equal '/something', @c.build_url('/something')
15
- assert_equal '/something?q=Testing', @c.build_url('/something', :q=>'Testing')
16
- assert_equal '/something?array=1&array=2&array=3', @c.build_url('/something', :array=>[1, 2, 3])
17
- result = @c.build_url('/something', :q=>'A', :array=>[1, 2, 3])
18
- assert result=~/^\/something\?/
19
- assert result=~/q=A/
20
- assert result=~/array=1/
21
- assert result=~/array=2/
22
- assert result=~/array=3/
23
- end
24
-
25
- def test_escape
26
- assert_equal '%2B', @c.escape('+')
27
- assert_equal 'This+is+a+test', @c.escape('This is a test')
28
- assert_equal '%3C%3E%2F%5C', @c.escape('<>/\\')
29
- assert_equal '%22', @c.escape('"')
30
- assert_equal '%3A', @c.escape(':')
31
- end
32
-
33
- def test_hash_to_query
34
- my_params = {
35
- :z=>'should be whatever',
36
- :q=>'test',
37
- :d=>[1, 2, 3, 4],
38
- :b=>:zxcv,
39
- :x=>['!', '*', nil]
40
- }
41
- result = @c.hash_to_query(my_params)
42
- assert result=~/z=should\+be\+whatever/
43
- assert result=~/q=test/
44
- assert result=~/d=1/
45
- assert result=~/d=2/
46
- assert result=~/d=3/
47
- assert result=~/d=4/
48
- assert result=~/b=zxcv/
49
- assert result=~/x=%21/
50
- assert result=~/x=*/
51
- assert result=~/x=&?/
52
- end
53
-
54
- def test_ampersand_within_query_value
55
- my_params = {
56
- "fq" => "building_facet:\"Green (Humanities & Social Sciences)\""
57
- }
58
- expected = 'fq=building_facet%3A%22Green+%28Humanities+%26+Social+Sciences%29%22'
59
- assert_equal expected, @c.hash_to_query(my_params)
60
- end
61
-
62
- def test_brackets
63
- assert_equal '%7B', @c.escape('{')
64
- assert_equal '%7D', @c.escape('}')
65
- end
66
-
67
- def test_exclamation
68
- assert_equal '%21', @c.escape('!')
69
- end
70
-
71
- def test_complex_solr_query1
72
- my_params = {'fq' => '{!raw f=field_name}crazy+\"field+value'}
73
- expected = 'fq=%7B%21raw+f%3Dfield_name%7Dcrazy%2B%5C%22field%2Bvalue'
74
- assert_equal expected, @c.hash_to_query(my_params)
75
- end
76
-
77
- def test_complex_solr_query2
78
- my_params = {'q' => '+popularity:[10 TO *] +section:0'}
79
- expected = 'q=%2Bpopularity%3A%5B10+TO+%2A%5D+%2Bsection%3A0'
80
- assert_equal expected, @c.hash_to_query(my_params)
81
- end
82
-
83
- end
data/test/helper.rb DELETED
@@ -1,61 +0,0 @@
1
-
2
- require File.join(File.dirname(__FILE__), '..', 'lib', 'rsolr')
3
- require 'test/unit'
4
-
5
- #
6
- class Test::Unit::TestCase
7
-
8
- def self.test(name, &block)
9
- test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
10
- defined = instance_method(test_name) rescue false
11
- raise "#{test_name} is already defined in #{self}" if defined
12
- if block_given?
13
- define_method(test_name, &block)
14
- else
15
- define_method(test_name) do
16
- flunk "No implementation provided for #{name}"
17
- end
18
- end
19
- end
20
-
21
- end
22
-
23
- class RSolrBaseTest < Test::Unit::TestCase
24
-
25
- def assert_class(expected, instance)
26
- assert_equal expected, instance.class
27
- end
28
-
29
- def default_test
30
-
31
- end
32
-
33
- end
34
-
35
- begin
36
- require 'rubygems'
37
- require 'redgreen'
38
- rescue LoadError
39
- end
40
-
41
- def mock_query_response
42
- %({'responseHeader'=>{
43
- 'status'=>0,'QTime'=>43,'params'=>{
44
- 'q'=>'*:*','wt'=>'ruby','echoParams'=>'EXPLICIT'
45
- }
46
- },
47
- 'response'=>{
48
- 'numFound'=>26,'start'=>0,'docs'=>[
49
- {'id'=>'SP2514N','inStock'=>true,'manu'=>'Samsung Electronics Co. Ltd.','name'=>'Samsung SpinPoint P120 SP2514N - hard drive - 250 GB - ATA-133','popularity'=>6,'price'=>92.0,'sku'=>'SP2514N','timestamp'=>'2008-11-21T17:21:55.601Z','cat'=>['electronics','hard drive'],'spell'=>['Samsung SpinPoint P120 SP2514N - hard drive - 250 GB - ATA-133'],'features'=>['7200RPM, 8MB cache, IDE Ultra ATA-133','NoiseGuard, SilentSeek technology, Fluid Dynamic Bearing (FDB) motor']},
50
- {'id'=>'6H500F0','inStock'=>true,'manu'=>'Maxtor Corp.','name'=>'Maxtor DiamondMax 11 - hard drive - 500 GB - SATA-300','popularity'=>6,'price'=>350.0,'sku'=>'6H500F0','timestamp'=>'2008-11-21T17:21:55.617Z','cat'=>['electronics','hard drive'],'spell'=>['Maxtor DiamondMax 11 - hard drive - 500 GB - SATA-300'],'features'=>['SATA 3.0Gb/s, NCQ','8.5ms seek','16MB cache']},
51
- {'id'=>'F8V7067-APL-KIT','inStock'=>false,'manu'=>'Belkin','name'=>'Belkin Mobile Power Cord for iPod w/ Dock','popularity'=>1,'price'=>19.95,'sku'=>'F8V7067-APL-KIT','timestamp'=>'2008-11-21T17:21:55.652Z','weight'=>4.0,'cat'=>['electronics','connector'],'spell'=>['Belkin Mobile Power Cord for iPod w/ Dock'],'features'=>['car power adapter, white']},
52
- {'id'=>'IW-02','inStock'=>false,'manu'=>'Belkin','name'=>'iPod & iPod Mini USB 2.0 Cable','popularity'=>1,'price'=>11.5,'sku'=>'IW-02','timestamp'=>'2008-11-21T17:21:55.657Z','weight'=>2.0,'cat'=>['electronics','connector'],'spell'=>['iPod & iPod Mini USB 2.0 Cable'],'features'=>['car power adapter for iPod, white']},
53
- {'id'=>'MA147LL/A','inStock'=>true,'includes'=>'earbud headphones, USB cable','manu'=>'Apple Computer Inc.','name'=>'Apple 60 GB iPod with Video Playback Black','popularity'=>10,'price'=>399.0,'sku'=>'MA147LL/A','timestamp'=>'2008-11-21T17:21:55.681Z','weight'=>5.5,'cat'=>['electronics','music'],'spell'=>['Apple 60 GB iPod with Video Playback Black'],'features'=>['iTunes, Podcasts, Audiobooks','Stores up to 15,000 songs, 25,000 photos, or 150 hours of video','2.5-inch, 320x240 color TFT LCD display with LED backlight','Up to 20 hours of battery life','Plays AAC, MP3, WAV, AIFF, Audible, Apple Lossless, H.264 video','Notes, Calendar, Phone book, Hold button, Date display, Photo wallet, Built-in games, JPEG photo playback, Upgradeable firmware, USB 2.0 compatibility, Playback speed control, Rechargeable capability, Battery level indication']},
54
- {'id'=>'TWINX2048-3200PRO','inStock'=>true,'manu'=>'Corsair Microsystems Inc.','name'=>'CORSAIR XMS 2GB (2 x 1GB) 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) Dual Channel Kit System Memory - Retail','popularity'=>5,'price'=>185.0,'sku'=>'TWINX2048-3200PRO','timestamp'=>'2008-11-21T17:21:55.706Z','cat'=>['electronics','memory'],'spell'=>['CORSAIR XMS 2GB (2 x 1GB) 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) Dual Channel Kit System Memory - Retail'],'features'=>['CAS latency 2, 2-3-3-6 timing, 2.75v, unbuffered, heat-spreader']},
55
- {'id'=>'VS1GB400C3','inStock'=>true,'manu'=>'Corsair Microsystems Inc.','name'=>'CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail','popularity'=>7,'price'=>74.99,'sku'=>'VS1GB400C3','timestamp'=>'2008-11-21T17:21:55.71Z','cat'=>['electronics','memory'],'spell'=>['CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail']},
56
- {'id'=>'VDBDB1A16','inStock'=>true,'manu'=>'A-DATA Technology Inc.','name'=>'A-DATA V-Series 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - OEM','popularity'=>5,'sku'=>'VDBDB1A16','timestamp'=>'2008-11-21T17:21:55.712Z','cat'=>['electronics','memory'],'spell'=>['A-DATA V-Series 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - OEM'],'features'=>['CAS latency 3, 2.7v']},
57
- {'id'=>'3007WFP','inStock'=>true,'includes'=>'USB cable','manu'=>'Dell, Inc.','name'=>'Dell Widescreen UltraSharp 3007WFP','popularity'=>6,'price'=>2199.0,'sku'=>'3007WFP','timestamp'=>'2008-11-21T17:21:55.724Z','weight'=>401.6,'cat'=>['electronics','monitor'],'spell'=>['Dell Widescreen UltraSharp 3007WFP'],'features'=>['30" TFT active matrix LCD, 2560 x 1600, .25mm dot pitch, 700:1 contrast']},
58
- {'id'=>'VA902B','inStock'=>true,'manu'=>'ViewSonic Corp.','name'=>'ViewSonic VA902B - flat panel display - TFT - 19"','popularity'=>6,'price'=>279.95,'sku'=>'VA902B','timestamp'=>'2008-11-21T17:21:55.734Z','weight'=>190.4,'cat'=>['electronics','monitor'],'spell'=>['ViewSonic VA902B - flat panel display - TFT - 19"'],'features'=>['19" TFT active matrix LCD, 8ms response time, 1280 x 1024 native resolution']}]
59
- }
60
- })
61
- end
data/test/message_test.rb DELETED
@@ -1,140 +0,0 @@
1
-
2
- require 'helper'
3
-
4
- class BuilderMessageTest < RSolrBaseTest
5
-
6
- def builder
7
- @builder ||= RSolr::Message::Builder.new
8
- end
9
-
10
- # call all of the simple methods...
11
- # make sure the xml string is valid
12
- # ensure the class is actually Solr::XML
13
- def test_simple_methods
14
- [:optimize, :rollback, :commit].each do |meth|
15
- result = self.builder.send(meth)
16
- assert_equal "<#{meth}/>", result.to_s
17
- assert_equal String, result.class
18
- end
19
- end
20
-
21
- def test_add_yields_doc_objects_if_block_given
22
- documents = [{:id=>1, :name=>'sam', :cat=>['cat 1', 'cat 2']}]
23
- add_attrs = {:boost=>200.00}
24
- result = self.builder.add(documents, add_attrs) do |doc|
25
- doc.field_by_name(:name).attrs[:boost] = 10
26
- assert_equal 4, doc.fields.size
27
- assert_equal 2, doc.fields_by_name(:cat).size
28
- end
29
- #<add boost="200.0">
30
- #<doc>
31
- #<field name="cat">cat 1</field>
32
- #<field name="cat">cat 2</field>
33
- #<field name="name" boost="10">sam</field>
34
- #<field name="id">1</field>
35
- #</doc>
36
- #</add>
37
- assert result =~ %r(name="cat">cat 1</field>)
38
- assert result =~ %r(name="cat">cat 2</field>)
39
- assert result =~ %r(<add boost="200.0">)
40
- assert result =~ %r(boost="10")
41
- assert result =~ %r(<field name="id">1</field>)
42
- end
43
-
44
- def test_delete_by_id
45
- result = self.builder.delete_by_id(10)
46
- assert_equal String, result.class
47
- assert_equal '<delete><id>10</id></delete>', result.to_s
48
- end
49
-
50
- def test_delete_by_multiple_ids
51
- result = self.builder.delete_by_id([1, 2, 3])
52
- assert_equal String, result.class
53
- assert_equal '<delete><id>1</id><id>2</id><id>3</id></delete>', result.to_s
54
- end
55
-
56
- def test_delete_by_query
57
- result = self.builder.delete_by_query('status:"LOST"')
58
- assert_equal String, result.class
59
- assert_equal '<delete><query>status:"LOST"</query></delete>', result.to_s
60
- end
61
-
62
- def test_delete_by_multiple_queries
63
- result = self.builder.delete_by_query(['status:"LOST"', 'quantity:0'])
64
- assert_equal String, result.class
65
- assert_equal '<delete><query>status:"LOST"</query><query>quantity:0</query></delete>', result.to_s
66
- end
67
-
68
- # add a single hash ("doc")
69
- def test_add_hash
70
- data = {
71
- :id=>1,
72
- :name=>'matt'
73
- }
74
- assert self.builder.add(data).to_s =~ /<field name="name">matt<\/field>/
75
- assert self.builder.add(data).to_s =~ /<field name="id">1<\/field>/
76
- end
77
-
78
- # add an array of hashes
79
- def test_add_array
80
- data = [
81
- {
82
- :id=>1,
83
- :name=>'matt'
84
- },
85
- {
86
- :id=>2,
87
- :name=>'sam'
88
- }
89
- ]
90
-
91
- message = self.builder.add(data)
92
- expected = '<add><doc><field name="id">1</field><field name="name">matt</field></doc><doc><field name="id">2</field><field name="name">sam</field></doc></add>'
93
-
94
- assert message.to_s=~/<field name="name">matt<\/field>/
95
- assert message.to_s=~/<field name="name">sam<\/field>/
96
- end
97
-
98
- # multiValue field support test, thanks to Fouad Mardini!
99
- def test_add_multi_valued_field
100
- data = {
101
- :id => 1,
102
- :name => ['matt1', 'matt2']
103
- }
104
-
105
- result = self.builder.add(data)
106
-
107
- assert result.to_s =~ /<field name="name">matt1<\/field>/
108
- assert result.to_s =~ /<field name="name">matt2<\/field>/
109
- end
110
-
111
- def test_add_single_document
112
- document = RSolr::Message::Document.new
113
- document.add_field('id', 1)
114
- document.add_field('name', 'matt', :boost => 2.0)
115
- result = self.builder.add(document)
116
-
117
- assert result.to_s =~ /<field name="id">1<\/field>/
118
-
119
- # depending on which ruby version, the attributes can be out of place
120
- # so we need to test both... there's gotta be a better way to do this?
121
- assert(
122
- result.to_s =~ /<field name="name" boost="2.0">matt<\/field>/ ||
123
- result.to_s =~ /<field boost="2.0" name="name">matt<\/field>/
124
- )
125
- end
126
-
127
- def test_add_multiple_documents
128
- documents = (1..2).map do |i|
129
- doc = RSolr::Message::Document.new
130
- doc.add_field('id', i)
131
- doc.add_field('name', "matt#{i}")
132
- doc
133
- end
134
- result = self.builder.add(documents)
135
-
136
- assert result.to_s =~ /<field name="name">matt1<\/field>/
137
- assert result.to_s =~ /<field name="name">matt2<\/field>/
138
- end
139
-
140
- end
data/test/rsolr_test.rb DELETED
@@ -1,21 +0,0 @@
1
- require 'helper'
2
-
3
- class SolrTest < RSolrBaseTest
4
-
5
- def setup
6
- if defined?(JRUBY_VERSION)
7
- @solr = RSolr.connect(:adapter=>:direct)
8
- else
9
- @solr = RSolr.connect
10
- end
11
- end
12
-
13
- def test_escape
14
- expected = %q(http\:\/\/lucene\.apache\.org\/solr)
15
- source = "http://lucene.apache.org/solr"
16
- assert_equal expected, RSolr.escape(source)
17
- assert @solr.respond_to?(:escape)
18
- assert_equal expected, @solr.escape(source)
19
- end
20
-
21
- end