simple_solr 0.6.0 → 0.7.0

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/.travis.yml CHANGED
@@ -1,3 +1,2 @@
1
1
  rvm:
2
- - 1.8.7
3
2
  - 1.9.2
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.7.0 (Sep 29, 2011)
2
+
3
+ - Only test on 1.9.2
4
+ - Use fakeweb to mock the webserver response
5
+ - Use Nokogiri to parse the response instead of relying on automatic hashing
6
+
7
+
1
8
  == 0.6.0 (Aug 18, 2011)
2
9
 
3
10
  - Return the parsed response from httparty for search results
data/Gemfile CHANGED
@@ -5,6 +5,8 @@ gemspec
5
5
  gem "rake"
6
6
  gem "activerecord"
7
7
  gem "rspec", ">= 2"
8
+ gem "nokogiri"
8
9
  gem "sqlite3"
9
10
  gem "httparty"
10
11
  gem "builder"
12
+ gem "fakeweb"
data/README.rdoc CHANGED
@@ -130,10 +130,25 @@ Use the +simple_search+ class method on your model:
130
130
 
131
131
  Document.simple_search 'apple'
132
132
 
133
- This will make a trip to Solr and return the results as a hash. That's right.
134
- The results are not correlated with your models. In fact, no processing is
135
- done at all. Simple, right? If you need to fetch model instances based on the
136
- results, that is up to you.
133
+ This will make a trip to Solr and return the results as a Nokogiri XML
134
+ Document. A slightly more convenient method to return only the matching
135
+ documents is present as well:
136
+
137
+ Document.simple_search_docs 'apple'
138
+
139
+ gives you a Nodeset which you can query further. You will need either
140
+ XPath or CSS selectors to drill down to the results you want. Given this
141
+ individual +doc+ result:
142
+
143
+ <doc><str name="title">Woezel en Pip</str></doc>
144
+
145
+ the contents of the title tag can be fetched like this:
146
+
147
+ results = Document.simple_search_docs 'apple'
148
+ results.first.at_css('str[name=title]').contents # => Woezel en Pip
149
+
150
+
151
+ === Search parameters
137
152
 
138
153
  You can add parameters, for example if you want to limit results using +fq+:
139
154
 
