rsolr-ext 0.11.2 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -9,10 +9,11 @@ A set of helper methods/modules to assist in building Solr queries and handling
9
9
  * {RSolr}[http://github.com/mwmitchell/rsolr]
10
10
 
11
11
  ==Requests
12
- To use the RSolr::Ext connection instead of the normal RSolr connection:
13
- solr = RSolr::Ext.connect
12
+ To use the RSolr::Ext connection instead of the normal RSolr connection just require 'rsolr-ext':
13
+ require 'rsolr-ext'
14
+ solr = RSolr.connect
14
15
 
15
- RSolr::Ext adds a #find and a #luke_admin method to the connection object.
16
+ RSolr::Ext adds a #find and a #luke method to the connection object.
16
17
 
17
18
  ===#luke
18
19
  The #luke method returns a Hash/Mash result of a /admin/luke?numTerms=0 request:
@@ -71,7 +72,8 @@ The #find method listens for certain keys. All other keys are ignored, allowing
71
72
 
72
73
 
73
74
  ==Request Example
74
- solr = RSolr::Ext.connect
75
+ require 'rsolr-ext'
76
+ solr = RSolr.connect
75
77
  solr_params = {
76
78
  :page=>2,
77
79
  :per_page=>10,
@@ -87,7 +89,8 @@ The #find method listens for certain keys. All other keys are ignored, allowing
87
89
  ==Responses
88
90
  RSolr::Ext decorates the normal output hash from RSolr and adds some helpful methods.
89
91
 
90
- solr = RSolr::Ext.connect
92
+ require 'rsolr-ext'
93
+ solr = RSolr.connect
91
94
 
92
95
  response = solr.find :q=>'*:*'
93
96
 
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "rsolr-ext"
8
+ gem.summary = %Q{A query/response extension lib for RSolr}
9
+ gem.description = %Q{A query/response extension lib for RSolr}
10
+ gem.email = "goodieboy@gmail.com"
11
+ gem.homepage = "http://github.com/mwmitchell/rsolr-ext"
12
+ gem.authors = ["Matt Mitchell"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_dependency "rsolr", ">= 0.12.1"
15
+
16
+ gem.files = FileList['lib/**/*.rb', 'LICENSE', 'README.rdoc', 'VERSION']
17
+ gem.test_files = ['spec/*', 'Rakefile']
18
+
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+ # Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'spec/rake/spectask'
27
+ Spec::Rake::SpecTask.new(:spec) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :spec => :check_dependencies
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "rsolr-ext #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.12.0
data/lib/rsolr-ext.rb CHANGED
@@ -17,28 +17,29 @@ end
17
17
  require 'rubygems'
18
18
  require 'rsolr'
19
19
 
20
- module RSolr
20
+ module RSolr::Ext
21
21
 
22
- module Ext
23
-
24
- VERSION = '0.11.1'
25
-
26
- autoload :Connection, 'rsolr-ext/connection.rb'
27
- autoload :Doc, 'rsolr-ext/doc.rb'
28
- autoload :Request, 'rsolr-ext/request.rb'
29
- autoload :Response, 'rsolr-ext/response.rb'
30
- autoload :Model, 'rsolr-ext/model.rb'
31
-
32
- module Connectors
33
- [:connect, :direct_connect].each do |m|
34
- define_method m do |*args|
35
- RSolr.send(m, *args).extend RSolr::Ext::Connection
36
- end
37
- end
38
- end
39
-
40
- extend Connectors
41
-
22
+ autoload :Client, 'rsolr-ext/client.rb'
23
+ autoload :Doc, 'rsolr-ext/doc.rb'
24
+ autoload :Request, 'rsolr-ext/request.rb'
25
+ autoload :Response, 'rsolr-ext/response.rb'
26
+ autoload :Model, 'rsolr-ext/model.rb'
27
+
28
+ def self.version
29
+ @version ||= File.read(File.join(File.dirname(__FILE__), '..', 'VERSION'))
30
+ end
31
+
32
+ VERSION = self.version
33
+
34
+ # modify the RSolr::Client (provides #find and #luke methods)
35
+ RSolr::Client.class_eval do
36
+ include RSolr::Ext::Client
37
+ end
38
+
39
+ # this is for backward compatibility: RSolr::Ext.connect
40
+ # recommended way is to just use RSolr.connect
41
+ def self.connect *args, &blk
42
+ RSolr.connect *args, &blk
42
43
  end
43
44
 
44
45
  end
@@ -1,4 +1,4 @@
1
- module RSolr::Ext::Connection
1
+ module RSolr::Ext::Client
2
2
 
3
3
  # TWO modes of arguments:
4
4
  #
@@ -18,7 +18,7 @@ module RSolr::Ext::Connection
18
18
  params = args.first.kind_of?(Hash) ? args.shift : {}
19
19
  # send path, map params and send the rest of the args along
20
20
  response = self.request path, RSolr::Ext::Request.map(params), *args
21
- RSolr::Ext::Response::Base.new(response)
21
+ RSolr::Ext::Response::Base.new(response, path, params)
22
22
  end
23
23
 
24
24
  # TWO modes of arguments:
@@ -20,7 +20,7 @@ module RSolr::Ext::Request
20
20
 
21
21
  # remove the input :q params
22
22
  output[:q] = input.delete :q
23
- output[:fq] = input.delete :fq
23
+ output[:fq] = input.delete(:fq) if input[:fq]
24
24
 
25
25
  if queries = input.delete(:queries)
26
26
  output[:q] = append_to_param output[:q], build_query(queries, false)
@@ -7,10 +7,12 @@ module RSolr::Ext::Response
7
7
  class Base < Mash
8
8
 
9
9
  attr :original_hash
10
+ attr_reader :request_path, :request_params
10
11
 
11
- def initialize hash
12
+ def initialize hash, handler, request_params
12
13
  super hash
13
14
  @original_hash = hash
15
+ @request_path, @request_params = request_path, request_params
14
16
  extend Response# if self['response']
15
17
  extend Docs# if self['response'] and self['response']['docs']
16
18
  extend Facets# if self['facet_counts']
@@ -21,12 +23,16 @@ module RSolr::Ext::Response
21
23
  self['responseHeader']
22
24
  end
23
25
 
26
+ def rows
27
+ params[:rows].to_i
28
+ end
29
+
24
30
  def params
25
- header['params']
31
+ (header and header['params']) ? header['params'] : request_params
26
32
  end
27
33
 
28
34
  def ok?
29
- header['status'] == 0
35
+ (header and header['status']) ? header['status'] == 0 : nil
30
36
  end
31
37
 
32
38
  def method_missing *args, &blk
@@ -43,7 +49,15 @@ module RSolr::Ext::Response
43
49
 
44
50
  # short cut to response['numFound']
45
51
  def total
46
- response[:numFound]
52
+ response[:numFound].to_s.to_i
53
+ end
54
+
55
+ def total
56
+ response[:numFound].to_s.to_i
57
+ end
58
+
59
+ def start
60
+ response[:start].to_s.to_i
47
61
  end
48
62
 
49
63
  end
@@ -44,9 +44,9 @@ module RSolr::Ext::Response::Docs
44
44
  d = base['response']['docs']
45
45
  d.each{|doc| doc.extend RSolr::Ext::Doc }
46
46
  d.extend Pageable
47
- d.per_page = base['responseHeader']['params']['rows'].to_s.to_i
48
- d.start = base['response']['start'].to_s.to_i
49
- d.total = base['response']['numFound'].to_s.to_i
47
+ d.per_page = base.rows
48
+ d.start = base.start
49
+ d.total = base.total
50
50
  end
51
51
 
52
52
  def docs
@@ -0,0 +1,216 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe RSolr::Ext do
4
+
5
+ context RSolr::Client do
6
+
7
+ let(:connection){RSolr.connect}
8
+
9
+ it 'should now have a #find method' do
10
+ connection.should respond_to(:find)
11
+ end
12
+
13
+ it 'should produce results from the #find method' do
14
+ c = connection
15
+ c.should_receive(:request).
16
+ with('/select', {:rows=>10, :start=>20, :q=>"*:*"}).
17
+ and_return({'response'=>{'docs' => []}, 'responseHeader' => {}})
18
+ response = c.find :page=>3, :per_page=>10, :q=>'*:*'#, :page=>1, :per_page=>10
19
+ response.should be_a(Mash)
20
+ end
21
+
22
+ it 'should call the #find method with a custom request handler' do
23
+ c = connection
24
+ expected_response = {'response'=>{'docs' => []}, 'responseHeader' => {}}
25
+ # ok this is hacky... the raw method needs to go into a mixin dude
26
+ def expected_response.raw
27
+ {:path => '/select'}
28
+ end
29
+ c.should_receive(:request).
30
+ with('/select', {:q=>'*:*'}).
31
+ and_return(expected_response)
32
+ response = c.find '/select', :q=>'*:*'
33
+ response.raw[:path].should match(/\/select/)
34
+ end
35
+
36
+ it 'should be ok' do
37
+ c = connection
38
+ c.should_receive(:request).
39
+ with('/select', :q=>'*:*').
40
+ and_return({'response'=>{'docs' => []}, 'responseHeader' => {'status'=>0}})
41
+ response = c.find :q=>'*:*'
42
+ response.should respond_to(:ok?)
43
+ response.ok?.should == true
44
+ end
45
+
46
+ it 'should call the #luke method' do
47
+ c = connection
48
+ c.should_receive(:request).
49
+ with('/admin/luke', {"numTerms"=>0}).
50
+ and_return({"fields"=>nil, "index"=>nil, "info" => nil})
51
+ info = c.luke
52
+ info.should be_a(Mash)
53
+ info.should have_key('fields')
54
+ info.should have_key('index')
55
+ info.should have_key('info')
56
+ end
57
+
58
+ end
59
+
60
+ context 'requests' do
61
+
62
+ it 'should create a valid request' do
63
+ solr_params = RSolr::Ext::Request.map(
64
+ :page=>'2',
65
+ :per_page=>'10',
66
+ :phrases=>{:name=>'This is a phrase'},
67
+ :filters=>['test', {:price=>(1..10)}],
68
+ :phrase_filters=>{:manu=>['Apple']},
69
+ :queries=>'ipod',
70
+ :facets=>{:fields=>['cat', 'blah']},
71
+ :spellcheck => true
72
+ )
73
+ ["test", "price:[1 TO 10]", "manu:\"Apple\""].should == solr_params[:fq]
74
+ solr_params[:start].should == 10
75
+ solr_params[:rows].should == 10
76
+ solr_params[:q].should == "ipod name:\"This is a phrase\""
77
+ solr_params['facet.field'].should == ['cat', 'blah']
78
+ solr_params[:facet].should == true
79
+ end
80
+
81
+ it 'should map fq using the phrase_filters mapping' do
82
+ solr_params = RSolr::Ext::Request.map(
83
+ :phrase_filters=>{:manu=>['Apple', 'ASG'], :color=>['red', 'blue']}
84
+ )
85
+
86
+ solr_params[:fq].size.should == 4
87
+ solr_params[:fq].should include("color:\"red\"")
88
+ solr_params[:fq].should include("color:\"blue\"")
89
+ solr_params[:fq].should include("manu:\"Apple\"")
90
+ solr_params[:fq].should include("manu:\"ASG\"")
91
+
92
+ end
93
+
94
+ it 'should map :filters and :phrase_filters while keeping an existing :fq' do
95
+ solr_params = RSolr::Ext::Request.map(
96
+ :fq => 'blah blah',
97
+ :phrase_filters=>{:manu=>['Apple', 'ASG'], :color=>['red', 'blue']}
98
+ )
99
+
100
+ solr_params[:fq].size.should == 5
101
+ solr_params[:fq].should include("blah blah")
102
+ solr_params[:fq].should include("color:\"red\"")
103
+ solr_params[:fq].should include("color:\"blue\"")
104
+ solr_params[:fq].should include("manu:\"Apple\"")
105
+ solr_params[:fq].should include("manu:\"ASG\"")
106
+ end
107
+
108
+ end
109
+
110
+ context 'response' do
111
+
112
+ def create_response
113
+ raw_response = eval(mock_query_response)
114
+ RSolr::Ext::Response::Base.new(raw_response, '/select', raw_response['params'])
115
+ end
116
+
117
+ it 'should create a valid response' do
118
+ r = create_response
119
+ r.should respond_to(:header)
120
+ r.ok?.should == true
121
+ end
122
+
123
+ it 'should have accurate pagination numbers' do
124
+ r = create_response
125
+ r.rows.should == 11
126
+ r.total.should == 26
127
+ r.start.should == 0
128
+ r.docs.per_page.should == 11
129
+ end
130
+
131
+ it 'should create a valid response class' do
132
+ r = create_response
133
+
134
+ r.should respond_to(:response)
135
+ r.ok?.should == true
136
+ r.docs.size.should == 11
137
+ r.params[:echoParams].should == 'EXPLICIT'
138
+ r.docs.previous_page.should == 1
139
+ r.docs.next_page.should == 2
140
+ #
141
+ r.should be_a(RSolr::Ext::Response::Docs)
142
+ r.should be_a(RSolr::Ext::Response::Facets)
143
+ end
144
+
145
+ it 'should create a doc with rsolr-ext methods' do
146
+ r = create_response
147
+
148
+ doc = r.docs.first
149
+ doc.has?(:cat, /^elec/).should == true
150
+ doc.has?(:cat, 'elec').should_not == true
151
+ doc.has?(:cat, 'electronics').should == true
152
+
153
+ doc.get(:cat).should == 'electronics, hard drive'
154
+ doc.get(:xyz).should == nil
155
+ doc.get(:xyz, :default=>'def').should == 'def'
156
+ end
157
+
158
+ it 'should provide facet helpers' do
159
+ r = create_response
160
+ r.facets.size.should == 2
161
+
162
+ field_names = r.facets.collect{|facet|facet.name}
163
+ field_names.include?('cat').should == true
164
+ field_names.include?('manu').should == true
165
+
166
+ first_facet = r.facets.first
167
+ first_facet.name.should == 'cat'
168
+
169
+ first_facet.items.size.should == 10
170
+
171
+ expected = "electronics - 14, memory - 3, card - 2, connector - 2, drive - 2, graphics - 2, hard - 2, monitor - 2, search - 2, software - 2"
172
+ received = first_facet.items.collect do |item|
173
+ item.value + ' - ' + item.hits.to_s
174
+ end.join(', ')
175
+
176
+ expected.should == received
177
+
178
+ r.facets.each do |facet|
179
+ facet.respond_to?(:name).should == true
180
+ facet.items.each do |item|
181
+ item.respond_to?(:value).should == true
182
+ item.respond_to?(:hits).should == true
183
+ end
184
+ end
185
+
186
+ end
187
+
188
+ it 'should return the correct value when calling facet_by_field_name' do
189
+ r = create_response
190
+ facet = r.facet_by_field_name('cat')
191
+ facet.name.should == 'cat'
192
+ end
193
+
194
+ it 'should provide the responseHeader params' do
195
+ raw_response = eval(mock_query_response)
196
+ raw_response['responseHeader']['params']['test'] = :test
197
+ r = RSolr::Ext::Response::Base.new(raw_response, '/catalog', raw_response['params'])
198
+ r.params['test'].should == :test
199
+ end
200
+
201
+ it 'should provide the solr-returned params and "rows" should be 11' do
202
+ raw_response = eval(mock_query_response)
203
+ r = RSolr::Ext::Response::Base.new(raw_response, '/catalog', {})
204
+ r.params[:rows].to_s.should == '11'
205
+ end
206
+
207
+ it 'should provide the ruby request params if responseHeader["params"] does not exist' do
208
+ raw_response = eval(mock_query_response)
209
+ raw_response.delete 'responseHeader'
210
+ r = RSolr::Ext::Response::Base.new(raw_response, '/catalog', :rows => 999)
211
+ r.params[:rows].to_s.should == '999'
212
+ end
213
+
214
+ end
215
+
216
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'rsolr-ext'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ def mock_query_response
10
+ %({'responseHeader'=>{'status'=>0,'QTime'=>5,'params'=>{'facet.limit'=>'10','wt'=>'ruby','rows'=>'11','facet'=>'true','facet.field'=>['manu','cat'],'echoParams'=>'EXPLICIT','q'=>'*:*','facet.sort'=>'true'}},'response'=>{'numFound'=>26,'start'=>0,'docs'=>[{'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'=>'2009-03-20T14:42:49.795Z','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']},{'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'=>'2009-03-20T14:42:49.877Z','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']},{'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'=>'2009-03-20T14:42:49.937Z','weight'=>4.0,'cat'=>['electronics','connector'],'spell'=>['Belkin Mobile Power Cord for iPod w/ Dock'],'features'=>['car power adapter, white']},{'id'=>'IW-02','inStock'=>false,'manu'=>'Belkin','name'=>'iPod & iPod Mini USB 2.0 Cable','popularity'=>1,'price'=>11.5,'sku'=>'IW-02','timestamp'=>'2009-03-20T14:42:49.944Z','weight'=>2.0,'cat'=>['electronics','connector'],'spell'=>['iPod & iPod Mini USB 2.0 Cable'],'features'=>['car power adapter for iPod, white']},{'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'=>'2009-03-20T14:42:49.962Z','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']},{'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'=>'2009-03-20T14:42:49.99Z','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']},{'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'=>'2009-03-20T14:42:50Z','cat'=>['electronics','memory'],'spell'=>['CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail']},{'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'=>'2009-03-20T14:42:50.004Z','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']},{'id'=>'3007WFP','inStock'=>true,'includes'=>'USB cable','manu'=>'Dell, Inc.','name'=>'Dell Widescreen UltraSharp 3007WFP','popularity'=>6,'price'=>2199.0,'sku'=>'3007WFP','timestamp'=>'2009-03-20T14:42:50.017Z','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']},{'id'=>'VA902B','inStock'=>true,'manu'=>'ViewSonic Corp.','name'=>'ViewSonic VA902B - flat panel display - TFT - 19"','popularity'=>6,'price'=>279.95,'sku'=>'VA902B','timestamp'=>'2009-03-20T14:42:50.034Z','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']},{'id'=>'0579B002','inStock'=>true,'manu'=>'Canon Inc.','name'=>'Canon PIXMA MP500 All-In-One Photo Printer','popularity'=>6,'price'=>179.99,'sku'=>'0579B002','timestamp'=>'2009-03-20T14:42:50.062Z','weight'=>352.0,'cat'=>['electronics','multifunction printer','printer','scanner','copier'],'spell'=>['Canon PIXMA MP500 All-In-One Photo Printer'],'features'=>['Multifunction ink-jet color photo printer','Flatbed scanner, optical scan resolution of 1,200 x 2,400 dpi','2.5" color LCD preview screen','Duplex Copying','Printing speed up to 29ppm black, 19ppm color','Hi-Speed USB','memory card: CompactFlash, Micro Drive, SmartMedia, Memory Stick, Memory Stick Pro, SD Card, and MultiMediaCard']}]},'facet_counts'=>{'facet_queries'=>{},'facet_fields'=>{'manu'=>['inc',8,'apach',2,'belkin',2,'canon',2,'comput',2,'corp',2,'corsair',2,'foundat',2,'microsystem',2,'softwar',2],'cat'=>['electronics',14,'memory',3,'card',2,'connector',2,'drive',2,'graphics',2,'hard',2,'monitor',2,'search',2,'software',2]},'facet_dates'=>{}}})
11
+ end
12
+
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rsolr-ext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.2
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Mitchell
@@ -9,20 +9,30 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-07 00:00:00 -05:00
12
+ date: 2010-02-09 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.9
24
+ version:
15
25
  - !ruby/object:Gem::Dependency
