solrsam 0.4.2

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.
@@ -0,0 +1,195 @@
1
+ module Solrsam
2
+ module Search
3
+ extend ActiveSupport::Concern
4
+ module ClassMethods
5
+
6
+ attr_accessor :solr_server
7
+
8
+ HL_START_TAG = "<mark>"
9
+ HL_END_TAG = "</mark>"
10
+
11
+ def class_name
12
+ to_s.underscore
13
+ end
14
+
15
+ def solr(method = :read)
16
+ @solr_server ||= :default
17
+ Solrsam::Config.instance.rsolr_object(@solr_server, method)
18
+ end
19
+
20
+ def perform_solr_command(method = :read)
21
+ yield(solr(method))
22
+ solr(method).commit
23
+ end
24
+
25
+ def search(search_params={})
26
+ start = search_params[:start] || 0
27
+ rows = search_params[:rows] || 20
28
+
29
+ solr_params = parse_params_for_solr(search_params)
30
+
31
+ begin
32
+ solr_response = solr.select :data => solr_params, :method => :post
33
+ parse_solr_response(solr_response)
34
+ rescue RSolr::Error::Http => e
35
+ {:docs => [],
36
+ :metadata =>
37
+ {:error => {:http_status_code => e.response[:status],
38
+ :http_message_status => RSolr::Error::Http::STATUS_CODES[e.response[:status].to_i],
39
+ :full_message => e.message}}}
40
+ end
41
+ end
42
+
43
+ def parse_params_for_solr(search_params={})
44
+ solr_params = { :echoParams => 'explicit',
45
+ :q => "*:*",
46
+ :facet => "on",
47
+ :'facet.mincount' => 1}.merge(search_params)
48
+
49
+ solr_params[:hl] = true unless search_params[:'hl.fl'].blank?
50
+ solr_params[:fq] = parse_fq(search_params[:fq]) + ( search_params[:untyped] ? [] : ["type:#{class_name}"])
51
+ solr_params
52
+ end
53
+
54
+ def parse_solr_response(solr_response)
55
+ docs = solr_response['response']['docs']
56
+ parsed_facet_counts = parse_facet_counts(solr_response['facet_counts'])
57
+ highlighting = solr_response['highlighting']
58
+ suggestions = solr_response['spellcheck']['suggestions'] rescue {}
59
+
60
+ metadata = {
61
+ :total_count => solr_response['response']['numFound'],
62
+ :start => solr_response['response']['start'],
63
+ :rows => solr_response['responseHeader']['params']['rows'],
64
+ :time => solr_response['responseHeader']['QTime'],
65
+ :status => solr_response['responseHeader']['status'],
66
+ :sort => solr_response['responseHeader']['params']['sort'],
67
+ :debug => solr_response['debug']
68
+ }
69
+ response = {:docs => docs, :metadata => metadata,
70
+ :facet_counts => parsed_facet_counts, :highlighting => highlighting}
71
+ response[:stats] = solr_response['stats'] if solr_response['stats']
72
+ response[:suggestions] = suggestions
73
+
74
+ embed_highlighting(response)
75
+ end
76
+
77
+ def parse_fq(fq)
78
+ return [] if fq.nil?
79
+ if fq.is_a?(Hash)
80
+ fq.map{|k,v| parse_element_in_fq({k => v})}.flatten
81
+ elsif fq.is_a?(Array)
82
+ fq.map{|ele| parse_element_in_fq(ele)}.flatten
83
+ else
84
+ raise "fq must be a hash or array"
85
+ end
86
+ end
87
+
88
+ def parse_element_in_fq(element)
89
+ if element.is_a?(String)
90
+ element
91
+ elsif element.is_a?(Hash)
92
+ element.map do |k,values|
93
+ if values.is_a?(String)
94
+ key_value_query(k,values)
95
+ else
96
+ values.map{|value| key_value_query(k,value) }
97
+ end
98
+ end
99
+ else
100
+ raise "each fq parameter must be a string or hash"
101
+ end
102
+ end
103
+
104
+ def key_value_query(key, value)
105
+ if value.starts_with?("[")
106
+ "#{key}:#{value}"
107
+ elsif value.starts_with?("(")
108
+ # we don't want to escape double quotes
109
+ "#{key}:" + value
110
+ else
111
+ "#{key}:\"#{value}\""
112
+ end
113
+ end
114
+
115
+ def parse_facet_counts(facet_counts)
116
+ return {} unless facet_counts
117
+
118
+ if facet_counts['facet_fields']
119
+ facet_counts['facet_fields'] = facet_counts['facet_fields'].reduce({}) do |acc, facet_collection|
120
+ acc[facet_collection[0]] = map_facet_array_to_facet_hash(facet_collection[1])
121
+ acc
122
+ end
123
+ end
124
+
125
+ if facet_counts['facet_queries']
126
+ facet_counts['facet_queries'] = facet_counts['facet_queries'].group_by{|k,v| k.split(":").first}.reduce({}) do |acc, facet_collection|
127
+ facet_name = facet_collection[0]
128
+ values = facet_collection[1]
129
+
130
+ acc[facet_name] = values.reduce({}) do |inner_acc, tuple|
131
+ range = tuple[0].split(":")[1]
132
+ inner_acc[range] = tuple[1]
133
+ inner_acc
134
+ end
135
+ acc
136
+ end
137
+ end
138
+
139
+ facet_counts
140
+ end
141
+
142
+ # solr facet_fields comes in tuple array format []
143
+ def map_facet_array_to_facet_hash(facet_collection)
144
+ if facet_collection.is_a?(Array)
145
+ facet_collection.each_slice(2).reduce({}){|acc, tuple| acc[tuple[0]] = tuple[1]; acc}
146
+ else
147
+ facet_collection
148
+ end
149
+ end
150
+
151
+ def embed_highlighting(search_response)
152
+ return search_response unless search_response[:highlighting]
153
+
154
+ excluded_highlighting_fields = ['id', 'db_id', 'type']
155
+
156
+ highlighted_docs = search_response[:docs].map do |doc|
157
+ hl_metadata = search_response[:highlighting][doc['id']]
158
+
159
+ hl_metadata.drop_while{|k,v| excluded_highlighting_fields.include?(k) }.each do |k,v|
160
+ new_value = if doc[k].is_a?(Array)
161
+ matched = v.map{|t| t.gsub(HL_START_TAG,"").gsub(HL_END_TAG,"") }
162
+ v.concat(doc[k].drop_while{|text| matched.include?(text) })
163
+ else
164
+ v
165
+ end
166
+ doc[k] = new_value
167
+ end if hl_metadata
168
+
169
+ doc
170
+ end
171
+
172
+ search_response[:docs] = highlighted_docs
173
+
174
+ search_response[:docs].extend RSolr::Pagination::PaginatedDocSet
175
+
176
+ search_response
177
+ end
178
+
179
+ end
180
+ end
181
+ end
182
+
183
+ # namespace test documents
184
+ if defined?(Rails) && Rails.env == "test"
185
+ module Solrsam
186
+ module Search
187
+ extend ActiveSupport::Concern
188
+ module ClassMethods
189
+ def class_name
190
+ "#{to_s.underscore}_test"
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,3 @@
1
+ module Solrsam
2
+ VERSION = "0.4.2"
3
+ end
data/lib/solrsam.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'rsolr'
2
+ require 'active_support/json'
3
+ require 'active_support/concern'
4
+ require 'active_support/core_ext'
5
+
6
+ require 'singleton'
7
+ require 'solrsam/config'
8
+ require 'solrsam/search'
9
+ require 'solrsam/indexer'
10
+
11
+ module Solrsam
12
+ end
@@ -0,0 +1,71 @@
1
+ require 'uri'
2
+ require 'yaml'
3
+ require 'open-uri'
4
+
5
+ namespace :solr do
6
+ env = "development"
7
+ base_dir = File.join(File.dirname(__FILE__), "..", "..")
8
+
9
+ if defined? Rails
10
+ env = Rails.env
11
+ base_dir = Rails.root
12
+ end
13
+
14
+ solr_config = YAML::load( File.open( File.join(base_dir, "config", "solr.yml") ) )
15
+ solr_home = File.join(base_dir, "config", "solr")
16
+ solr_data_dir = solr_config[env]['solr_data_dir']
17
+ solr_server_url = solr_config[env]['solr_server_url']
18
+ java_opts = solr_config[env]['java_opts'] || ""
19
+
20
+ jetty_port = URI.parse(solr_server_url).port
21
+ jetty_path = solr_config[env]['jetty_path']
22
+
23
+ solr_server_dir = "cd #{jetty_path};"
24
+ start_solr_cmd = "java #{java_opts} -jar start.jar"
25
+ logging_xml = "etc/jetty-logging.xml"
26
+ jetty_port_opt = "jetty.port=#{jetty_port}"
27
+ solr_params = "#{jetty_port_opt} -Dsolr.solr.home=#{solr_home} -Dsolr.data.dir=#{solr_data_dir}"
28
+
29
+ desc "Start solr"
30
+ task(:start) do
31
+ # -Dsolr.clustering.enabled=true
32
+ cmd = kill_matching_process_cmd(jetty_port_opt)
33
+ stop_exit_status = run_system_command(cmd)
34
+
35
+ sleep(1)
36
+
37
+ cmd = "#{solr_server_dir} #{start_solr_cmd} #{logging_xml} #{solr_params} &"
38
+ run_system_command(cmd)
39
+ end
40
+
41
+ desc "Stop solr"
42
+ task(:stop) do
43
+ cmd = kill_matching_process_cmd(jetty_port_opt)
44
+ run_system_command(cmd)
45
+ end
46
+
47
+ desc "update spelling dictionary"
48
+ task :build_dictionary do
49
+ open("#{solr_server_url}/select?q=facebok&qt=spell&spellcheck.build=true")
50
+ end
51
+
52
+ def run_system_command(cmd)
53
+ puts cmd
54
+ status = system(cmd)
55
+ $?.exitstatus
56
+ end
57
+
58
+ def kill_matching_process_cmd(process_name)
59
+ cmd = "echo `ps -ef | grep -v grep | grep \"#{process_name.gsub("-", "\\-")}\" | awk '{print $2}'` | xargs kill"
60
+ end
61
+
62
+ # #example of a task to index all items
63
+ # desc "index food"
64
+ # task(:import_foods, :needs => :environment) do
65
+ # FoodDescription.find_in_batches do |batch|
66
+ # FoodIndexer.index(batch)
67
+ # puts "Done with batch of size: #{batch.size}"
68
+ # end
69
+ # end
70
+ end
71
+
data/solrsam.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "solrsam/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "solrsam"
7
+ s.version = Solrsam::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Tommy Chheng", "Sam Dalton"]
10
+ s.email = ["tommy.chheng@gmail.com", "sam@quid.com"]
11
+ s.homepage = "http://github.com/samdalton/solrsan"
12
+ s.summary = %q{Lightweight wrapper for using Apache Solr within a Ruby application including Rails and Sinatra.}
13
+ s.description = %q{solrsan is a lightweight wrapper for using Apache Solr within a Ruby application including Rails and Sinatra.}
14
+
15
+ s.rubyforge_project = "solrsam"
16
+
17
+ s.add_dependency 'activesupport'
18
+ s.add_dependency 'activemodel'
19
+ s.add_dependency 'rsolr', '1.0.0'
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,11 @@
1
+ require 'active_model/attribute_methods'
2
+
3
+ class Document
4
+ include ActiveModel::AttributeMethods
5
+ include Solrsam::Search
6
+ attr_accessor :attributes
7
+
8
+ def initialize(attributes={})
9
+ @attributes = attributes
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module SearchTestHelper
2
+ def document_mock
3
+ doc = Document.new({:id => 500,
4
+ :title => "Solr test document",
5
+ :author => "Tommy Chheng",
6
+ :content => "ruby scala search",
7
+ :review_count => 4,
8
+ :scores => [1,2,3,4],
9
+ :created_at => Date.parse("Dec 10 2010")})
10
+ doc
11
+ end
12
+ end
13
+
@@ -0,0 +1,27 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+
4
+ MODELS = File.join(File.dirname(__FILE__), "models")
5
+ $LOAD_PATH.unshift(MODELS)
6
+
7
+ #simulate rails env
8
+ class Rails
9
+ def self.env
10
+ "test"
11
+ end
12
+ end
13
+
14
+ require "rubygems"
15
+ require "test/unit"
16
+ require 'solrsam'
17
+
18
+ #test models
19
+ require 'document'
20
+
21
+ solr_config = YAML::load( File.open( File.join(File.dirname(__FILE__), "..", "config", "solr.yml") ) )
22
+ solr_server_url = solr_config["test"]['solr_server_url']
23
+
24
+ Solrsam::Config.instance.add_server(:example, 'example.com', :read)
25
+ Solrsam::Config.instance.add_server(:example, 'example.com', :write)
26
+ Solrsam::Config.instance.add_server(:default, solr_server_url, :read)
27
+ Solrsam::Config.instance.add_server(:default, solr_server_url, :write)
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+ require 'search_test_helper'
3
+
4
+ class IndexerTest < Test::Unit::TestCase
5
+ include SearchTestHelper
6
+
7
+ def setup
8
+ @document = document_mock
9
+ end
10
+
11
+ def teardown
12
+ end
13
+
14
+ def test_indexed_fields
15
+ created_doc = @document.indexed_fields
16
+ assert_equal @document.attributes[:id], created_doc[:db_id]
17
+ assert_equal @document.attributes[:title], created_doc[:title]
18
+ assert_equal @document.attributes[:author], created_doc[:author]
19
+ assert_equal @document.attributes[:content], created_doc[:content]
20
+ assert_equal @document.attributes[:review_count], created_doc[:review_count]
21
+ assert_equal @document.attributes[:scores], created_doc[:scores]
22
+ assert_equal @document.attributes[:created_at].to_time.utc.xmlschema, created_doc[:created_at]
23
+ end
24
+
25
+ end
@@ -0,0 +1,251 @@
1
+ require 'test_helper'
2
+ require 'search_test_helper'
3
+
4
+ class SearchTest < Test::Unit::TestCase
5
+ include SearchTestHelper
6
+
7
+ def setup
8
+ Document.destroy_all_index_documents!
9
+ @document = document_mock
10
+ end
11
+
12
+ def teardown
13
+ Document.destroy_all_index_documents!
14
+ end
15
+
16
+ def test_simple_query
17
+ Document.index(@document)
18
+ q = @document.attributes[:title]
19
+
20
+ response = Document.search(:q => q)
21
+ metadata = response[:metadata]
22
+ docs = response[:docs]
23
+ assert metadata[:total_count] > 0
24
+ end
25
+
26
+ def test_sort
27
+ Document.index(Document.new(:id => 3, :title => "solar city",:review_count => 10))
28
+ Document.index(Document.new(:id => 4, :title => "city solar", :review_count => 5))
29
+
30
+ q = "solar"
31
+ response = Document.search(:q => q, :sort => "review_count asc")
32
+ docs = response[:docs]
33
+
34
+ assert_not_nil docs[0], "Not enough docs for #{q} to test."
35
+ first_result_name = docs[0][:title]
36
+ assert_not_nil docs[1], "Not enough docs for #{q} to test."
37
+ second_result_name = docs[1][:title]
38
+
39
+ assert_equal [second_result_name, first_result_name].sort, [first_result_name, second_result_name]
40
+
41
+ response = Document.search(:q => q, :sort => "review_count desc")
42
+ docs = response[:docs]
43
+
44
+ assert_not_nil docs[0], "Not enough docs for #{q} to test."
45
+ first_result_name = docs[0][:title]
46
+ assert_not_nil docs[1], "Not enough docs for #{q} to test."
47
+ second_result_name = docs[1][:title]
48
+
49
+ assert_equal [second_result_name, first_result_name].sort.reverse, [first_result_name, second_result_name]
50
+ end
51
+
52
+ def test_invalid_query_should_return_error_message_in_metadata
53
+ response = Document.search(:q => "http://tommy.chheng.com")
54
+ docs = response[:docs]
55
+ metadata = response[:metadata]
56
+
57
+ assert_not_nil response[:metadata][:error]
58
+ assert_equal 400, response[:metadata][:error][:http_status_code]
59
+ end
60
+
61
+ def test_parse_facet_fields
62
+ facet_counts = {'facet_queries'=>{},
63
+ 'facet_fields' => {'language' => ["Scala", 2, "Ruby", 1, "Java", 0]},
64
+ 'facet_dates'=>{}}
65
+
66
+ facet_counts = Document.parse_facet_counts(facet_counts)
67
+
68
+ assert_equal ["Scala", "Ruby", "Java"], facet_counts['facet_fields']['language'].keys
69
+ end
70
+
71
+ def test_parse_facet_queries
72
+ facet_counts = {"facet_queries"=>{"funding:[0 TO 5000000]"=>1, "funding:[10000000 TO 50000000]"=>0}, "facet_fields"=>{}, "facet_dates"=>{}}
73
+
74
+ facet_counts = Document.parse_facet_counts(facet_counts)
75
+
76
+ expected = {"funding"=>{"[0 TO 5000000]"=>1, "[10000000 TO 50000000]"=>0}}
77
+ assert_equal expected, facet_counts['facet_queries']
78
+ end
79
+
80
+ def test_parse_fq_with_hash
81
+ params = {:fq => {:tags => ["ruby", "scala"]}}
82
+ filters = Document.parse_fq(params[:fq])
83
+
84
+ expected = ["tags:\"ruby\"", "tags:\"scala\""]
85
+ assert_equal expected, filters
86
+ end
87
+
88
+ def test_parse_fq_with_hash_multiple_entries
89
+ params = {:fq => {:tags => ["ruby", "scala"], :author => "Bert"}}
90
+ filters = Document.parse_fq(params[:fq])
91
+
92
+ expected = ["tags:\"ruby\"", "tags:\"scala\"", "author:\"Bert\""]
93
+ assert_equal expected, filters
94
+ end
95
+
96
+ def test_parse_fq_with_hash_array_args
97
+ params = {:fq => [{:tags => ["ruby", "scala"]}]}
98
+ filters = Document.parse_fq(params[:fq])
99
+
100
+ expected = ["tags:\"ruby\"", "tags:\"scala\""]
101
+ assert_equal expected, filters
102
+ end
103
+
104
+ def test_parse_fq_with_hash_string_args
105
+ params = {:fq => [{:tags => "ruby"}]}
106
+ filters = Document.parse_fq(params[:fq])
107
+
108
+ expected = ["tags:\"ruby\""]
109
+ assert_equal expected, filters
110
+ end
111
+
112
+ def test_parse_fq_with_string_args
113
+ params = {:fq => ["tags:ruby"]}
114
+ filters = Document.parse_fq(params[:fq])
115
+
116
+ expected = ["tags:ruby"]
117
+ assert_equal expected, filters
118
+ end
119
+
120
+ def test_parse_fq_with_empty
121
+ filters = Document.parse_fq([])
122
+ expected = []
123
+ assert_equal expected, filters
124
+ end
125
+
126
+
127
+ def test_filter_query_mulitple_filters
128
+ Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10, :tags => ['ruby']))
129
+ Document.index(Document.new(:id => 4, :author => "Ernie", :title => "lucene solr", :review_count => 5, :tags => ['ruby', 'scala']))
130
+
131
+ response = Document.search(:q => "solr", :fq => {:tags => ["scala"], :author => "Ernie"})
132
+ docs = response[:docs]
133
+ metadata = response[:metadata]
134
+
135
+ assert_equal 1, metadata[:total_count]
136
+
137
+ doc = docs.first
138
+ assert_not_nil doc['tags']
139
+ assert doc['tags'].include?("scala")
140
+ end
141
+
142
+ def test_filter_query
143
+ Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10, :tags => ['ruby']))
144
+ Document.index(Document.new(:id => 4, :author => "Ernie", :title => "lucene solr", :review_count => 5, :tags => ['ruby', 'scala']))
145
+
146
+ response = Document.search(:q => "solr", :fq => [{:tags => ["scala"]}])
147
+ docs = response[:docs]
148
+ metadata = response[:metadata]
149
+
150
+ assert_equal 1, metadata[:total_count]
151
+
152
+ doc = docs.first
153
+ assert_not_nil doc['tags']
154
+ assert doc['tags'].include?("scala")
155
+ end
156
+
157
+ def test_text_faceting
158
+ Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10))
159
+ Document.index(Document.new(:id => 4, :author => "Ernie", :title => "lucene solr", :review_count => 5))
160
+
161
+ response = Document.search(:q => "solr", :'facet.field' => ['author'])
162
+ docs = response[:docs]
163
+ facet_counts = response[:facet_counts]
164
+ assert_not_nil facet_counts["facet_fields"]["author"]
165
+
166
+ author_facet_entries = facet_counts["facet_fields"]["author"]
167
+ assert author_facet_entries.keys.include?("Bert") && author_facet_entries.keys.include?("Ernie")
168
+ end
169
+
170
+ def test_range_faceting
171
+ Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10))
172
+ Document.index(Document.new(:id => 4, :author => "Ernie", :title => "lucene solr", :review_count => 5))
173
+
174
+ response = Document.search(:q => "solr", :'facet.field' => ['author'], :'facet.query' => ["review_count:[1 TO 5]", "review_count:[6 TO 10]"])
175
+ docs = response[:docs]
176
+ facet_counts = response[:facet_counts]
177
+
178
+ assert_not_nil facet_counts["facet_fields"]["author"]
179
+ assert_not_nil facet_counts["facet_queries"]["review_count"]
180
+ assert_equal({"[1 TO 5]"=>1, "[6 TO 10]"=>1}, facet_counts["facet_queries"]["review_count"])
181
+ end
182
+
183
+ def test_highlighting_support
184
+ Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10, :tags => ["solr"]))
185
+
186
+ response = Document.search(:q => "solr",
187
+ :'hl.fl' => "*")
188
+ docs = response[:docs]
189
+ highlighting = response[:highlighting]
190
+
191
+ first_result = highlighting.first
192
+ assert first_result[1]['tags'].include?("<mark>solr</mark>")
193
+ end
194
+
195
+ def test_embed_highlighting
196
+ Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10, :tags => ["solr", "sphinx"]))
197
+
198
+ response = Document.search(:q => "solr",
199
+ :'hl.fl' => "*")
200
+ docs = response[:docs]
201
+ assert_equal ["<mark>solr</mark>","sphinx"], docs.first['tags']
202
+ end
203
+
204
+ def test_debug_response
205
+ Document.index(@document)
206
+ q = @document.attributes[:title]
207
+
208
+ response = Document.search({:q => q, :debugQuery => true})
209
+ metadata = response[:metadata]
210
+ assert_not_nil metadata[:debug]
211
+ end
212
+
213
+ def test_stats_response
214
+ Document.index(@document)
215
+ q = @document.attributes[:title]
216
+
217
+ response = Document.search({:q => q, :stats => true, :'stats.field' => 'review_count'})
218
+ assert_not_nil response[:stats]
219
+ assert_equal 1, response[:stats]['stats_fields']['review_count']['count']
220
+ end
221
+
222
+ def test_will_paginate_support
223
+ Document.index(Document.new(:id => 3, :author => "Bert", :title => "solr lucene",:review_count => 10))
224
+ Document.index(Document.new(:id => 4, :author => "Ernie", :title => "lucene solr", :review_count => 5))
225
+
226
+ response = Document.search(:q => "solr")
227
+ docs = response[:docs]
228
+ assert_not_nil docs.start
229
+ assert_not_nil docs.per_page
230
+ assert_not_nil docs.current_page
231
+ end
232
+
233
+ def test_solr_server_attribute_writable
234
+ begin
235
+ Document.solr_server = :example
236
+ assert_equal :example, Document.solr_server
237
+ ensure
238
+ Document.solr_server = nil
239
+ end
240
+ end
241
+
242
+ def test_rsolr_is_configured_with_the_set_solr_server
243
+ begin
244
+ Document.solr_server = :example
245
+ assert_equal "example.com/", Document.solr.options[:url]
246
+ ensure
247
+ Document.solr_server = nil
248
+ end
249
+ end
250
+ end
251
+