jbasdf-muck-solr 0.4.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.
Files changed (156) hide show
  1. data/CHANGE_LOG +239 -0
  2. data/LICENSE +19 -0
  3. data/README.markdown +118 -0
  4. data/README.rdoc +107 -0
  5. data/Rakefile +99 -0
  6. data/TESTING_THE_PLUGIN +25 -0
  7. data/VERSION.yml +4 -0
  8. data/config/solr.yml +15 -0
  9. data/config/solr_environment.rb +32 -0
  10. data/lib/acts_as_solr/acts_methods.rb +352 -0
  11. data/lib/acts_as_solr/class_methods.rb +236 -0
  12. data/lib/acts_as_solr/common_methods.rb +89 -0
  13. data/lib/acts_as_solr/deprecation.rb +61 -0
  14. data/lib/acts_as_solr/instance_methods.rb +165 -0
  15. data/lib/acts_as_solr/lazy_document.rb +18 -0
  16. data/lib/acts_as_solr/parser_methods.rb +203 -0
  17. data/lib/acts_as_solr/search_results.rb +68 -0
  18. data/lib/acts_as_solr/solr_fixtures.rb +13 -0
  19. data/lib/acts_as_solr/tasks/database.rake +16 -0
  20. data/lib/acts_as_solr/tasks/solr.rake +135 -0
  21. data/lib/acts_as_solr/tasks/test.rake +5 -0
  22. data/lib/acts_as_solr/tasks.rb +10 -0
  23. data/lib/acts_as_solr.rb +65 -0
  24. data/lib/solr/connection.rb +177 -0
  25. data/lib/solr/document.rb +75 -0
  26. data/lib/solr/exception.rb +13 -0
  27. data/lib/solr/field.rb +36 -0
  28. data/lib/solr/importer/array_mapper.rb +26 -0
  29. data/lib/solr/importer/delimited_file_source.rb +38 -0
  30. data/lib/solr/importer/hpricot_mapper.rb +27 -0
  31. data/lib/solr/importer/mapper.rb +51 -0
  32. data/lib/solr/importer/solr_source.rb +41 -0
  33. data/lib/solr/importer/xpath_mapper.rb +35 -0
  34. data/lib/solr/importer.rb +19 -0
  35. data/lib/solr/indexer.rb +52 -0
  36. data/lib/solr/request/add_document.rb +58 -0
  37. data/lib/solr/request/base.rb +36 -0
  38. data/lib/solr/request/commit.rb +29 -0
  39. data/lib/solr/request/delete.rb +48 -0
  40. data/lib/solr/request/dismax.rb +46 -0
  41. data/lib/solr/request/index_info.rb +22 -0
  42. data/lib/solr/request/modify_document.rb +46 -0
  43. data/lib/solr/request/optimize.rb +19 -0
  44. data/lib/solr/request/ping.rb +36 -0
  45. data/lib/solr/request/select.rb +54 -0
  46. data/lib/solr/request/spellcheck.rb +30 -0
  47. data/lib/solr/request/standard.rb +402 -0
  48. data/lib/solr/request/update.rb +23 -0
  49. data/lib/solr/request.rb +26 -0
  50. data/lib/solr/response/add_document.rb +17 -0
  51. data/lib/solr/response/base.rb +42 -0
  52. data/lib/solr/response/commit.rb +15 -0
  53. data/lib/solr/response/delete.rb +13 -0
  54. data/lib/solr/response/dismax.rb +8 -0
  55. data/lib/solr/response/index_info.rb +26 -0
  56. data/lib/solr/response/modify_document.rb +17 -0
  57. data/lib/solr/response/optimize.rb +14 -0
  58. data/lib/solr/response/ping.rb +26 -0
  59. data/lib/solr/response/ruby.rb +42 -0
  60. data/lib/solr/response/select.rb +17 -0
  61. data/lib/solr/response/spellcheck.rb +20 -0
  62. data/lib/solr/response/standard.rb +60 -0
  63. data/lib/solr/response/xml.rb +39 -0
  64. data/lib/solr/response.rb +27 -0
  65. data/lib/solr/solrtasks.rb +27 -0
  66. data/lib/solr/util.rb +32 -0
  67. data/lib/solr/xml.rb +44 -0
  68. data/lib/solr.rb +26 -0
  69. data/solr/CHANGES.txt +1207 -0
  70. data/solr/LICENSE.txt +712 -0
  71. data/solr/NOTICE.txt +90 -0
  72. data/solr/etc/jetty.xml +205 -0
  73. data/solr/etc/webdefault.xml +379 -0
  74. data/solr/lib/easymock.jar +0 -0
  75. data/solr/lib/jetty-6.1.3.jar +0 -0
  76. data/solr/lib/jetty-util-6.1.3.jar +0 -0
  77. data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
  78. data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
  79. data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
  80. data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
  81. data/solr/lib/servlet-api-2.4.jar +0 -0
  82. data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
  83. data/solr/lib/xpp3-1.1.3.4.O.jar +0 -0
  84. data/solr/solr/README.txt +52 -0
  85. data/solr/solr/bin/abc +176 -0
  86. data/solr/solr/bin/abo +176 -0
  87. data/solr/solr/bin/backup +108 -0
  88. data/solr/solr/bin/backupcleaner +142 -0
  89. data/solr/solr/bin/commit +128 -0
  90. data/solr/solr/bin/optimize +129 -0
  91. data/solr/solr/bin/readercycle +129 -0
  92. data/solr/solr/bin/rsyncd-disable +77 -0
  93. data/solr/solr/bin/rsyncd-enable +76 -0
  94. data/solr/solr/bin/rsyncd-start +145 -0
  95. data/solr/solr/bin/rsyncd-stop +105 -0
  96. data/solr/solr/bin/scripts-util +83 -0
  97. data/solr/solr/bin/snapcleaner +148 -0
  98. data/solr/solr/bin/snapinstaller +168 -0
  99. data/solr/solr/bin/snappuller +248 -0
  100. data/solr/solr/bin/snappuller-disable +77 -0
  101. data/solr/solr/bin/snappuller-enable +77 -0
  102. data/solr/solr/bin/snapshooter +109 -0
  103. data/solr/solr/conf/admin-extra.html +31 -0
  104. data/solr/solr/conf/protwords.txt +21 -0
  105. data/solr/solr/conf/schema.xml +126 -0
  106. data/solr/solr/conf/scripts.conf +24 -0
  107. data/solr/solr/conf/solrconfig.xml +458 -0
  108. data/solr/solr/conf/stopwords.txt +57 -0
  109. data/solr/solr/conf/synonyms.txt +31 -0
  110. data/solr/solr/conf/xslt/example.xsl +132 -0
  111. data/solr/solr/conf/xslt/example_atom.xsl +63 -0
  112. data/solr/solr/conf/xslt/example_rss.xsl +62 -0
  113. data/solr/start.jar +0 -0
  114. data/solr/webapps/solr.war +0 -0
  115. data/test/config/solr.yml +2 -0
  116. data/test/db/connections/mysql/connection.rb +10 -0
  117. data/test/db/connections/sqlite/connection.rb +8 -0
  118. data/test/db/migrate/001_create_books.rb +15 -0
  119. data/test/db/migrate/002_create_movies.rb +12 -0
  120. data/test/db/migrate/003_create_categories.rb +11 -0
  121. data/test/db/migrate/004_create_electronics.rb +16 -0
  122. data/test/db/migrate/005_create_authors.rb +12 -0
  123. data/test/db/migrate/006_create_postings.rb +9 -0
  124. data/test/db/migrate/007_create_posts.rb +13 -0
  125. data/test/db/migrate/008_create_gadgets.rb +11 -0
  126. data/test/fixtures/authors.yml +9 -0
  127. data/test/fixtures/books.yml +13 -0
  128. data/test/fixtures/categories.yml +7 -0
  129. data/test/fixtures/db_definitions/mysql.sql +41 -0
  130. data/test/fixtures/electronics.yml +49 -0
  131. data/test/fixtures/movies.yml +9 -0
  132. data/test/fixtures/postings.yml +10 -0
  133. data/test/functional/acts_as_solr_test.rb +413 -0
  134. data/test/functional/association_indexing_test.rb +37 -0
  135. data/test/functional/faceted_search_test.rb +163 -0
  136. data/test/functional/multi_solr_search_test.rb +57 -0
  137. data/test/models/author.rb +10 -0
  138. data/test/models/book.rb +10 -0
  139. data/test/models/category.rb +8 -0
  140. data/test/models/electronic.rb +25 -0
  141. data/test/models/gadget.rb +9 -0
  142. data/test/models/movie.rb +17 -0
  143. data/test/models/novel.rb +2 -0
  144. data/test/models/post.rb +3 -0
  145. data/test/models/posting.rb +11 -0
  146. data/test/test_helper.rb +54 -0
  147. data/test/unit/acts_methods_shoulda.rb +68 -0
  148. data/test/unit/class_methods_shoulda.rb +85 -0
  149. data/test/unit/common_methods_shoulda.rb +111 -0
  150. data/test/unit/instance_methods_shoulda.rb +318 -0
  151. data/test/unit/lazy_document_shoulda.rb +34 -0
  152. data/test/unit/parser_instance.rb +19 -0
  153. data/test/unit/parser_methods_shoulda.rb +268 -0
  154. data/test/unit/solr_instance.rb +49 -0
  155. data/test/unit/test_helper.rb +24 -0
  156. metadata +241 -0
