sunspot 2.0.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -0
  4. data/Appraisals +7 -0
  5. data/Gemfile +0 -2
  6. data/History.txt +10 -0
  7. data/lib/sunspot.rb +55 -17
  8. data/lib/sunspot/adapters.rb +68 -18
  9. data/lib/sunspot/batcher.rb +1 -1
  10. data/lib/sunspot/configuration.rb +4 -2
  11. data/lib/sunspot/data_extractor.rb +36 -6
  12. data/lib/sunspot/dsl.rb +4 -3
  13. data/lib/sunspot/dsl/adjustable.rb +2 -2
  14. data/lib/sunspot/dsl/field_query.rb +69 -16
  15. data/lib/sunspot/dsl/field_stats.rb +25 -0
  16. data/lib/sunspot/dsl/fields.rb +28 -8
  17. data/lib/sunspot/dsl/fulltext.rb +9 -1
  18. data/lib/sunspot/dsl/group.rb +118 -0
  19. data/lib/sunspot/dsl/paginatable.rb +4 -1
  20. data/lib/sunspot/dsl/scope.rb +19 -10
  21. data/lib/sunspot/dsl/search.rb +1 -1
  22. data/lib/sunspot/dsl/spellcheckable.rb +14 -0
  23. data/lib/sunspot/dsl/standard_query.rb +63 -35
  24. data/lib/sunspot/field.rb +76 -4
  25. data/lib/sunspot/field_factory.rb +60 -11
  26. data/lib/sunspot/indexer.rb +70 -18
  27. data/lib/sunspot/query.rb +5 -4
  28. data/lib/sunspot/query/abstract_field_facet.rb +0 -2
  29. data/lib/sunspot/query/abstract_fulltext.rb +76 -0
  30. data/lib/sunspot/query/abstract_json_field_facet.rb +70 -0
  31. data/lib/sunspot/query/bbox.rb +5 -1
  32. data/lib/sunspot/query/common_query.rb +31 -6
  33. data/lib/sunspot/query/composite_fulltext.rb +58 -8
  34. data/lib/sunspot/query/date_field_json_facet.rb +25 -0
  35. data/lib/sunspot/query/dismax.rb +25 -71
  36. data/lib/sunspot/query/field_json_facet.rb +19 -0
  37. data/lib/sunspot/query/field_list.rb +15 -0
  38. data/lib/sunspot/query/field_stats.rb +61 -0
  39. data/lib/sunspot/query/function_query.rb +1 -2
  40. data/lib/sunspot/query/geo.rb +1 -1
  41. data/lib/sunspot/query/geofilt.rb +8 -3
  42. data/lib/sunspot/query/group.rb +46 -0
  43. data/lib/sunspot/query/group_query.rb +17 -0
  44. data/lib/sunspot/query/join.rb +88 -0
  45. data/lib/sunspot/query/more_like_this.rb +1 -1
  46. data/lib/sunspot/query/pagination.rb +12 -4
  47. data/lib/sunspot/query/range_json_facet.rb +28 -0
  48. data/lib/sunspot/query/restriction.rb +99 -13
  49. data/lib/sunspot/query/sort.rb +41 -0
  50. data/lib/sunspot/query/sort_composite.rb +7 -0
  51. data/lib/sunspot/query/spellcheck.rb +19 -0
  52. data/lib/sunspot/query/standard_query.rb +24 -2
  53. data/lib/sunspot/query/text_field_boost.rb +1 -3
  54. data/lib/sunspot/schema.rb +12 -3
  55. data/lib/sunspot/search.rb +4 -2
  56. data/lib/sunspot/search/abstract_search.rb +93 -43
  57. data/lib/sunspot/search/cursor_paginated_collection.rb +32 -0
  58. data/lib/sunspot/search/field_facet.rb +4 -4
  59. data/lib/sunspot/search/field_json_facet.rb +33 -0
  60. data/lib/sunspot/search/field_stats.rb +21 -0
  61. data/lib/sunspot/search/hit.rb +6 -1
  62. data/lib/sunspot/search/hit_enumerable.rb +4 -1
  63. data/lib/sunspot/search/json_facet_row.rb +40 -0
  64. data/lib/sunspot/search/json_facet_stats.rb +23 -0
  65. data/lib/sunspot/search/paginated_collection.rb +1 -0
  66. data/lib/sunspot/search/query_group.rb +74 -0
  67. data/lib/sunspot/search/standard_search.rb +70 -3
  68. data/lib/sunspot/search/stats_facet.rb +25 -0
  69. data/lib/sunspot/search/stats_json_row.rb +82 -0
  70. data/lib/sunspot/search/stats_row.rb +68 -0
  71. data/lib/sunspot/session.rb +62 -37
  72. data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +6 -4
  73. data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +16 -8
  74. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +2 -2
  75. data/lib/sunspot/session_proxy/retry_5xx_session_proxy.rb +1 -1
  76. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +4 -2
  77. data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +1 -1
  78. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +6 -4
  79. data/lib/sunspot/setup.rb +42 -0
  80. data/lib/sunspot/type.rb +20 -0
  81. data/lib/sunspot/util.rb +78 -14
  82. data/lib/sunspot/version.rb +1 -1
  83. data/spec/api/adapters_spec.rb +40 -15
  84. data/spec/api/batcher_spec.rb +15 -15
  85. data/spec/api/binding_spec.rb +3 -3
  86. data/spec/api/class_set_spec.rb +6 -6
  87. data/spec/api/data_extractor_spec.rb +39 -0
  88. data/spec/api/hit_enumerable_spec.rb +32 -9
  89. data/spec/api/indexer/attributes_spec.rb +35 -30
  90. data/spec/api/indexer/batch_spec.rb +8 -7
  91. data/spec/api/indexer/dynamic_fields_spec.rb +8 -8
  92. data/spec/api/indexer/fixed_fields_spec.rb +16 -11
  93. data/spec/api/indexer/fulltext_spec.rb +8 -8
  94. data/spec/api/indexer/removal_spec.rb +24 -14
  95. data/spec/api/indexer_spec.rb +2 -2
  96. data/spec/api/query/advanced_manipulation_examples.rb +3 -3
  97. data/spec/api/query/connectives_examples.rb +26 -14
  98. data/spec/api/query/dsl_spec.rb +24 -6
  99. data/spec/api/query/dynamic_fields_examples.rb +18 -18
  100. data/spec/api/query/faceting_examples.rb +80 -61
  101. data/spec/api/query/fulltext_examples.rb +194 -40
  102. data/spec/api/query/function_spec.rb +116 -13
  103. data/spec/api/query/geo_examples.rb +8 -12
  104. data/spec/api/query/group_spec.rb +27 -5
  105. data/spec/api/query/highlighting_examples.rb +26 -26
  106. data/spec/api/query/join_spec.rb +19 -0
  107. data/spec/api/query/more_like_this_spec.rb +40 -27
  108. data/spec/api/query/ordering_pagination_examples.rb +37 -23
  109. data/spec/api/query/scope_examples.rb +39 -39
  110. data/spec/api/query/spatial_examples.rb +3 -3
  111. data/spec/api/query/spellcheck_examples.rb +20 -0
  112. data/spec/api/query/standard_spec.rb +3 -1
  113. data/spec/api/query/stats_examples.rb +66 -0
  114. data/spec/api/query/text_field_scoping_examples.rb +5 -5
  115. data/spec/api/query/types_spec.rb +4 -4
  116. data/spec/api/search/cursor_paginated_collection_spec.rb +35 -0
  117. data/spec/api/search/dynamic_fields_spec.rb +4 -4
  118. data/spec/api/search/faceting_spec.rb +55 -52
  119. data/spec/api/search/highlighting_spec.rb +7 -7
  120. data/spec/api/search/hits_spec.rb +43 -29
  121. data/spec/api/search/paginated_collection_spec.rb +19 -18
  122. data/spec/api/search/results_spec.rb +13 -13
  123. data/spec/api/search/search_spec.rb +3 -3
  124. data/spec/api/search/stats_spec.rb +94 -0
  125. data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +23 -16
  126. data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +16 -4
  127. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +10 -6
  128. data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +11 -11
  129. data/spec/api/session_proxy/sharding_session_proxy_spec.rb +15 -14
  130. data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +3 -3
  131. data/spec/api/session_proxy/spec_helper.rb +1 -1
  132. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +40 -26
  133. data/spec/api/session_spec.rb +78 -38
  134. data/spec/api/sunspot_spec.rb +7 -4
  135. data/spec/helpers/integration_helper.rb +11 -1
  136. data/spec/helpers/query_helper.rb +1 -1
  137. data/spec/helpers/search_helper.rb +30 -0
  138. data/spec/integration/atomic_updates_spec.rb +58 -0
  139. data/spec/integration/dynamic_fields_spec.rb +31 -20
  140. data/spec/integration/faceting_spec.rb +252 -39
  141. data/spec/integration/field_grouping_spec.rb +47 -15
  142. data/spec/integration/field_lists_spec.rb +57 -0
  143. data/spec/integration/geospatial_spec.rb +34 -8
  144. data/spec/integration/highlighting_spec.rb +8 -8
  145. data/spec/integration/indexing_spec.rb +7 -6
  146. data/spec/integration/join_spec.rb +45 -0
  147. data/spec/integration/keyword_search_spec.rb +68 -38
  148. data/spec/integration/local_search_spec.rb +4 -4
  149. data/spec/integration/more_like_this_spec.rb +7 -7
  150. data/spec/integration/scoped_search_spec.rb +193 -74
  151. data/spec/integration/spellcheck_spec.rb +119 -0
  152. data/spec/integration/stats_spec.rb +88 -0
  153. data/spec/integration/stored_fields_spec.rb +1 -1
  154. data/spec/integration/test_pagination.rb +4 -4
  155. data/spec/integration/unicode_spec.rb +1 -1
  156. data/spec/mocks/adapters.rb +36 -0
  157. data/spec/mocks/connection.rb +5 -3
  158. data/spec/mocks/photo.rb +32 -1
  159. data/spec/mocks/post.rb +18 -3
  160. data/spec/spec_helper.rb +13 -8
  161. data/sunspot.gemspec +6 -4
  162. data/tasks/rdoc.rake +22 -14
  163. metadata +101 -44
  164. data/lib/sunspot/dsl/field_group.rb +0 -57
  165. data/lib/sunspot/query/field_group.rb +0 -37
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 179de5f5261bdb69d21038a0b2e36fbd2812e1fc71ef4c1efd77979a03e58179
4
+ data.tar.gz: 1f7f40d9737400cf61c23515c61ebde70140b1c1bf9df800d7e19ce27c3cbd0d
5
+ SHA512:
6
+ metadata.gz: ad59d5868f3461648d29c77b6368d7c5145ef6247ecca38878bf4f03bb3d2ab73fea2decf629936d58282b8067345198f6bff82be1347bb0cc92cb4537722d28
7
+ data.tar.gz: 3c4fd67940331fbdacffd665ca624119038bf12da2aa2b041adbd8260aef3921660b83803a912cf81384c7269f6b46d3b7fad1c883c34e1a1ba2ccbade2fd6dc
data/.gitignore CHANGED
@@ -11,3 +11,4 @@ pkg
11
11
  README.rdoc