16
26
  name: rsolr
17
27
  type: :runtime
18
28
  version_requirement:
19
29
  version_requirements: !ruby/object:Gem::Requirement
20
30
  requirements:
21
- - - "="
31
+ - - ">="
22
32
  - !ruby/object:Gem::Version
23
- version: 0.11.0
33
+ version: 0.12.1
24
34
  version:
25
- description: An extension lib for RSolr
35
+ description: A query/response extension lib for RSolr
26
36
  email: goodieboy@gmail.com
27
37
  executables: []
28
38
 
@@ -32,26 +42,26 @@ extra_rdoc_files:
32
42
  - LICENSE
33
43
  - README.rdoc
34
44
  files:
45
+ - LICENSE
46
+ - README.rdoc
47
+ - VERSION
35
48
  - lib/mash.rb
36
- - lib/rsolr-ext/connection.rb
49
+ - lib/rsolr-ext.rb
50
+ - lib/rsolr-ext/client.rb
37
51
  - lib/rsolr-ext/doc.rb
38
52
  - lib/rsolr-ext/model.rb
39
53
  - lib/rsolr-ext/request.rb
54
+ - lib/rsolr-ext/response.rb
40
55
  - lib/rsolr-ext/response/docs.rb
41
56
  - lib/rsolr-ext/response/facets.rb