@@ -143,7 +158,10 @@ See the Solr documentation[http://wiki.apache.org/solr/CommonQueryParameters] fo
143
158
  of common query parameters. Just remember that the +q+ parameter will be set already,
144
159
  although it can be overriden by the parameters you provide.
145
160
 
146
- The response from Solr will look something like this:
161
+
162
+ === Response example
163
+
164
+ The raw response from Solr will look something like this:
147
165
 
148
166
  <?xml version="1.0" encoding="UTF-8"?>
149
167
  <response>
@@ -166,8 +184,7 @@ The response from Solr will look something like this:
166
184
  </lst>
167
185
  </response>
168
186
 
169
- This response will be translated into a hash by httparty. Take a look at your
170
- webserver config/response headers if that does not happen.
187
+ where every +doc+ is a matching document found in the index.
171
188
 
172
189
 
173
190
  == Working in batches
@@ -184,10 +201,15 @@ Same for deleting documents:
184
201
  document.delete_from_solr
185
202
  end
186
203
 
187
- Just remember to not touch the +id+ field since you added the model, since
204
+ Just remember to not change the +id+ field since you added the model, since
188
205
  this key is used to delete documents from Solr.
189
206
 
190
207
 
208
+ == Supported Ruby version
209
+
210
+ This gem is only tested on Ruby 1.9.2. It will probably work on other versions as well.
211
+
212
+
191
213
  == Helping out
192
214
 
193
215
  Interested in working on SimpleSolr? Please see DEVELOPMENT.rdoc.
data/lib/simple_solr.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'active_record'
2
+ require 'nokogiri'
2
3
  require 'httparty'
3
4
  require 'builder'
4
5
 
@@ -9,7 +10,6 @@ require "simple_solr/version"
9
10
 
10
11
  if defined?(ActiveRecord::Base)
11
12
  ActiveRecord::Base.send :include, SimpleSolr::Update
12
- ActiveRecord::Base.extend SimpleSolr::Search
13
13
  end
14
14
 
15
15
  module SimpleSolr
@@ -17,9 +17,5 @@ module SimpleSolr
17
17
  def configuration
18
18
  @configuration ||= SimpleSolr::Configuration.new
19
19
  end
20
-
21
- def search(query, params)
22
- SimpleSolr::Search.simple_search(query, params)
23
- end
24
20
  end
25
21
  end
@@ -5,15 +5,26 @@ module SimpleSolr
5
5
  #
6
6
  # Product.simple_search 'delicious', :fq => "category:fruit"
7
7
  #
8
- # Returns a hash with the search results:
9
- #
10
- # {
11
- # "lst" => [{"int"=>["0", "18"], "name"=>"responseHeader"},{"name"=>"highlighting"}],
12
- # "result" => {"name"=>"response", "numFound"=>"0", "start"=>"0", "maxScore"=>"0.0"}
13
- # }
8
+ # Returns a Nokogiri::XML::Document.
14
9
  def simple_search(query, params={})
15
10
  query = {:q => query}
16
- get(SimpleSolr.configuration.uri + "/select", :query => query.merge(params)).parsed_response['response']
11
+ response = get(SimpleSolr.configuration.uri + "/select", :query => query.merge(params))
12
+ Nokogiri::XML(response.body)
13
+ end
14
+
15
+ # Returns all +doc+ elements, aka matching documents, from the search results in an array.
16
+ # To dig deeper, use css selectors to find the elements you need.
17
+ #
18
+ # <doc><str name="title">Woezel en Pip</str></doc>
19
+ #
20
+ # the contents of the title tag can be fetched like this:
21
+ #
22
+ # results = Document.simple_search_docs('apple')
23
+ # results.first.at_css('str[name=title]').contents # => Woezel en Pip
24
+ #
25
+ # I told you it was close to the metal! Refer to the Nokogiro docs for more information.
26
+ def simple_search_docs(query, params={})
27
+ simple_search(query, params).css('doc')
17
28
  end
18
29
  end
19
30
  end
@@ -2,6 +2,7 @@ module SimpleSolr
2
2
  module Update
3
3
  def self.included(base)
4
4
  base.extend ClassMethods
5
+ base.extend SimpleSolr::Search
5
6
  end
6
7
 
7
8
  module ClassMethods
@@ -1,3 +1,3 @@
1
1
  module SimpleSolr
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
data/simple_solr.gemspec CHANGED
@@ -17,8 +17,10 @@ Gem::Specification.new do |s|
17
17
  s.require_paths = ["lib"]
18
18
 
19
19
  s.add_development_dependency "rspec", ">= 2"
20
+ s.add_development_dependency "fakeweb"
20
21
 
21
22
  s.add_runtime_dependency "activerecord"
23
+ s.add_runtime_dependency "nokogiri"
22
24
  s.add_runtime_dependency "httparty"
23
25
  s.add_runtime_dependency "builder"
24
26
  end
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <response>
3
+ <lst name="responseHeader">
4
+ <int name="status">0</int>
5
+ <int name="QTime">3</int>
6
+ </lst>
7
+ <result name="response" numFound="1" start="0" maxScore="13.722203">
8
+ <doc>
9
+ <float name="score">13.722203</float>
10
+ <date name="date_creation">2011-01-06T23:02:33Z</date>
11
+ <str name="id">969</str>
12
+ <str name="publisher">Widgets, Inc</str>
13
+ <str name="title">Golden Delicious</str>
14
+ <str name="category">Apples</str>
15
+ </doc>
16
+ </result>
17
+ <lst name="highlighting">
18
+ <lst name="969"/>
19
+ </lst>
20
+ </response>
@@ -0,0 +1,46 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <response>
3
+ <lst name="responseHeader">
4
+ <int name="status">0</int>
5
+ <int name="QTime">3</int>
6
+ </lst>
7
+ <result name="response" numFound="1" start="0" maxScore="3.2594316">
8
+ <doc>
9
+ <float name="score">3.2594316</float>
10
+ <str name="brand_site">www.zappelin.nl</str>
11
+ <str name="brand_title">Z@ppelin</str>
12
+ <arr name="contenttype">
13
+ <str>text</str>
14
+ </arr>
15
+ <date name="date_creation">2010-12-26T23:02:48Z</date>
16
+ <date name="date_offline">2021-08-23T10:44:46Z</date>
17
+ <date name="date_online">2010-12-26T23:02:00Z</date>
18
+ <date name="date_updated">2011-01-26T16:21:56Z</date>
19
+ <str name="deeplink">http://www.zappelin.nl/series/962-woezel-en-pip</str>
20
+ <str name="id">http://www.zappelin.nl/series/962-woezel-en-pip</str>
21
+ <arr name="keywords">
22
+ <str/>
23
+ </arr>
24
+ <str name="publisher">NPO</str>
25
+ <str name="shared">true</str>
26
+ <str name="summary">&lt;p&gt;Woezel en Pip zijn de nieuwsgierige hondjes die bedacht zijn door Guusje Nederhorst.&lt;/p&gt;</str>
27
+ <arr name="thumbnails">
28
+ <str>/attachments/contents/000/002/743/uploads/thumbnail/woezel_pip.jpg</str>
29
+ </arr>
30
+ <str name="title">Woezel en Pip</str>
31
+ </doc>
32
+ </result>
33
+ <lst name="highlighting">
34
+ <lst name="http://www.zappelin.nl/series/962-woezel-en-pip">
35
+ <arr name="title">
36
+ <str>&lt;em&gt;Woezel&lt;/em&gt; en Pip </str>
37
+ </arr>
38
+ <arr name="deeplink">
39
+ <str>s/962-&lt;em&gt;woezel&lt;/em&gt;-en-pip </str>
40
+ </arr>
41
+ <arr name="summary">
42
+ <str>&lt;p&gt;&lt;em&gt;Woezel&lt;/em&gt; en Pip zijn de nieuwsgierige hondjes die bedacht zijn door Guusje Nederhorst.&lt;/p&gt; </str>
43
+ </arr>
44
+ </lst>
45
+ </lst>
46
+ </response>
@@ -1,30 +1,32 @@
1
1
  require 'spec_helper'
2
2
 
3
+ fixture = File.dirname(__FILE__) + "/../fixtures/result.xml"
4
+
5
+ FakeWeb.register_uri(:get,
6
+ "http://test.local:8983/solr/select?q=bonanza",
7
+ :body => File.read(fixture),
8
+ :content_type => "application/xml"
9
+ )
10
+
3
11
  describe SimpleSolr::Search do
4
- let(:response) { stub("response")}
5
- let(:httparty) { stub("httparty", :parsed_response => {'response' => response})}
6
-
12
+
7
13
  describe SimpleDocument do
8
- before do
9
- SimpleDocument.stub(:get).and_return(httparty)
10
- end
11
14
 
12
- it "responds to search" do
13
- SimpleDocument.should respond_to(:simple_search)
15
+ it "returns a Nokogiri::XML::Document" do
16
+ SimpleDocument.simple_search('bonanza').should be_a(Nokogiri::XML::Document)
14
17
  end
15
18
 
16
- it "gets results" do
17
- SimpleDocument.should_receive(:get).with("http://test.local:8983/solr/select", :query => {:q => 'bonanza'}).and_return(httparty)
18
- SimpleDocument.simple_search 'bonanza'
19
+ it "returns one document" do
20
+ SimpleDocument.simple_search('bonanza').css('doc').length.should eq 1
19
21
  end
20
-
21
- it "allows parameters" do
22
- SimpleDocument.should_receive(:get).with("http://test.local:8983/solr/select", :query => {:q => 'bonanza', :fq => "brand_site:www.example.com"}).and_return(httparty)
23
- SimpleDocument.simple_search 'bonanza', :fq => "brand_site:www.example.com"
22
+
23
+ it "returns one simple search result" do
24
+ SimpleDocument.simple_search_docs('bonanza').length.should eq 1
24
25
  end
25
26
 
26
- it "returns parsed response" do
27
- SimpleDocument.simple_search('bonanza').should eq(response)
27
+ it "returns title" do
28
+ SimpleDocument.simple_search_docs('bonanza').first.at_css('str[name=title]').content.should eq "Woezel en Pip"
28
29
  end
29
30
  end
31
+
30
32
  end
@@ -1,6 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe SimpleSolr::Update do
4
+ before do
5
+ SparseDocument.stub(:post) # prevent calls going out over the wire
6
+ end
7
+
4
8
  describe SparseDocument do
5
9
  it "stores just the id field" do
6
10
  SparseDocument.simple_solr_fields.should eq({:id => nil})
@@ -8,6 +12,10 @@ describe SimpleSolr::Update do
8
12
  end
9
13
 
10
14
  describe SimpleDocument do
15
+ before do
16
+ SimpleDocument.stub(:post) # prevent calls going out over the wire
17
+ end
18
+
11
19
  it "provides simple_solr class method" do
12
20
  SimpleDocument.should respond_to(:simple_solr)
13
21
  end
@@ -17,20 +25,24 @@ describe SimpleSolr::Update do
17
25
  end
18
26
 
19
27
  context "save" do
20
- let(:document) { SimpleDocument.create! :title => 'Omg Ponies' }
21
-
28
+ before do
29
+ @document = SimpleDocument.create! :title => 'Omg Ponies'
30
+ end
31
+
22
32
  it "posts to solr" do
23
- SimpleDocument.should_receive(:post).with("http://test.local:8983/solr/update?commit=true", :body => "<add><doc><field name=\"id\">#{document.id}</field><field name=\"title\">Omg Ponies</field></doc></add>")
33
+ SimpleDocument.should_receive(:post).with("http://test.local:8983/solr/update?commit=true", :body => "<add><doc><field name=\"id\">#{@document.id}</field><field name=\"title\">Omg Ponies</field></doc></add>")
34
+ @document.save
24
35
  end
25
36
  end
26
37
 
27
38
  context "destroy" do
28
- let(:document) { SimpleDocument.create! :title => 'Omg Ponies' }
39
+ before do
40
+ @document = SimpleDocument.create! :title => 'Omg Ponies'
41
+ end
29
42
 
30
43
  it "posts to solr" do
31
- SimpleDocument.should_receive(:post).with("http://test.local:8983/solr/update?commit=true", :body => "<add><doc><field name=\"id\">#{document.id}</field><field name=\"title\">Omg Ponies</field></doc></add>")
32
- SimpleDocument.should_receive(:post).with("http://test.local:8983/solr/update?commit=true", :body => "<delete><id>#{document.id}</id></delete>")
33
- document.destroy
44
+ SimpleDocument.should_receive(:post).with("http://test.local:8983/solr/update?commit=true", :body => "<delete><id>#{@document.id}</id></delete>")
45
+ @document.destroy
34
46
  end
35
47
  end
36
48
 
@@ -48,10 +60,14 @@ describe SimpleSolr::Update do
48
60
  end
49
61
 
50
62
  describe FullDocument do
51
- let(:document) { FullDocument.create :title => "Rainbows" }
63
+ before do
64
+ FullDocument.stub(:post) # prevent calls going out over the wire
65
+ @document = FullDocument.create! :title => "Rainbows", :created_at => '2011-08-18 13:32:00'.to_time
66
+ end
52
67
 
53
68
  it "posts to solr after save" do
54
- FullDocument.should_receive(:post).with("http://test.local:8983/solr?commit=true", :body => "<add><doc><field name=\"id\">full-document-#{document.id}</field><field name=\"title\">Rainbows</field><field name=\"date_creation\">#{document.created_at}</field><field name=\"shared\">false</field><field name=\"body\"></field></doc></add>")
69
+ FullDocument.should_receive(:post).with("http://test.local:8983/solr/update?commit=true", :body => "<add><doc><field name=\"id\">full-document-#{@document.id}</field><field name=\"title\">Rainbows</field><field name=\"date_creation\">#{@document.created_at}</field><field name=\"shared\">false</field><field name=\"body\"></field></doc></add>")
70
+ @document.save
55
71
  end
56
72
  end
57
73
  end
@@ -0,0 +1,3 @@
1
+ require 'fakeweb'
2
+
3
+ FakeWeb.allow_net_connect = false
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_solr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-18 00:00:00.000000000Z
12
+ date: 2011-09-29 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &2153333520 !ruby/object:Gem::Requirement
16
+ requirement: &2156008520 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,32 @@ dependencies:
21
21
  version: '2'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2153333520
24
+ version_requirements: *2156008520
25
+ - !ruby/object:Gem::Dependency
26
+ name: fakeweb
27
+ requirement: &2156007520 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2156007520
25
36
  - !ruby/object:Gem::Dependency
26
37
  name: activerecord
27
- requirement: &2153333100 !ruby/object:Gem::Requirement
38
+ requirement: &2156006480 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2156006480
47
+ - !ruby/object:Gem::Dependency
48
+ name: nokogiri
49
+ requirement: &2156005900 !ruby/object:Gem::Requirement
28
50
  none: false
29
51
  requirements:
30
52
  - - ! '>='
@@ -32,10 +54,10 @@ dependencies:
32
54
  version: '0'
33
55
  type: :runtime
34
56
  prerelease: false
35
- version_requirements: *2153333100
57
+ version_requirements: *2156005900
36
58
  - !ruby/object:Gem::Dependency
37
59
  name: httparty
38
- requirement: &2164268940 !ruby/object:Gem::Requirement
60
+ requirement: &2156004760 !ruby/object:Gem::Requirement
39
61
  none: false
40
62
  requirements:
41
63
  - - ! '>='
@@ -43,10 +65,10 @@ dependencies:
43
65
  version: '0'
44
66
  type: :runtime
45
67
  prerelease: false
46
- version_requirements: *2164268940
68
+ version_requirements: *2156004760
47
69
  - !ruby/object:Gem::Dependency
48
70
  name: builder
49
- requirement: &2164268520 !ruby/object:Gem::Requirement
71
+ requirement: &2156003620 !ruby/object:Gem::Requirement
50
72
  none: false
51
73
  requirements:
52
74
  - - ! '>='
@@ -54,7 +76,7 @@ dependencies:
54
76
  version: '0'
55
77
  type: :runtime
56
78
  prerelease: false
57
- version_requirements: *2164268520
79
+ version_requirements: *2156003620
58
80
  description: Solr client for Ruby on Rails with as few features as possible.
59
81
  email:
60
82
  - joost@spacebabies.nl
@@ -80,12 +102,15 @@ files:
80
102
  - spec/config/simple_solr.yml
81
103
  - spec/db/models.rb
82
104
  - spec/db/schema.rb
105
+ - spec/fixtures/apple.xml
106
+ - spec/fixtures/result.xml
83
107
  - spec/simple_solr/configuration_spec.rb
84
108
  - spec/simple_solr/search_spec.rb
85
109
  - spec/simple_solr/update_spec.rb
86
110
  - spec/simple_solr_spec.rb
87
111
  - spec/spec_helper.rb
88
112
  - spec/support/database.rb
113
+ - spec/support/fakeweb.rb
89
114
  - spec/support/rails.rb
90
115
  homepage: https://github.com/tilsammans/simple_solr
91
116
  licenses: []
@@ -116,10 +141,13 @@ test_files:
116
141
  - spec/config/simple_solr.yml
117
142
  - spec/db/models.rb
118
143
  - spec/db/schema.rb
144
+ - spec/fixtures/apple.xml
145
+ - spec/fixtures/result.xml
119
146
  - spec/simple_solr/configuration_spec.rb
120
147
  - spec/simple_solr/search_spec.rb
121
148
  - spec/simple_solr/update_spec.rb
122
149
  - spec/simple_solr_spec.rb
123
150
  - spec/spec_helper.rb
124
151
  - spec/support/database.rb
152
+ - spec/support/fakeweb.rb
125
153
  - spec/support/rails.rb