@@ -0,0 +1,318 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/test_helper")
2
+ module Solr; end
3
+
4
+ class InstanceMethodsTest < Test::Unit::TestCase
5
+
6
+ context "With a Solr record instance" do
7
+ setup do
8
+ @instance = SolrInstance.new
9
+ end
10
+
11
+ context "when checking whether indexing is disabled" do
12
+
13
+ setup do
14
+ @instance.configuration = {:if => true}
15
+ end
16
+
17
+ should "return true if the specified proc returns true " do
18
+ @instance.configuration[:offline] = proc {|record| true}
19
+ assert @instance.indexing_disabled?
20
+ end
21
+
22
+ should "return false if the specified proc returns false" do
23
+ @instance.configuration[:offline] = proc {|record| false}
24
+ assert !@instance.indexing_disabled?
25
+ end
26
+
27
+ should "return true if no valid offline option was specified" do
28
+ @instance.configuration[:offline] = nil
29
+ @instance.configuration[:if] = proc {true}
30
+ assert !@instance.indexing_disabled?
31
+ end
32
+ end
33
+
34
+ context "when validating the boost" do
35
+ setup do
36
+ @instance.solr_configuration = {:default_boost => 10.0}
37
+ @instance.configuration = {:if => true}
38
+ end
39
+
40
+ should "accept and evaluate a block" do
41
+ @instance.configuration[:boost] = proc {|record| record.boost_rate}
42
+ assert_equal 10.0, @instance.send(:validate_boost, @instance.configuration[:boost])
43
+ end
44
+
45
+ should "accept and return a float" do
46
+ @instance.configuration[:boost] = 9.0
47
+ assert_equal 9.0, @instance.send(:validate_boost, @instance.configuration[:boost])
48
+ end
49
+
50
+ should "return the default float when the specified is negative" do
51
+ @instance.configuration[:boost] = -1.0
52
+ assert_equal 10.0, @instance.send(:validate_boost, @instance.configuration[:boost])
53
+ end
54
+
55
+ should "execute the according method when value is a symbol" do
56
+ @instance.configuration[:boost] = :irate
57
+ assert_equal 8.0, @instance.send(:validate_boost, @instance.configuration[:boost])
58
+ end
59
+
60
+ should "return the default boost when there is no valid boost" do
61
+ @instance.configuration[:boost] = "boost!"
62
+ assert_equal 10.0, @instance.send(:validate_boost, @instance.configuration[:boost])
63
+ end
64
+ end
65
+
66
+ context "when determining the solr document id" do
67
+ should "combine class name and id" do
68
+ assert_equal "SolrInstance:10", @instance.solr_id
69
+ end
70
+ end
71
+
72
+ context "when saving the instance to solr" do
73
+ context "with indexing disabled" do
74
+ setup do
75
+ @instance.configuration = {:fields => [:name], :if => nil}
76
+ end
77
+
78
+ should "just return and do nothing" do
79
+ @instance.expects(:solr_add).never
80
+ @instance.expects(:solr_destroy).never
81
+ assert @instance.solr_save
82
+ end
83
+ end
84
+
85
+ context "with indexing enabled" do
86
+ setup do
87
+ @instance.configuration = {:fields => [:name], :if => "true", :auto_commit => true}
88
+ @instance.stubs(:solr_commit)
89
+ @instance.stubs(:solr_add)
90
+ @instance.stubs(:to_solr_doc).returns("My test document")
91
+ end
92
+
93
+ should "add the solr document" do
94
+ @instance.expects(:solr_add).with("My test document").once
95
+ @instance.solr_save
96
+ end
97
+
98
+ should "commit to solr" do
99
+ @instance.expects(:solr_commit).once
100
+ @instance.solr_save
101
+ end
102
+
103
+ should "not commit if auto_commit is disabled" do
104
+ @instance.configuration.merge!(:auto_commit => false)
105
+ @instance.expects(:solr_commit).never
106
+ @instance.solr_save
107
+ end
108
+
109
+ should "destroy the document if :if clause is false" do
110
+ @instance.configuration.merge!(:if => "false")
111
+ @instance.expects(:solr_destroy).once
112
+ @instance.solr_save
113
+ end
114
+ end
115
+ end
116
+
117
+ context "when destroying an instance in solr" do
118
+ setup do
119
+ @instance.configuration = {:if => true, :auto_commit => true}
120
+ @instance.stubs(:solr_commit)
121
+ @instance.stubs(:solr_delete)
122
+ end
123
+
124
+ should "delete the instance" do
125
+ @instance.expects(:solr_delete).with("SolrInstance:10")
126
+ @instance.solr_destroy
127
+ end
128
+
129
+ should "commit to solr" do
130
+ @instance.expects(:solr_commit)
131
+ @instance.solr_destroy
132
+ end
133
+
134
+ should "not commit if auto_commit is disabled" do
135
+ @instance.configuration.merge!(:auto_commit => false)
136
+ @instance.expects(:solr_commit).never
137
+ @instance.solr_destroy
138
+ end
139
+
140
+ context "with indexing disabled" do
141
+ should "not contact solr" do
142
+ @instance.configuration.merge!(:offline => true, :if => nil)
143
+ @instance.expects(:solr_delete).never
144
+ @instance.solr_destroy
145
+ end
146
+ end
147
+ end
148
+
149
+ context "when converting an instance to a solr document" do
150
+ setup do
151
+ @instance.configuration = {:if => true, :auto_commit => true, :solr_fields => {:name => {:boost => 9.0}}, :boost => 10.0}
152
+ @instance.solr_configuration = {:type_field => "type", :primary_key_field => "pk_id", :default_boost => 25.0}
153
+ end
154
+
155
+ should "add a document boost" do
156
+ assert_equal 10, @instance.to_solr_doc.boost
157
+ end
158
+
159
+ should "set the solr id" do
160
+ assert_equal "SolrInstance:10", @instance.to_solr_doc[:id]
161
+ end
162
+
163
+ should "set the type field" do
164
+ assert_equal "SolrInstance", @instance.to_solr_doc[:type]
165
+ end
166
+
167
+ should "set the primary key fields" do
168
+ assert_equal("10", @instance.to_solr_doc[:pk_id])
169
+ end
170
+
171
+ should "add the includes if they were configured" do
172
+ @instance.configuration.merge! :include => [:author]
173
+ @instance.expects(:add_includes)
174
+ @instance.to_solr_doc
175
+ end
176
+
177
+ context "with indexed fields" do
178
+ should "add fields with type" do
179
+ assert_equal "Chunky bacon!", @instance.to_solr_doc[:name_s]
180
+ end
181
+
182
+ should "add the field boost" do
183
+ field = @instance.to_solr_doc.fields.find {|f| f.name.to_s == "name_s"}
184
+ assert_equal 9.0, field.boost
185
+ end
186
+
187
+ should "set the default boost for the field, if none is configured" do
188
+ @instance.configuration[:solr_fields][:name][:boost] = nil
189
+ field = @instance.to_solr_doc.fields.find {|f| f.name.to_s == "name_s"}
190
+ assert_equal 25.0, field.boost
191
+ end
192
+
193
+ should "not overwrite the type or id field" do
194
+ @instance.configuration[:solr_fields] = {:type => {}, :id => {}}
195
+ doc = @instance.to_solr_doc
196
+ assert_not_equal "humbug", doc[:type]
197
+ assert_not_equal "bogus", doc[:id]
198
+ end
199
+
200
+ should "set the default value if field value is nil" do
201
+ @instance.name = nil
202
+ @instance.expects(:set_value_if_nil).with('s')
203
+ @instance.to_solr_doc
204
+ end
205
+
206
+ should "not include nil values" do
207
+ @instance.name = ""
208
+ @instance.stubs(:set_value_if_nil).returns ""
209
+ assert_nil @instance.to_solr_doc[:name_s]
210
+ end
211
+
212
+ should "escape the contents" do
213
+ @instance.name = "<script>malicious()</script>"
214
+ assert_equal "&lt;script&gt;malicious()&lt;/script&gt;", @instance.to_solr_doc[:name_s]
215
+ end
216
+
217
+ should "use an alternate field name if specified in options" do
218
+ @instance.stubs(:nickname_for_solr).returns('Nick')
219
+ @instance.configuration[:solr_fields].merge! :nickname => {:as => :alias}
220
+ doc = @instance.to_solr_doc
221
+ assert_not_nil @instance.to_solr_doc.fields.find {|f| f.name.to_s == "alias_s"}
222
+ assert_nil @instance.to_solr_doc.fields.find {|f| f.name.to_s == "nickname_s"}
223
+ end
224
+
225
+ context "when associations are included" do
226
+ setup do
227
+ class AssocLabel < String
228
+ @@singular = {'people' => 'person'}
229
+ def to_s
230
+ self
231
+ end
232
+ def singularize
233
+ @@singular[self]
234
+ end
235
+ end
236
+ @assoc = AssocLabel.new('people')
237
+ person = {:name => 'Hank Venture', :address => 'Venture Compound'}
238
+ @people = [OpenStruct.new(person.merge(:attributes => person))]
239
+ @instance.stubs(:people).returns(@people)
240
+ @reflection = OpenStruct.new(:macro => :has_many)
241
+ @instance.class.stubs(:reflect_on_association).returns(@reflection)
242
+ @instance.configuration[:solr_includes] = {@assoc => {}}
243
+ @instance.solr_configuration.merge! :default_boost => 35.0
244
+ end
245
+
246
+ should "set the default name for the include, if none is configured" do
247
+ @instance.configuration[:solr_includes] = {@assoc => {:type => :text}}
248
+ doc = @instance.to_solr_doc
249
+ assert_not_nil doc.fields.find {|f| f.name.to_s == "person_s"}
250
+ end
251
+
252
+ should "add the include alias" do
253
+ @instance.configuration[:solr_includes] = {@assoc => {:as => :human, :type => :text}}
254
+ doc = @instance.to_solr_doc
255
+ assert_not_nil doc.fields.find {|f| f.name.to_s == "human_s"}
256
+ assert_nil doc.fields.find {|f| f.name.to_s == "person_s"}
257
+ end
258
+
259
+ should "add the include type" do
260
+ @instance.configuration[:solr_includes] = {@assoc => {:type => :date}}
261
+ @instance.expects(:get_solr_field_type).with(){|v| true}.at_least_once.returns('s')
262
+ @instance.expects(:get_solr_field_type).with(:date).once.returns('d')
263
+ doc = @instance.to_solr_doc
264
+ end
265
+
266
+ should "set the default boost for the include, if none is configured" do
267
+ # @instance.configuration[:solr_includes] = {@assoc => {}}
268
+ field = @instance.to_solr_doc.fields.find {|f| f.name.to_s == "person_s"}
269
+ assert_equal 35.0, field.boost
270
+ end
271
+
272
+ should "add the include boost" do
273
+ @instance.configuration[:solr_includes] = {@assoc => {:boost => 10.0}}
274
+ field = @instance.to_solr_doc.fields.find {|f| f.name.to_s == "person_s"}
275
+ assert_equal 10.0, field.boost
276
+ end
277
+
278
+ should "default to a field value with all association attributes" do
279
+ # @instance.configuration[:solr_includes] = {@assoc => {}}
280
+ field = @instance.to_solr_doc.fields.find {|f| f.name.to_s == "person_s"}
281
+ @people.first.attributes.each do |attr, value|
282
+ assert_match /#{attr}=#{value}/, field.value
283
+ end
284
+ end
285
+
286
+ should "use a field value from an association method, if one is configured" do
287
+ @instance.configuration[:solr_includes] = {@assoc => {:using => :name}}
288
+ field = @instance.to_solr_doc.fields.find {|f| f.name.to_s == "person_s"}
289
+ assert_equal @people.first.name, field.value
290
+ end
291
+
292
+ should "use a field value from a proc, if one is configured" do
293
+ @instance.configuration[:solr_includes] = {@assoc => {:using => lambda{|r| r.name.reverse}}}
294
+ field = @instance.to_solr_doc.fields.find {|f| f.name.to_s == "person_s"}
295
+ assert_equal @people.first.name.reverse, field.value
296
+ end
297
+
298
+ should "join multiple values into a single field unless the :multivalued options is specified" do
299
+ @instance.configuration[:solr_includes] = {@assoc => {:multivalued => :true}}
300
+ second_person = {:name => 'Dean Venture', :address => 'Venture Compound'}
301
+ @people << OpenStruct.new(second_person.merge(:attributes => second_person))
302
+ fields = @instance.to_solr_doc.fields.select {|f| f.name.to_s == "person_s"}
303
+ assert_equal @people.size, fields.size
304
+ end
305
+
306
+ should "include multiple values separately if the :multivalued options is specified" do
307
+ # @instance.configuration[:solr_includes] = {@assoc => {}}
308
+ second_person = {:name => 'Dean Venture', :address => 'Venture Compound'}
309
+ @people << OpenStruct.new(second_person.merge(:attributes => second_person))
310
+ fields = @instance.to_solr_doc.fields.select {|f| f.name.to_s == "person_s"}
311
+ assert_not_equal @people.size, fields.size
312
+ assert_equal 1, fields.size
313
+ end
314
+ end
315
+ end
316
+ end
317
+ end
318
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/test_helper")
2
+
3
+ class UserModel; end
4
+
5
+ class LazyDocumentTest < Test::Unit::TestCase
6
+ context "With a lazy document" do
7
+ setup do
8
+ @record = stub(:record)
9
+ @record.stubs(:is_valid?).returns true
10
+ UserModel.stubs(:find).returns @record
11
+ @document = ActsAsSolr::LazyDocument.new(1, UserModel)
12
+ end
13
+
14
+ context "with an uninitialized document" do
15
+ should "fetch the record from the database" do
16
+ UserModel.expects(:find).with(1).returns(@record)
17
+ @document.is_valid?
18
+ end
19
+ end
20
+
21
+ context "with an initialized document" do
22
+ should "not fetch the record again" do
23
+ @document.is_valid?
24
+ @document.expects(:find).never
25
+ @document.is_valid?
26
+ end
27
+
28
+ should "reroute the calls to the record" do
29
+ @record.expects(:is_valid?).once
30
+ @document.is_valid?
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ class ActsAsSolr::ParserInstance
2
+ include ActsAsSolr::ParserMethods
3
+ include ActsAsSolr::CommonMethods
4
+ attr_accessor :configuration, :solr_configuration
5
+
6
+ def table_name
7
+ "documents"
8
+ end
9
+
10
+ def primary_key
11
+ "id"
12
+ end
13
+
14
+ def find(*args)
15
+ []
16
+ end
17
+
18
+ public :parse_results, :reorder, :parse_query, :add_scores, :replace_types
19
+ end
@@ -0,0 +1,268 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/test_helper")
2
+
3
+ class ActsAsSolr::Post; end
4
+
5
+ class ParserMethodsTest < Test::Unit::TestCase
6
+
7
+ context "With a parser instance" do
8
+ setup do
9
+ @parser = ActsAsSolr::ParserInstance.new
10
+ end
11
+
12
+ context "When parsing results" do
13
+ setup do
14
+ @results = stub(:results)
15
+ @results.stubs(:total_hits).returns(2)
16
+ @results.stubs(:hits).returns([])
17
+ @results.stubs(:max_score).returns 2.1
18
+ @results.stubs(:data).returns({"responseHeader" => {"QTime" => "10.2"}})
19
+ end
20
+
21
+ should "return a SearchResults object" do
22
+ assert_equal ActsAsSolr::SearchResults, @parser.parse_results(@results).class
23
+ end
24
+
25
+ should "set the max score" do
26
+ assert_equal 2.1, @parser.parse_results(@results).max_score
27
+ end
28
+
29
+ should "include the facets" do
30
+ @results.stubs(:data).returns({"responseHeader" => {"QTime" => "10.2"}, "facet_counts" => 2})
31
+ assert_equal 2, @parser.parse_results(@results, :facets => true).facets
32
+ end
33
+
34
+ context "when the format requests objects" do
35
+ setup do
36
+ @parser.configuration = {:format => :objects}
37
+ @parser.solr_configuration = {:primary_key_field => :pk_id}
38
+ @results.stubs(:hits).returns [{"pk_id" => 1}, {"pk_id" => 2}]
39
+ @parser.stubs(:reorder)
40
+ end
41
+
42
+ should "query with the record ids" do
43
+ @parser.expects(:find).with(:all, :conditions => ["documents.id in (?)", [1, 2]]).returns [1, 2]
44
+ @parser.parse_results(@results)
45
+ end
46
+
47
+ should "reorder the records" do
48
+ @parser.expects(:reorder).with([], [1, 2])
49
+ @parser.parse_results(@results)
50
+ end
51
+
52
+ should "add :include if :include was specified" do
53
+ @parser.expects(:find).with(:all, :conditions => ["documents.id in (?)", [1, 2]], :include => [:author]).returns [1, 2]
54
+ @parser.parse_results(@results, :include => [:author])
55
+ end
56
+ end
57
+
58
+ context "when the format doesn't request objects" do
59
+ setup do
60
+ @parser.solr_configuration = {:primary_key_field => "pk_id"}
61
+ end
62
+
63
+ should "not query the database" do
64
+ @parser.expects(:find).never
65
+ @parser.parse_results(@results, :format => nil)
66
+ end
67
+
68
+ should "return just the ids" do
69
+ @results.stubs(:hits).returns([{"pk_id" => 1}, {"pk_id" => 2}])
70
+ assert_equal [1, 2], @parser.parse_results(@results, :format => nil).docs
71
+ end
72
+
73
+ should "ignore the :lazy option" do
74
+ @results.stubs(:hits).returns([{"pk_id" => 1}, {"pk_id" => 2}])
75
+ assert_equal [1, 2], @parser.parse_results(@results, :format => :ids, :lazy => true).docs
76
+ end
77
+ end
78
+
79
+ context "with an empty result set" do
80
+ setup do
81
+ @results.stubs(:total_hits).returns(0)
82
+ @results.stubs(:hits).returns([])
83
+ end
84
+
85
+ should "return an empty search results set" do
86
+ assert_equal 0, @parser.parse_results(@results).total
87
+ end
88
+
89
+ should "not have any search results" do
90
+ assert_equal [], @parser.parse_results(@results).docs
91
+ end
92
+ end
93
+
94
+ context "with a nil result set" do
95
+ should "return an empty search results set" do
96
+ assert_equal 0, @parser.parse_results(nil).total
97
+ end
98
+ end
99
+
100
+ context "with the scores option" do
101
+ should "add the scores" do
102
+ @parser.expects(:add_scores).with([], @results)
103
+ @parser.parse_results(@results, :scores => true)
104
+ end
105
+ end
106
+
107
+ context "with lazy format" do
108
+ setup do
109
+ @parser.solr_configuration = {:primary_key_field => :pk_id}
110
+ @results.stubs(:hits).returns([{"pk_id" => 1}, {"pk_id" => 2}])
111
+ end
112
+
113
+ should "create LazyDocuments for the resulting docs" do
114
+ result = @parser.parse_results(@results, :lazy => true)
115
+ assert_equal ActsAsSolr::LazyDocument, result.results.first.class
116
+ end
117
+
118
+ should "set the document id as the record id" do
119
+ result = @parser.parse_results(@results, :lazy => true)
120
+ assert_equal 1, result.results.first.id
121
+ end
122
+
123
+ should "set the document class" do
124
+ result = @parser.parse_results(@results, :lazy => true)
125
+ assert_equal ActsAsSolr::ParserInstance, result.results.first.clazz.class
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ context "when reordering results" do
132
+ should "raise an error if arguments don't have the same number of elements" do
133
+ assert_raise(RuntimeError) {@parser.reorder([], [1])}
134
+ end
135
+
136
+ should "reorder the results to match the order of the documents returned by solr" do
137
+ thing1 = stub(:thing1)
138
+ thing1.stubs(:id).returns 5
139
+ thing2 = stub(:thing2)
140
+ thing2.stubs(:id).returns 1
141
+ thing3 = stub(:things3)
142
+ thing3.stubs(:id).returns 3
143
+ things = [thing1, thing2, thing3]
144
+ reordered = @parser.reorder(things, [1, 3, 5])
145
+ assert_equal [1, 3, 5], reordered.collect{|thing| thing.id}
146
+ end
147
+ end
148
+
149
+ context "When parsing a query" do
150
+ setup do
151
+ ActsAsSolr::Post.stubs(:execute)
152
+ @parser.stubs(:solr_type_condition).returns "(type:ParserMethodsTest)"
153
+ @parser.solr_configuration = {:primary_key_field => "id"}
154
+ @parser.configuration = {:solr_fields => nil}
155
+ end
156
+
157
+ should "set the limit and offset" do
158
+ ActsAsSolr::Post.expects(:execute).with {|request|
159
+ 10 == request.to_hash[:rows]
160
+ 20 == request.to_hash[:start]
161
+ }
162
+ @parser.parse_query "foo", :limit => 10, :offset => 20
163
+ end
164
+
165
+ should "set the operator" do
166
+ ActsAsSolr::Post.expects(:execute).with {|request|
167
+ "OR" == request.to_hash["q.op"]
168
+ }
169
+ @parser.parse_query "foo", :operator => :or
170
+ end
171
+
172
+ should "not execute anything if the query is nil" do
173
+ ActsAsSolr::Post.expects(:execute).never
174
+ assert_nil @parser.parse_query(nil)
175
+ end
176
+
177
+ should "not execute anything if the query is ''" do
178
+ ActsAsSolr::Post.expects(:execute).never
179
+ assert_nil @parser.parse_query('')
180
+ end
181
+
182
+ should "raise an error if invalid options where specified" do
183
+ assert_raise(RuntimeError) {@parser.parse_query "foo", :invalid => true}
184
+ end
185
+
186
+ should "add the type" do
187
+ ActsAsSolr::Post.expects(:execute).with {|request|
188
+ request.to_hash[:q].include?("(type:ParserMethodsTest)")
189
+ }
190
+ @parser.parse_query "foo"
191
+ end
192
+
193
+ should "append the field types for the specified fields" do
194
+ ActsAsSolr::Post.expects(:execute).with {|request|
195
+ request.to_hash[:q].include?("(username_t:Chunky)")
196
+ }
197
+ @parser.parse_query "username:Chunky"
198
+ end
199
+
200
+ should "replace the field types" do
201
+ @parser.expects(:replace_types).returns(["active_i:1"])
202
+ ActsAsSolr::Post.expects(:execute).with {|request|
203
+ request.to_hash[:q].include?("active_i:1")
204
+ }
205
+ @parser.parse_query "active:1"
206
+ end
207
+
208
+ should "add score and primary key to field list" do
209
+ ActsAsSolr::Post.expects(:execute).with {|request|
210
+ request.to_hash[:fl] == ('id,score')
211
+ }
212
+ @parser.parse_query "foo"
213
+ end
214
+
215
+ context "with the order option" do
216
+ should "add the order criteria to the query" do
217
+ ActsAsSolr::Post.expects(:execute).with {|request|
218
+ request.to_hash[:q].include?(";active_t desc")
219
+ }
220
+ @parser.parse_query "active:1", :order => "active desc"
221
+ end
222
+ end
223
+
224
+ context "with facets" do
225
+ end
226
+ end
227
+
228
+ context "When setting the field types" do
229
+ setup do
230
+ @parser.configuration = {:solr_fields => {:name => {:type => :string},
231
+ :age => {:type => :integer}}}
232
+ end
233
+
234
+ should "replace the _t suffix with the real type" do
235
+ assert_equal ["name_s:Chunky AND age_i:21"], @parser.replace_types(["name_t:Chunky AND age_t:21"])
236
+ end
237
+
238
+ context "with a suffix" do
239
+ should "not include the colon when false" do
240
+ assert_equal ["name_s"], @parser.replace_types(["name_t"], false)
241
+ end
242
+
243
+ should "include the colon by default" do
244
+ assert_equal ["name_s:Chunky"], @parser.replace_types(["name_t:Chunky"])
245
+ end
246
+ end
247
+ end
248
+
249
+ context "When adding scores" do
250
+ setup do
251
+ @solr_data = stub(:results)
252
+ @solr_data.stubs(:total_hits).returns(1)
253
+ @solr_data.stubs(:hits).returns([{"id" => 2, "score" => 2.546}])
254
+ @solr_data.stubs(:max_score).returns 2.1
255
+
256
+ @results = [Array.new]
257
+
258
+ @parser.stubs(:record_id).returns(2)
259
+
260
+ @parser.solr_configuration = {:primary_key_field => "id"}
261
+ end
262
+
263
+ should "add the score to the result document" do
264
+ assert_equal 2.546, @parser.add_scores(@results, @solr_data).first.last.solr_score
265
+ end
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,49 @@
1
+ class SolrInstance
2
+ include ActsAsSolr::InstanceMethods
3
+ attr_accessor :configuration, :solr_configuration, :name
4
+
5
+ class << self
6
+ include ActsAsSolr::ActsMethods
7
+ include ActsAsSolr::ClassMethods
8
+ end
9
+
10
+ def initialize(name = "Chunky bacon!")
11
+ @name = name
12
+ end
13
+
14
+ def self.primary_key
15
+ "id"
16
+ end
17
+
18
+ def logger
19
+ @logger ||= Logger.new(StringIO.new)
20
+ end
21
+
22
+ def record_id(obj)
23
+ 10
24
+ end
25
+
26
+ def boost_rate
27
+ 10.0
28
+ end
29
+
30
+ def irate
31
+ 8.0
32
+ end
33
+
34
+ def name_for_solr
35
+ name
36
+ end
37
+
38
+ def id_for_solr
39
+ "bogus"
40
+ end
41
+
42
+ def type_for_solr
43
+ "humbug"
44
+ end
45
+
46
+ def get_solr_field_type(args)
47
+ "s"
48
+ end
49
+ end