12
12
  .bundle
13
13
  Gemfile.lock
14
+ gemfiles/*.gemfile*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Appraisals ADDED
@@ -0,0 +1,7 @@
1
+ appraise 'rsolr-1.x' do
2
+ gem 'rsolr', '>= 1', '< 2'
3
+ end
4
+
5
+ appraise 'rsolr-2.x' do
6
+ gem 'rsolr', '>= 2', '< 3'
7
+ end
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem 'sunspot_solr', :path => File.expand_path('../../sunspot_solr', __FILE__)
4
-
5
3
  gemspec
data/History.txt CHANGED
@@ -1,3 +1,13 @@
1
+ == 2.1.0
2
+ * Dropped support for rails 2.x. Added support for Rails 4.
3
+ * Bundled Solr installation (`sunspot_solr`) is version 4.2.0
4
+ * Upgrade to Jetty 8 and changed solr config directory structure.
5
+ * Removed interactive warning prompt from sunspot:reindex rake task.
6
+ * Support Rails 4 custom primary keys i.e. UUID
7
+ * Switch to EDismax query parser from dismax.
8
+ * Extend Sunspot.remove! to accept a block, and enable .remove_by_id! to accept multiple ids.
9
+ * add 'order_by_function' method to field queries. Allowing for Solr FunctionQuery, nesting, and literal constants.
10
+
1
11
  == 2.0.0
2
12
  * Adds support for field grouping (Andy Lindeman)
3
13
  * Adds support for native geospatial searches and ordering (Eric Tang, Bruno Miranda, Andy Lindeman)
data/lib/sunspot.rb CHANGED
@@ -196,23 +196,61 @@ module Sunspot
196
196
  session.index!(*objects)
197
197
  end
198
198
 
199
- # Commits the singleton session
199
+ # Atomic update object properties on the singleton session.
200
+ #
201
+ # ==== Parameters
202
+ #
203
+ # clazz<Class>:: the class of the objects to be updated
204
+ # updates<Hash>:: hash of updates where keys are model ids
205
+ # and values are hash with property name/values to be updated
206
+ #
207
+ # ==== Example
208
+ #
209
+ # post1, post2 = new Array(2) { Post.create }
210
+ # Sunspot.atomic_update(Post, post1.id => {title: 'New Title'}, post2.id => {description: 'new description'})
211
+ #
212
+ # Note that indexed objects won't be reflected in search until a commit is
213
+ # sent - see Sunspot.index! and Sunspot.commit
214
+ #
215
+ def atomic_update(clazz, updates = {})
216
+ session.atomic_update(clazz, updates)
217
+ end
218
+
219
+ # Atomic update object properties on the singleton session.
220
+ #
221
+ # See: Sunspot.atomic_update and Sunspot.commit
222
+ #
223
+ # ==== Parameters
224
+ #
225
+ # clazz<Class>:: the class of the objects to be updated
226
+ # updates<Hash>:: hash of updates where keys are model ids
227
+ # and values are hash with property name/values to be updated
228
+ #
229
+ def atomic_update!(clazz, updates = {})
230
+ session.atomic_update!(clazz, updates)
231
+ end
232
+
233
+ # Commits (soft or hard) the singleton session
200
234
  #
201
235
  # When documents are added to or removed from Solr, the changes are
202
236
  # initially stored in memory, and are not reflected in Solr's existing
203
- # searcher instance. When a commit message is sent, the changes are written
237
+ # searcher instance. When a hard commit message is sent, the changes are written
204
238
  # to disk, and a new searcher is spawned. Commits are thus fairly
205
239
  # expensive, so if your application needs to index several documents as part
206
240
  # of a single operation, it is advisable to index them all and then call
207
241
  # commit at the end of the operation.
242
+ # Solr 4 introduced the concept of a soft commit which is much faster
243
+ # since it only makes index changes visible while not writing changes to disk.
244
+ # If Solr crashes or there is a loss of power, changes that occurred after
245
+ # the last hard commit will be lost.
208
246
  #
209
247
  # Note that Solr can also be configured to automatically perform a commit
210
248
  # after either a specified interval after the last change, or after a
211
249
  # specified number of documents are added. See
212
250
  # http://wiki.apache.org/solr/SolrConfigXml
213
251
  #
214
- def commit
215
- session.commit
252
+ def commit(soft_commit = false)
253
+ session.commit soft_commit
216
254
  end
217
255
 
218
256
  # Optimizes the index on the singletion session.
@@ -417,8 +455,8 @@ module Sunspot
417
455
  #
418
456
  # objects...<Object>:: Objects to remove from the index
419
457
  #
420
- def remove!(*objects)
421
- session.remove!(*objects)
458
+ def remove!(*objects, &block)
459
+ session.remove!(*objects, &block)
422
460
  end
423
461
 
424
462
  #
@@ -433,16 +471,16 @@ module Sunspot
433
471
  # Primary key of the object. This should be the same id that would be
434
472
  # returned by the class's instance adapter.
435
473
  #
436
- def remove_by_id(clazz, id)
437
- session.remove_by_id(clazz, id)
474
+ def remove_by_id(clazz, *ids)
475
+ session.remove_by_id(clazz, ids)
438
476
  end
439
477
 
440
478
  #
441
479
  # Remove an object by class name and primary key, and immediately commit.
442
480
  # See #remove_by_id and #commit
443
481
  #
444
- def remove_by_id!(clazz, id)
445
- session.remove_by_id!(clazz, id)
482
+ def remove_by_id!(clazz, *ids)
483
+ session.remove_by_id!(clazz, ids)
446
484
  end
447
485
 
448
486
  # Remove all objects of the given classes from the index. There isn't much
@@ -486,9 +524,9 @@ module Sunspot
486
524
  #
487
525
  # Sunspot.batch do
488
526
  # post = Post.new
489
- # Sunspot.add(post)
527
+ # Sunspot.index(post)
490
528
  # comment = Comment.new
491
- # Sunspot.add(comment)
529
+ # Sunspot.index(comment)
492
530
  # end
493
531
  #
494
532
  # Sunspot will send both the post and the comment in a single request.
@@ -510,10 +548,10 @@ module Sunspot
510
548
  end
511
549
 
512
550
  #
513
- # Sends a commit if the session is dirty (see #dirty?).
551
+ # Sends a commit (soft or hard) if the session is dirty (see #dirty?).
514
552
  #
515
- def commit_if_dirty
516
- session.commit_if_dirty
553
+ def commit_if_dirty(soft_commit = false)
554
+ session.commit_if_dirty soft_commit
517
555
  end
518
556
 
519
557
  #
@@ -530,8 +568,8 @@ module Sunspot
530
568
  #
531
569
  # Sends a commit if the session has deletes since the last commit (see #delete_dirty?).
532
570
  #
533
- def commit_if_delete_dirty
534
- session.commit_if_delete_dirty
571
+ def commit_if_delete_dirty(soft_commit = false)
572
+ session.commit_if_delete_dirty soft_commit
535
573
  end
536
574
 
537
575
  # Returns the configuration associated with the singleton session. See
@@ -1,3 +1,5 @@
1
+ require 'forwardable'
2
+
1
3
  module Sunspot
2
4
  #
3
5
  # Sunspot works by saving references to the primary key (or natural ID) of
@@ -46,7 +48,7 @@ module Sunspot
46
48
  # end
47
49
  #
48
50
  # # then in your initializer
49
- # Sunspot::Adapters::InstanceAdapter.register(MyAdapter, File)
51
+ # Sunspot::Adapters::InstanceAdapter.register(FileAdapter, File)
50
52
  #
51
53
  class InstanceAdapter
52
54
  def initialize(instance) #:nodoc:
@@ -61,7 +63,10 @@ module Sunspot
61
63
  # String:: ID for use in Solr
62
64
  #
63
65
  def index_id #:nodoc:
64
- InstanceAdapter.index_id_for(@instance.class.name, id)
66
+ setup = Sunspot::Setup.for(@instance.class)
67
+ id_prefix = setup ? setup.id_prefix_for(@instance) : nil
68
+
69
+ InstanceAdapter.index_id_for("#{id_prefix}#{@instance.class.name}", id)
65
70
  end
66
71
 
67
72
  class <<self
@@ -119,16 +124,28 @@ module Sunspot
119
124
  #
120
125
  # Sunspot::NoAdapterError:: If no adapter is registered for this class
121
126
  #
122
- def for(clazz) #:nodoc:
123
- original_class_name = clazz.name
124
- clazz.ancestors.each do |ancestor_class|
125
- next if ancestor_class.name.nil? || ancestor_class.name.empty?
126
- class_name = ancestor_class.name.to_sym
127
- return instance_adapters[class_name] if instance_adapters[class_name]
128
- end
129
-
127
+ def for(clazz)
128
+ adapter = registered_adapter_for(clazz) || registered_adapter_for_ancestors_of(clazz)
129
+ return adapter if adapter
130
130
  raise(Sunspot::NoAdapterError,
131
- "No adapter is configured for #{original_class_name} or its superclasses. See the documentation for Sunspot::Adapters")
131
+ "No adapter is configured for #{clazz.name} or its superclasses. See the documentation for Sunspot::Adapters")
132
+ end
133
+
134
+ # Returns the directly-registered adapter for the specified class,
135
+ # if one exists, without searching the class's ancestors.
136
+ #
137
+ # === Parameters
138
+ #
139
+ # clazz<Class>:: The model class to be checked for the registered
140
+ # adapter
141
+ #
142
+ # === Returns
143
+ #
144
+ # Class:: Subclass of InstanceAdapter, or nil if none found
145
+ #
146
+ def registered_adapter_for(clazz)
147
+ return nil if clazz.name.nil? || clazz.name.empty?
148
+ instance_adapters[clazz.name.to_sym]
132
149
  end
133
150
 
134
151
  def index_id_for(class_name, id) #:nodoc:
@@ -146,6 +163,16 @@ module Sunspot
146
163
  def instance_adapters #:nodoc:
147
164
  @instance_adapters ||= {}
148
165
  end
166
+
167
+ def registered_adapter_for_ancestors_of(clazz) # :nodoc:
168
+ clazz.ancestors.each do |ancestor_class|
169
+ if adapter = registered_adapter_for(ancestor_class)
170
+ register(adapter, clazz)
171
+ return adapter
172
+ end
173
+ end
174
+ nil
175
+ end
149
176
  end
150
177
  end
151
178
 
@@ -247,14 +274,27 @@ module Sunspot
247
274
  # Sunspot::NoAdapterError:: If no data accessor exists for the given class
248
275
  #
249
276
  def for(clazz) #:nodoc:
250
- original_class_name = clazz.name
251
- clazz.ancestors.each do |ancestor_class|
252
- next if ancestor_class.name.nil? || ancestor_class.name.empty?
253
- class_name = ancestor_class.name.to_sym
254
- return data_accessors[class_name] if data_accessors[class_name]
255
- end
277
+ accessor = registered_accessor_for(clazz) || registered_accessor_for_ancestors_of(clazz)
278
+ return accessor if accessor
256
279
  raise(Sunspot::NoAdapterError,
257
- "No data accessor is configured for #{original_class_name} or its superclasses. See the documentation for Sunspot::Adapters")
280
+ "No data accessor is configured for #{clazz.name} or its superclasses. See the documentation for Sunspot::Adapters")
281
+ end
282
+
283
+ # Returns the directly-registered accessor for the specified class, if
284
+ # one exists, without searching the class's ancestors.
285
+ #
286
+ # === Parameters
287
+ #
288
+ # clazz<Class>:: The model class to be checked for the registered
289
+ # data accessor
290
+ #
291
+ # === Returns
292
+ #
293
+ # Class:: Subclass of DataAccessor, or nil if none found
294
+ #
295
+ def registered_accessor_for(clazz)
296
+ return nil if clazz.name.nil? || clazz.name.empty?
297
+ data_accessors[clazz.name.to_sym]
258
298
  end
259
299
 
260
300
  protected
@@ -268,6 +308,16 @@ module Sunspot
268
308
  def data_accessors #:nodoc:
269
309
  @adapters ||= {}
270
310
  end
311
+
312
+ def registered_accessor_for_ancestors_of(clazz) # :nodoc:
313
+ clazz.ancestors.each do |ancestor_class|
314
+ if accessor = registered_accessor_for(ancestor_class)
315
+ register(accessor, clazz)
316
+ return accessor
317
+ end
318
+ end
319
+ nil
320
+ end
271
321
  end
272
322
  end
273
323
 
@@ -12,7 +12,7 @@ module Sunspot
12
12
  # end
13
13
  #
14
14
  # it is the Batcher's job to keep track of these nestings. The inner will
15
- # be sent of to be indexed first.
15
+ # be sent off to be indexed first.
16
16
  #
17
17
  class Batcher
18
18
  include Enumerable
@@ -22,9 +22,11 @@ module Sunspot
22
22
  def build #:nodoc:
23
23
  LightConfig.build do
24
24
  solr do
25
- url 'http://127.0.0.1:8983/solr'
25
+ url 'http://127.0.0.1:8983/solr/default'
26
26
  read_timeout nil
27
27
  open_timeout nil
28
+ proxy nil
29
+ update_format :xml
28
30
  end
29
31
  master_solr do
30
32
  url nil
@@ -37,7 +39,7 @@ module Sunspot
37
39
  end
38
40
  end
39
41
  end
40
-
42
+
41
43
  # Location for the default solr configuration files,
42
44
  # required for bootstrapping a new solr installation
43
45
  #
@@ -5,16 +5,46 @@ module Sunspot
5
5
  # method, which takes an object and returns the value extracted from it.
6
6
  #
7
7
  module DataExtractor #:nodoc: all
8
+ #
9
+ # Abstract extractor to perform common actions on extracted values
10
+ #
11
+ class AbstractExtractor
12
+ BLACKLIST_REGEXP = /[\x0-\x8\xB\xC\xE-\x1F\x7f]/
13
+
14
+ def value_for(object)
15
+ extract_value_from(object)
16
+ end
17
+
18
+ private
19
+
20
+ def extract_value_from(object)
21
+ case object
22
+ when String
23
+ remove_blacklisted_chars(object)
24
+ when Array
25
+ object.map { |o| extract_value_from(o) }
26
+ when Hash
27
+ object.inject({}) { |h, (k, v)| h.merge(extract_value_from(k) => extract_value_from(v)) }
28
+ else
29
+ object
30
+ end
31
+ end
32
+
33
+ def remove_blacklisted_chars(object)
34
+ object.gsub(BLACKLIST_REGEXP, '')
35
+ end
36
+ end
37
+
8
38
  #
9
39
  # AttributeExtractors extract data by simply calling a method on the block.
10
40
  #
11
- class AttributeExtractor
41
+ class AttributeExtractor < AbstractExtractor
12
42
  def initialize(attribute_name)
13
43
  @attribute_name = attribute_name
14
44
  end
15
45
 
16
46
  def value_for(object)
17
- object.send(@attribute_name)
47
+ super object.send(@attribute_name)
18
48
  end
19
49
  end
20
50
 
@@ -24,26 +54,26 @@ module Sunspot
24
54
  # as the argument to the block. Either way, the return value of the block is
25
55
  # the value returned by the extractor.
26
56
  #
27
- class BlockExtractor
57
+ class BlockExtractor < AbstractExtractor
28
58
  def initialize(&block)
29
59
  @block = block
30
60
  end
31
61
 
32
62
  def value_for(object)
33
- Util.instance_eval_or_call(object, &@block)
63
+ super Util.instance_eval_or_call(object, &@block)
34
64
  end
35
65
  end
36
66
 
37
67
  #
38
68
  # Constant data extractors simply return the same value for every object.
39
69
  #
40
- class Constant
70
+ class Constant < AbstractExtractor
41
71
  def initialize(value)
42
72
  @value = value
43
73
  end
44
74
 
45
75
  def value_for(object)
46
- @value
76
+ super @value
47
77
  end
48
78
  end
49
79
  end
data/lib/sunspot/dsl.rb CHANGED
@@ -1,5 +1,6 @@
1
- %w(fields scope paginatable adjustable field_query standard_query query_facet
2
- functional fulltext restriction restriction_with_near search
3
- more_like_this_query function field_group).each do |file|
1
+ %w(spellcheckable fields scope paginatable adjustable field_query
2
+ standard_query query_facet functional fulltext restriction
3
+ restriction_with_near search more_like_this_query function
4
+ group field_stats).each do |file|
4
5
  require File.join(File.dirname(__FILE__), 'dsl', file)
5
6
  end
@@ -26,9 +26,9 @@ module Sunspot
26
26
  # params["mlt.match.include"] = true
27
27
  # end
28
28
  # end
29
- #
29
+ #
30
30
  def adjust_solr_params( &block )
31
- @query.solr_parameter_adjustment = block
31
+ @query.add_parameter_adjustment(block)
32
32
  end
33
33
 
34
34
  #