42
57
  - lib/rsolr-ext/response/spelling.rb
43
- - lib/rsolr-ext/response.rb
44
- - lib/rsolr-ext.rb
45
- - LICENSE
46
- - README.rdoc
47
- - rsolr-ext.gemspec
48
58
  has_rdoc: true
49
59
  homepage: http://github.com/mwmitchell/rsolr-ext
50
60
  licenses: []
51
61
 
52
62
  post_install_message:
53
- rdoc_options: []
54
-
63
+ rdoc_options:
64
+ - --charset=UTF-8
55
65
  require_paths:
56
66
  - lib
57
67
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -72,10 +82,9 @@ rubyforge_project:
72
82
  rubygems_version: 1.3.5
73
83
  signing_key:
74
84
  specification_version: 3
75
- summary: An extension lib for RSolr
85
+ summary: A query/response extension lib for RSolr
76
86
  test_files:
77
- - test/connection_test.rb
78
- - test/request_test.rb
79
- - test/response_test.rb
80
- - test/test_unit_test_case.rb
81
- - test/helper.rb
87
+ - spec/rsolr-ext_spec.rb
88
+ - spec/spec.opts
89
+ - spec/spec_helper.rb
90
+ - Rakefile
data/rsolr-ext.gemspec DELETED
@@ -1,40 +0,0 @@
1
- Gem::Specification.new do |s|
2
-
3
- s.name = "rsolr-ext"
4
- s.version = "0.11.2"
5
- s.date = "2010-01-07"
6
-
7
- s.summary = "An extension lib for RSolr"
8
- s.email = "goodieboy@gmail.com"
9
- s.homepage = "http://github.com/mwmitchell/rsolr-ext"
10
- s.description = "An extension lib for RSolr"
11
- s.has_rdoc = true
12
- s.authors = ["Matt Mitchell"]
13
- s.files = [
14
- "lib/mash.rb",
15
- "lib/rsolr-ext/connection.rb",
16
- "lib/rsolr-ext/doc.rb",
17
- "lib/rsolr-ext/model.rb",
18
- "lib/rsolr-ext/request.rb",
19
- "lib/rsolr-ext/response/docs.rb",
20
- "lib/rsolr-ext/response/facets.rb",
21
- "lib/rsolr-ext/response/spelling.rb",
22
- "lib/rsolr-ext/response.rb",
23
- "lib/rsolr-ext.rb",
24
- "LICENSE",
25
- "README.rdoc",
26
- "rsolr-ext.gemspec"
27
- ]
28
- s.test_files = [
29
- 'test/connection_test.rb',
30
- 'test/request_test.rb',
31
- 'test/response_test.rb',
32
- 'test/test_unit_test_case.rb',
33
- 'test/helper.rb'
34
- ]
35
-
36
- s.extra_rdoc_files = %w(LICENSE README.rdoc)
37
-
38
- s.add_dependency("rsolr", ["=0.11.0"])
39
-
40
- end
@@ -1,36 +0,0 @@
1
- class RSolrExtConnectionTest < Test::Unit::TestCase
2
-
3
- test 'the #connect method' do
4
- connection = RSolr::Ext.connect
5
- assert connection.respond_to?(:find)
6
- end
7
-
8
- test 'the #find method' do
9
- connection = RSolr::Ext.connect
10
- response = connection.find :page=>3, :per_page=>10, :q=>'*:*'#, :page=>1, :per_page=>10
11
- assert response.kind_of?(Mash)
12
- end
13
-
14
- test 'the #find method with a custom request handler' do
15
- connection = RSolr::Ext.connect
16
- response = connection.find '/select', :q=>'*:*'
17
- assert response.raw[:path]=~/\/select/
18
- end
19
-
20
- test 'the response' do
21
- connection = RSolr::Ext.connect
22
- response = connection.find :q=>'*:*'
23
- assert response.respond_to?(:ok?)
24
- assert response.ok?
25
- assert_equal response.docs[0][:id], response.docs[0].id
26
- end
27
-
28
- test 'the #luke method' do
29
- info = RSolr::Ext.connect.luke
30
- assert info.kind_of?(Mash)
31
- assert info.key?('fields')
32
- assert info.key?('index')
33
- assert info.key?('info')
34
- end
35
-
36
- end
data/test/helper.rb DELETED
@@ -1,3 +0,0 @@
1
- def mock_query_response
2
- %({'responseHeader'=>{'status'=>0,'QTime'=>5,'params'=>{'facet.limit'=>'10','wt'=>'ruby','rows'=>'11','facet'=>'true','facet.field'=>['manu','cat'],'echoParams'=>'EXPLICIT','q'=>'*:*','facet.sort'=>'true'}},'response'=>{'numFound'=>26,'start'=>0,'docs'=>[{'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'=>'2009-03-20T14:42:49.795Z','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']},{'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'=>'2009-03-20T14:42:49.877Z','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']},{'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'=>'2009-03-20T14:42:49.937Z','weight'=>4.0,'cat'=>['electronics','connector'],'spell'=>['Belkin Mobile Power Cord for iPod w/ Dock'],'features'=>['car power adapter, white']},{'id'=>'IW-02','inStock'=>false,'manu'=>'Belkin','name'=>'iPod & iPod Mini USB 2.0 Cable','popularity'=>1,'price'=>11.5,'sku'=>'IW-02','timestamp'=>'2009-03-20T14:42:49.944Z','weight'=>2.0,'cat'=>['electronics','connector'],'spell'=>['iPod & iPod Mini USB 2.0 Cable'],'features'=>['car power adapter for iPod, white']},{'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'=>'2009-03-20T14:42:49.962Z','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']},{'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'=>'2009-03-20T14:42:49.99Z','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']},{'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'=>'2009-03-20T14:42:50Z','cat'=>['electronics','memory'],'spell'=>['CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail']},{'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'=>'2009-03-20T14:42:50.004Z','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']},{'id'=>'3007WFP','inStock'=>true,'includes'=>'USB cable','manu'=>'Dell, Inc.','name'=>'Dell Widescreen UltraSharp 3007WFP','popularity'=>6,'price'=>2199.0,'sku'=>'3007WFP','timestamp'=>'2009-03-20T14:42:50.017Z','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']},{'id'=>'VA902B','inStock'=>true,'manu'=>'ViewSonic Corp.','name'=>'ViewSonic VA902B - flat panel display - TFT - 19"','popularity'=>6,'price'=>279.95,'sku'=>'VA902B','timestamp'=>'2009-03-20T14:42:50.034Z','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']},{'id'=>'0579B002','inStock'=>true,'manu'=>'Canon Inc.','name'=>'Canon PIXMA MP500 All-In-One Photo Printer','popularity'=>6,'price'=>179.99,'sku'=>'0579B002','timestamp'=>'2009-03-20T14:42:50.062Z','weight'=>352.0,'cat'=>['electronics','multifunction printer','printer','scanner','copier'],'spell'=>['Canon PIXMA MP500 All-In-One Photo Printer'],'features'=>['Multifunction ink-jet color photo printer','Flatbed scanner, optical scan resolution of 1,200 x 2,400 dpi','2.5" color LCD preview screen','Duplex Copying','Printing speed up to 29ppm black, 19ppm color','Hi-Speed USB','memory card: CompactFlash, Micro Drive, SmartMedia, Memory Stick, Memory Stick Pro, SD Card, and MultiMediaCard']}]},'facet_counts'=>{'facet_queries'=>{},'facet_fields'=>{'manu'=>['inc',8,'apach',2,'belkin',2,'canon',2,'comput',2,'corp',2,'corsair',2,'foundat',2,'microsystem',2,'softwar',2],'cat'=>['electronics',14,'memory',3,'card',2,'connector',2,'drive',2,'graphics',2,'hard',2,'monitor',2,'search',2,'software',2]},'facet_dates'=>{}}})
3
- end
data/test/request_test.rb DELETED
@@ -1,50 +0,0 @@
1
- class RSolrExtRequestTest < Test::Unit::TestCase
2
-
3
- test 'standard request' do
4
- solr_params = RSolr::Ext::Request.map(
5
- :page=>'2',
6
- :per_page=>'10',
7
- :phrases=>{:name=>'This is a phrase'},
8
- :filters=>['test', {:price=>(1..10)}],
9
- :phrase_filters=>{:manu=>['Apple']},
10
- :queries=>'ipod',
11
- :facets=>{:fields=>['cat', 'blah']},
12
- :spellcheck => true
13
- )
14
- assert_equal ["test", "price:[1 TO 10]", "manu:\"Apple\""], solr_params[:fq]
15
- assert_equal 10, solr_params[:start]
16
- assert_equal 10, solr_params[:rows]
17
- assert_equal "ipod name:\"This is a phrase\"", solr_params[:q]
18
- assert_equal ['cat', 'blah'], solr_params['facet.field']
19
- assert_equal true, solr_params[:facet]
20
- end
21
-
22
- test 'fq param using the phrase_filters mapping' do
23
- solr_params = RSolr::Ext::Request.map(
24
- :phrase_filters=>{:manu=>['Apple', 'ASG'], :color=>['red', 'blue']}
25
- )
26
-
27
- assert_equal 4, solr_params[:fq].size
28
- assert solr_params[:fq].include?("color:\"red\"")
29
- assert solr_params[:fq].include?("color:\"blue\"")
30
- assert solr_params[:fq].include?("manu:\"Apple\"")
31
- assert solr_params[:fq].include?("manu:\"ASG\"")
32
-
33
- end
34
-
35
- test ':filters and :phrase_filters will play nice with :fq' do
36
- solr_params = RSolr::Ext::Request.map(
37
- :fq => 'blah blah',
38
- :phrase_filters=>{:manu=>['Apple', 'ASG'], :color=>['red', 'blue']}
39
- )
40
- expected = {:fq=>["blah blah", "color:\"red\"", "color:\"blue\"", "manu:\"Apple\"", "manu:\"ASG\""]}
41
-
42
- assert_equal 5, solr_params[:fq].size
43
- assert solr_params[:fq].include?("blah blah")
44
- assert solr_params[:fq].include?("color:\"red\"")
45
- assert solr_params[:fq].include?("color:\"blue\"")
46
- assert solr_params[:fq].include?("manu:\"Apple\"")
47
- assert solr_params[:fq].include?("manu:\"ASG\"")
48
- end
49
-
50
- end
@@ -1,103 +0,0 @@
1
- class RSolrExtResponseTest < Test::Unit::TestCase
2
-
3
- test 'base response class' do
4
- raw_response = eval(mock_query_response)
5
- r = RSolr::Ext::Response::Base.new(raw_response)
6
- assert r.respond_to?(:header)
7
- assert r.ok?
8
- end
9
-
10
- test 'standard response class' do
11
- raw_response = eval(mock_query_response)
12
- r = RSolr::Ext::Response::Base.new(raw_response)
13
-
14
- assert r.respond_to?(:response)
15
- assert r.ok?
16
- assert_equal 11, r.docs.size
17
- assert_equal 'EXPLICIT', r.params[:echoParams]
18
- assert_equal 1, r.docs.previous_page
19
- assert_equal 2, r.docs.next_page
20
- #
21
- assert r.kind_of?(RSolr::Ext::Response::Docs)
22
- assert r.kind_of?(RSolr::Ext::Response::Facets)
23
- end
24
-
25
- test 'standard response doc ext methods' do
26
- raw_response = eval(mock_query_response)
27
- r = RSolr::Ext::Response::Base.new(raw_response)
28
- doc = r.docs.first
29
- assert doc.has?(:cat, /^elec/)
30
- assert ! doc.has?(:cat, 'elec')
31
- assert doc.has?(:cat, 'electronics')
32
-
33
- assert 'electronics', doc.get(:cat)
34
- assert_nil doc.get(:xyz)
35
- assert_equal 'def', doc.get(:xyz, :default=>'def')
36
- end
37
-
38
- test 'Response::Standard facets' do
39
- raw_response = eval(mock_query_response)
40
- r = RSolr::Ext::Response::Base.new(raw_response)
41
- assert_equal 2, r.facets.size
42
-
43
- field_names = r.facets.collect{|facet|facet.name}
44
- assert field_names.include?('cat')
45
- assert field_names.include?('manu')
46
-
47
- first_facet = r.facets.first
48
- assert_equal 'cat', first_facet.name
49
-
50
- assert_equal 10, first_facet.items.size
51
-
52
- expected = first_facet.items.collect do |item|
53
- item.value + ' - ' + item.hits.to_s
54
- end.join(', ')
55
- assert_equal "electronics - 14, memory - 3, card - 2, connector - 2, drive - 2, graphics - 2, hard - 2, monitor - 2, search - 2, software - 2", expected
56
-
57
- r.facets.each do |facet|
58
- assert facet.respond_to?(:name)
59
- facet.items.each do |item|
60
- assert item.respond_to?(:value)
61
- assert item.respond_to?(:hits)
62
- end
63
- end
64
-
65
- end
66
-
67
- test 'response::standard facet_by_field_name' do
68
- raw_response = eval(mock_query_response)
69
- r = RSolr::Ext::Response::Base.new(raw_response)
70
- facet = r.facet_by_field_name('cat')
71
- assert_equal 'cat', facet.name
72
- end
73
-
74
- =begin
75
-
76
- # pagination for facets has been commented out in the response/facets module.
77
- # ...need to think more about how this can be handled
78
-
79
- test 'response::standard facets.paginate' do
80
- raw_response = eval(mock_query_response)
81
- raw_response['responseHeader']['params']['facet.offset'] = 1
82
- raw_response['responseHeader']['params']['facet.limit'] = 2
83
-
84
- r = RSolr::Ext::Response::Standard.new(raw_response)
85
-
86
- assert_equal 2, r.facets.current_page
87
-
88
- # always 1 less than facet.limit
89
- assert_equal 1, r.facets.per_page
90
-
91
- assert_equal 3, r.facets.next_page
92
-
93
- assert_equal 1, r.facets.previous_page
94
-
95
- # can't know how many pages there are with facets.... so we set it to -1
96
- assert_equal -1, r.facets.total_pages
97
-
98
- assert r.facets.has_next?
99
- assert r.facets.has_previous?
100
- end
101
- =end
102
-
103
- end
@@ -1,18 +0,0 @@
1
- require 'test/unit'
2
-
3
- class Test::Unit::TestCase
4
-
5
- def self.test(name, &block)
6
- test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
7
- defined = instance_method(test_name) rescue false
8
- raise "#{test_name} is already defined in #{self}" if defined
9
- if block_given?
10
- define_method(test_name, &block)
11
- else
12
- define_method(test_name) do
13
- flunk "No implementation provided for #{name}"
14
- end
15
- end
16
- end
17
-
18
- end