blacklight 5.3.0 → 5.4.0.rc1

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/VERSION +1 -1
  4. data/app/assets/javascripts/blacklight/blacklight.js +1 -0
  5. data/app/assets/javascripts/blacklight/collapsable.js +9 -0
  6. data/app/controllers/bookmarks_controller.rb +72 -9
  7. data/app/helpers/blacklight/blacklight_helper_behavior.rb +15 -7
  8. data/app/helpers/blacklight/catalog_helper_behavior.rb +17 -9
  9. data/app/helpers/blacklight/configuration_helper_behavior.rb +59 -7
  10. data/app/helpers/blacklight/facets_helper_behavior.rb +1 -16
  11. data/app/helpers/blacklight/url_helper_behavior.rb +21 -2
  12. data/app/models/bookmark.rb +13 -4
  13. data/app/models/solr_document.rb +5 -0
  14. data/app/views/bookmarks/_tools.html.erb +10 -11
  15. data/app/views/catalog/_bookmark_control.html.erb +2 -2
  16. data/app/views/catalog/_refworks_form.html.erb +3 -2
  17. data/app/views/catalog/_sort_widget.html.erb +5 -5
  18. data/app/views/catalog/_view_type_group.html.erb +2 -2
  19. data/app/views/shared/_header_navbar.html.erb +1 -3
  20. data/config/locales/blacklight.pt-BR.yml +223 -0
  21. data/db/migrate/20140320000000_add_polymorphic_type_to_bookmarks.rb +8 -0
  22. data/gemfiles/rails4.1.gemfile +1 -1
  23. data/lib/blacklight.rb +5 -0
  24. data/lib/blacklight/catalog.rb +33 -5
  25. data/lib/blacklight/configuration.rb +12 -3
  26. data/lib/blacklight/configuration/facet_field.rb +1 -1
  27. data/lib/blacklight/configuration/search_field.rb +3 -2
  28. data/lib/blacklight/configuration/solr_field.rb +2 -1
  29. data/lib/blacklight/configuration/sort_field.rb +2 -1
  30. data/lib/blacklight/engine.rb +9 -1
  31. data/lib/blacklight/exceptions.rb +3 -0
  32. data/lib/blacklight/rails/routes.rb +12 -0
  33. data/lib/blacklight/request_builders.rb +19 -18
  34. data/lib/blacklight/search_fields.rb +0 -9
  35. data/lib/blacklight/solr/document.rb +15 -0
  36. data/lib/blacklight/solr/document/export.rb +4 -0
  37. data/lib/blacklight/solr_helper.rb +25 -28
  38. data/lib/blacklight/solr_response.rb +31 -29
  39. data/lib/blacklight/solr_response/response.rb +18 -0
  40. data/lib/blacklight/user.rb +17 -4
  41. data/lib/blacklight/utils.rb +30 -2
  42. data/lib/generators/blacklight/install_generator.rb +4 -0
  43. data/lib/generators/blacklight/templates/config/initializers/blacklight_initializer.rb +9 -0
  44. data/spec/controllers/application_controller_spec.rb +0 -1
  45. data/spec/controllers/bookmarks_controller_spec.rb +8 -4
  46. data/spec/controllers/catalog_controller_spec.rb +48 -55
  47. data/spec/controllers/saved_searches_controller_spec.rb +1 -4
  48. data/spec/controllers/search_history_controller_spec.rb +0 -1
  49. data/spec/features/bookmarks_spec.rb +14 -0
  50. data/spec/features/search_formats_spec.rb +45 -0
  51. data/spec/helpers/blacklight_helper_spec.rb +71 -30
  52. data/spec/helpers/configuration_helper_spec.rb +128 -4
  53. data/spec/helpers/facets_helper_spec.rb +1 -1
  54. data/spec/lib/blacklight/configuration_spec.rb +0 -5
  55. data/spec/lib/blacklight/search_fields_spec.rb +0 -22
  56. data/spec/lib/blacklight/solr/document_spec.rb +6 -0
  57. data/spec/lib/blacklight/solr_helper_spec.rb +31 -10
  58. data/spec/lib/blacklight/solr_response_spec.rb +8 -0
  59. data/spec/lib/blacklight/user_spec.rb +38 -4
  60. data/spec/models/bookmark_spec.rb +22 -17
  61. data/spec/spec_helper.rb +2 -0
  62. data/template.demo.rb +4 -9
  63. metadata +12 -6
  64. data/spec/data/sample_docs.yml +0 -655
@@ -10,9 +10,9 @@ module Blacklight
10
10
 
11
11
  self.collapse = true if self.collapse.nil?
12
12
  self.show = true if self.show.nil?
13
+ self.if ||= self.show
13
14
 
14
15
  super
15
16
  end
16
17
  end
17
18
  end
18
-
@@ -1,5 +1,5 @@
1
1
  module Blacklight
2
- class Configuration::SearchField < OpenStructWithHashAccess
2
+ class Configuration::SearchField < Blacklight::Configuration::SolrField
3
3
  def normalize! blacklight_config = nil
4
4
  # Some normalization, calculate display_label from key,
5
5
  # and make sure we have a qt from defaults.
@@ -7,6 +7,8 @@ module Blacklight
7
7
  self.field ||= self.key
8
8
  self.label ||= self.key.try(:titlecase)
9
9
  self.qt ||= blacklight_config.default_solr_params[:qt] if blacklight_config && blacklight_config.default_solr_params
10
+ self.if ||= self.include_in_simple_select
11
+ super
10
12
  end
11
13
 
12
14
  def validate!
@@ -14,4 +16,3 @@ module Blacklight
14
16
  end
15
17
  end
16
18
  end
17
-
@@ -2,6 +2,8 @@ module Blacklight
2
2
  class Configuration::SolrField < OpenStructWithHashAccess
3
3
  def normalize! blacklight_config = nil
4
4
  self.label ||= default_label
5
+ self.if = true if self.if.nil?
6
+ self.unless = false if self.unless.nil?
5
7
  self
6
8
  end
7
9
 
@@ -18,4 +20,3 @@ module Blacklight
18
20
  end
19
21
  end
20
22
  end
21
-
@@ -1,5 +1,5 @@
1
1
  module Blacklight
2
- class Configuration::SortField < OpenStructWithHashAccess
2
+ class Configuration::SortField < Blacklight::Configuration::SolrField
3
3
  def normalize! blacklight_config = nil
4
4
  self.sort ||= self.field
5
5
 
@@ -8,6 +8,7 @@ module Blacklight
8
8
  self.field ||= self.sort
9
9
 
10
10
  self.key ||= self.field
11
+ super
11
12
  end
12
13
 
13
14
  def validate!
@@ -19,6 +19,14 @@ module Blacklight
19
19
  end
20
20
  end
21
21
  end
22
+
23
+ initializer "blacklight.secret_key" do |app|
24
+ if app.respond_to?(:secrets)
25
+ Blacklight.secret_key ||= app.secrets.secret_key_base
26
+ elsif app.config.respond_to?(:secret_key_base)
27
+ Blacklight.secret_key ||= app.config.secret_key_base
28
+ end
29
+ end
22
30
 
23
31
  end
24
- end
32
+ end
@@ -9,6 +9,9 @@ module Blacklight
9
9
  # is not successful, raise this:
10
10
  class InvalidSolrID < RuntimeError
11
11
  end
12
+
13
+ class ExpiredSessionToken < Exception
14
+ end
12
15
 
13
16
  class ECONNREFUSED < ::Errno::ECONNREFUSED; end
14
17
 
@@ -7,11 +7,23 @@ module ActionDispatch::Routing
7
7
  # blacklight_for :catalog, only: [ :saved_searches, :solr_document ]
8
8
  # blacklight_for :catalog, constraints: {id: /[0-9]+/ }
9
9
  def blacklight_for(*resources)
10
+ raise_no_blacklight_secret_key unless Blacklight.secret_key
10
11
  options = resources.extract_options!
11
12
  resources.map!(&:to_sym)
12
13
 
13
14
  Blacklight::Routes.new(self, options.merge(resources: resources)).draw
14
15
 
15
16
  end
17
+
18
+ private
19
+ def raise_no_blacklight_secret_key #:nodoc:
20
+ raise <<-ERROR
21
+ Blacklight.secret_key was not set. Please add the following to an initializer:
22
+
23
+ Blacklight.secret_key = '#{SecureRandom.hex(64)}'
24
+
25
+ Please ensure you restarted your application after installing Blacklight or setting the key.
26
+ ERROR
27
+ end
16
28
  end
17
29
  end
@@ -201,27 +201,25 @@ module Blacklight
201
201
  # app level per_page and page to Solr rows and start.
202
202
  def add_paging_to_solr(solr_params, user_params)
203
203
 
204
- # Now any over-rides from current URL?
205
- solr_params[:rows] = user_params[:rows].to_i unless user_params[:rows].blank?
206
- solr_params[:rows] = user_params[:per_page].to_i unless user_params[:per_page].blank?
204
+ # user-provided parameters should override any default row
205
+ solr_params[:rows] = user_params[:rows].to_i unless user_params[:rows].blank?
206
+ solr_params[:rows] = user_params[:per_page].to_i unless user_params[:per_page].blank?
207
+
208
+ # configuration defaults should only set a default value, not override a value set elsewhere (e.g. search field parameters)
209
+ solr_params[:rows] ||= blacklight_config.default_per_page unless blacklight_config.default_per_page.blank?
210
+ solr_params[:rows] ||= blacklight_config.per_page.first unless blacklight_config.per_page.blank?
211
+
212
+ # set a reasonable default
213
+ Rails.logger.info "Solr :rows parameter not set (by the user, configuration, or default solr parameters); using 10 rows by default"
214
+ solr_params[:rows] ||= 10
207
215
 
208
- # Do we need to translate :page to Solr :start?
216
+ # ensure we don't excede the max page size
217
+ solr_params[:rows] = blacklight_config.max_per_page if solr_params[:rows].to_i > blacklight_config.max_per_page
209
218
  unless user_params[:page].blank?
210
- # already set solr_params["rows"] might not be the one we just set,
211
- # could have been from app defaults too. But we need one.
212
- # raising is consistent with prior RSolr magic keys behavior.
213
- # We could change this to default to 10, or to raise on startup
214
- # from config instead of at runtime.
215
- if solr_params[:rows].blank?
216
- raise Exception.new("To use pagination when no :per_page is supplied in the URL, :rows must be configured in blacklight_config default_solr_params")
217
- end
218
219
  solr_params[:start] = solr_params[:rows].to_i * (user_params[:page].to_i - 1)
219
220
  solr_params[:start] = 0 if solr_params[:start].to_i < 0
220
221
  end
221
222
 
222
- solr_params[:rows] ||= blacklight_config.per_page.first unless blacklight_config.per_page.blank?
223
-
224
- solr_params[:rows] = blacklight_config.max_per_page if solr_params[:rows].to_i > blacklight_config.max_per_page
225
223
  end
226
224
 
227
225
  ###
@@ -270,11 +268,14 @@ module Blacklight
270
268
  fq = case
271
269
  when (facet_config and facet_config.query)
272
270
  facet_config.query[value][:fq]
273
- when (facet_config and facet_config.date),
274
- (value.is_a?(TrueClass) or value.is_a?(FalseClass) or value == 'true' or value == 'false'),
271
+ when (facet_config and facet_config.date)
272
+ # in solr 3.2+, this could be replaced by a !term query
273
+ "#{prefix}#{facet_field}:#{RSolr.escape(value)}"
274
+ when (value.is_a?(DateTime) or value.is_a?(Date) or value.is_a?(Time))
275
+ "#{prefix}#{facet_field}:#{RSolr.escape(value.to_time.utc.strftime("%Y-%m-%dT%H:%M:%SZ"))}"
276
+ when (value.is_a?(TrueClass) or value.is_a?(FalseClass) or value == 'true' or value == 'false'),
275
277
  (value.is_a?(Integer) or (value.to_i.to_s == value if value.respond_to? :to_i)),
276
278
  (value.is_a?(Float) or (value.to_f.to_s == value if value.respond_to? :to_f))
277
- (value.is_a?(DateTime) or value.is_a?(Date) or value.is_a?(Time))
278
279
  "#{prefix}#{facet_field}:#{value}"
279
280
  when value.is_a?(Range)
280
281
  "#{prefix}#{facet_field}:[#{value.first} TO #{value.last}]"
@@ -38,15 +38,6 @@ module Blacklight::SearchFields
38
38
  blacklight_config.search_fields.values
39
39
  end
40
40
 
41
- # Returns suitable argument to options_for_select method, to create
42
- # an html select based on #search_field_list. Skips search_fields
43
- # marked :include_in_simple_select => false
44
- def search_field_options_for_select
45
- blacklight_config.search_fields.collect do |key, field_def|
46
- [field_def.label, field_def.key] unless field_def.include_in_simple_select == false
47
- end.compact
48
- end
49
-
50
41
  # Looks up a search field blacklight_config hash from search_field_list having
51
42
  # a certain supplied :key.
52
43
  def search_field_def_for_key(key)
@@ -151,7 +151,14 @@ module Blacklight::Solr::Document
151
151
  return @semantic_value_hash
152
152
  end
153
153
 
154
+ def destroyed?
155
+ false
156
+ end
154
157
 
158
+ def new_record?
159
+ false
160
+ end
161
+
155
162
  # Certain class-level methods needed for the document-specific
156
163
  # extendability architecture
157
164
  module ClassMethods
@@ -160,6 +167,14 @@ module Blacklight::Solr::Document
160
167
  def unique_key
161
168
  @unique_key ||= 'id'
162
169
  end
170
+
171
+ def primary_key
172
+ 'id'
173
+ end
174
+
175
+ def base_class
176
+ self
177
+ end
163
178
 
164
179
  # Returns array of hashes of registered extensions. Each hash
165
180
  # has a :module_obj key and a :condition_proc key. Usually this
@@ -100,4 +100,8 @@ module Blacklight::Solr::Document::Export
100
100
  def export_as(short_name)
101
101
  send("export_as_#{short_name.to_s}")
102
102
  end
103
+
104
+ def exports_as? short_name
105
+ respond_to? "export_as_#{short_name.to_s}"
106
+ end
103
107
  end
@@ -46,6 +46,7 @@
46
46
 
47
47
  module Blacklight::SolrHelper
48
48
  extend ActiveSupport::Concern
49
+ extend Deprecation
49
50
  include Blacklight::SearchFields
50
51
  include Blacklight::Facet
51
52
  include ActiveSupport::Benchmarkable
@@ -59,18 +60,6 @@ module Blacklight::SolrHelper
59
60
 
60
61
  end
61
62
 
62
- def force_to_utf8(value)
63
- case value
64
- when Hash
65
- value.each { |k, v| value[k] = force_to_utf8(v) }
66
- when Array
67
- value.each { |v| force_to_utf8(v) }
68
- when String
69
- value.force_encoding("utf-8") if value.respond_to?(:force_encoding)
70
- end
71
- value
72
- end
73
-
74
63
  ##
75
64
  # Execute a solr query
76
65
  # @see [RSolr::Client#send_and_receive]
@@ -80,6 +69,7 @@ module Blacklight::SolrHelper
80
69
  # @param [Hash] parameters for RSolr::Client#send_and_receive
81
70
  # @overload find(params)
82
71
  # @param [Hash] parameters for RSolr::Client#send_and_receive
72
+ # @return [Blacklight::SolrResponse] the solr response object
83
73
  def find(*args)
84
74
  # In later versions of Rails, the #benchmark method can do timing
85
75
  # better for us.
@@ -91,7 +81,7 @@ module Blacklight::SolrHelper
91
81
  key = blacklight_config.http_method == :post ? :data : :params
92
82
  res = blacklight_solr.send_and_receive(path, {key=>solr_params.to_hash, method:blacklight_config.http_method})
93
83
 
94
- solr_response = Blacklight::SolrResponse.new(force_to_utf8(res), solr_params)
84
+ solr_response = Blacklight::SolrResponse.new(res, solr_params, solr_document_model: blacklight_config.solr_document_model)
95
85
 
96
86
  Rails.logger.debug("Solr query: #{solr_params.inspect}")
97
87
  Rails.logger.debug("Solr response: #{solr_response.inspect}") if defined?(::BLACKLIGHT_VERBOSE_LOGGING) and ::BLACKLIGHT_VERBOSE_LOGGING
@@ -131,15 +121,14 @@ module Blacklight::SolrHelper
131
121
  when (solr_response.grouped? && solr_response.grouped.length == 1)
132
122
  [solr_response.grouped.first, []]
133
123
  else
134
- document_list = solr_response.docs.collect {|doc| SolrDocument.new(doc, solr_response)}
135
- [solr_response, document_list]
124
+ [solr_response, solr_response.documents]
136
125
  end
137
126
  end
138
127
 
139
128
 
140
129
  # a solr query method
141
130
  # given a user query,
142
- # Returns a solr response object
131
+ # @return [Blacklight::SolrResponse] the solr response object
143
132
  def query_solr(user_params = params || {}, extra_controller_params = {})
144
133
  solr_params = self.solr_search_params(user_params).merge(extra_controller_params)
145
134
 
@@ -167,22 +156,25 @@ module Blacklight::SolrHelper
167
156
 
168
157
  # a solr query method
169
158
  # retrieve a solr document, given the doc id
159
+ # @return [Blacklight::SolrResponse, Blacklight::SolrDocument] the solr response object and the first document
170
160
  def get_solr_response_for_doc_id(id=nil, extra_controller_params={})
171
161
  solr_params = solr_doc_params(id).merge(extra_controller_params)
172
162
  solr_response = find(blacklight_config.document_solr_path, solr_params)
173
- raise Blacklight::Exceptions::InvalidSolrID.new if solr_response.docs.empty?
174
- document = SolrDocument.new(solr_response.docs.first, solr_response)
175
- [solr_response, document]
163
+ raise Blacklight::Exceptions::InvalidSolrID.new if solr_response.documents.empty?
164
+ [solr_response, solr_response.documents.first]
165
+ end
166
+
167
+ def get_solr_response_for_document_ids(ids=[], extra_solr_params = {})
168
+ get_solr_response_for_field_values(blacklight_config.solr_document_model.unique_key, ids, extra_solr_params)
176
169
  end
177
170
 
178
171
  # given a field name and array of values, get the matching SOLR documents
172
+ # @return [Blacklight::SolrResponse, Array<Blacklight::SolrDocument>] the solr response object and a list of solr documents
179
173
  def get_solr_response_for_field_values(field, values, extra_solr_params = {})
180
- values = Array(values) unless values.respond_to? :each
181
-
182
- q = if values.empty?
174
+ q = if Array(values).empty?
183
175
  "NOT *:*"
184
176
  else
185
- "#{field}:(#{ values.to_a.map { |x| solr_param_quote(x)}.join(" OR ")})"
177
+ "#{field}:(#{ Array(values).map { |x| solr_param_quote(x)}.join(" OR ")})"
186
178
  end
187
179
 
188
180
  solr_params = {
@@ -199,8 +191,7 @@ module Blacklight::SolrHelper
199
191
  }.merge(extra_solr_params)
200
192
 
201
193
  solr_response = find(self.solr_search_params().merge(solr_params) )
202
- document_list = solr_response.docs.collect{|doc| SolrDocument.new(doc, solr_response) }
203
- [solr_response,document_list]
194
+ [solr_response, solr_response.documents]
204
195
  end
205
196
 
206
197
  # returns a params hash for a single facet field solr query.
@@ -241,6 +232,7 @@ module Blacklight::SolrHelper
241
232
 
242
233
  ##
243
234
  # Get the solr response when retrieving only a single facet field
235
+ # @return [Blacklight::SolrResponse] the solr response
244
236
  def get_facet_field_response(facet_field, user_params = params || {}, extra_controller_params = {})
245
237
  solr_params = solr_facet_params(facet_field, user_params, extra_controller_params)
246
238
  # Make the solr call
@@ -266,12 +258,14 @@ module Blacklight::SolrHelper
266
258
  :sort => response.params[:"f.#{facet_field}.facet.sort"] || response.params["facet.sort"]
267
259
  )
268
260
  end
261
+ deprecation_deprecate :get_facet_pagination
269
262
 
270
263
  # a solr query method
271
264
  # this is used when selecting a search result: we have a query and a
272
265
  # position in the search results and possibly some facets
273
266
  # Pass in an index where 1 is the first document in the list, and
274
267
  # the Blacklight app-level request params that define the search.
268
+ # @return [Blacklight::SolrDocument, nil] the found document or nil if not found
275
269
  def get_single_doc_via_search(index, request_params)
276
270
  solr_params = solr_search_params(request_params)
277
271
 
@@ -279,10 +273,12 @@ module Blacklight::SolrHelper
279
273
  solr_params[:rows] = 1
280
274
  solr_params[:fl] = '*'
281
275
  solr_response = find(solr_params)
282
- SolrDocument.new(solr_response.docs.first, solr_response) unless solr_response.docs.empty?
276
+ solr_response.documents.first
283
277
  end
278
+ deprecation_deprecate :get_single_doc_via_search
284
279
 
285
280
  # Get the previous and next document from a search result
281
+ # @return [Blacklight::SolrResponse, Array<Blacklight::SolrDocument>] the solr response and a list of the first and last document
286
282
  def get_previous_and_next_documents_for_search(index, request_params, extra_controller_params={})
287
283
 
288
284
  solr_params = solr_search_params(request_params).merge(extra_controller_params)
@@ -299,7 +295,7 @@ module Blacklight::SolrHelper
299
295
  solr_params[:facet] = false
300
296
  solr_response = find(solr_params)
301
297
 
302
- document_list = solr_response.docs.collect{|doc| SolrDocument.new(doc, solr_response) }
298
+ document_list = solr_response.documents
303
299
 
304
300
  # only get the previous doc if there is one
305
301
  prev_doc = document_list.first if index > 0
@@ -328,7 +324,7 @@ module Blacklight::SolrHelper
328
324
  solr_params = solr_opensearch_params().merge(extra_controller_params)
329
325
  response = find(solr_params)
330
326
  a = [solr_params[:q]]
331
- a << response.docs.map {|doc| doc[solr_params[:fl]].to_s }
327
+ a << response.documents.map {|doc| doc[solr_params[:fl]].to_s }
332
328
  end
333
329
 
334
330
 
@@ -377,4 +373,5 @@ module Blacklight::SolrHelper
377
373
  def should_add_to_solr field_name, field
378
374
  field.include_in_request || (field.include_in_request.nil? && blacklight_config.add_field_configuration_to_solr_request)
379
375
  end
376
+
380
377
  end
@@ -2,22 +2,26 @@ class Blacklight::SolrResponse < HashWithIndifferentAccess
2
2
 
3
3
  require 'blacklight/solr_response/pagination_methods'
4
4
 
5
- autoload :Spelling, 'blacklight/solr_response/spelling'
6
- autoload :Facets, 'blacklight/solr_response/facets'
7
- autoload :MoreLikeThis, 'blacklight/solr_response/more_like_this'
5
+ require 'blacklight/solr_response/response'
6
+ require 'blacklight/solr_response/spelling'
7
+ require 'blacklight/solr_response/facets'
8
+ require 'blacklight/solr_response/more_like_this'
8
9
  autoload :GroupResponse, 'blacklight/solr_response/group_response'
9
10
  autoload :Group, 'blacklight/solr_response/group'
10
11
 
11
12
  include PaginationMethods
13
+ include Spelling
14
+ include Facets
15
+ include Response
16
+ include MoreLikeThis
12
17
 
13
18
  attr_reader :request_params
14
- def initialize(data, request_params)
15
- super(data)
19
+ attr_accessor :solr_document_model
20
+
21
+ def initialize(data, request_params, options = {})
22
+ super(force_to_utf8(data))
16
23
  @request_params = request_params
17
- extend Spelling
18
- extend Facets
19
- extend Response
20
- extend MoreLikeThis
24
+ self.solr_document_model = options[:solr_document_model] || SolrDocument
21
25
  end
22
26
 
23
27
  def header
@@ -42,9 +46,9 @@ class Blacklight::SolrResponse < HashWithIndifferentAccess
42
46
  response['docs'] || []
43
47
  end
44
48
  end
45
-
46
- def spelling
47
- self['spelling']
49
+
50
+ def documents
51
+ docs.collect{|doc| solr_document_model.new(doc, self) }
48
52
  end
49
53
 
50
54
  def grouped
@@ -72,23 +76,21 @@ class Blacklight::SolrResponse < HashWithIndifferentAccess
72
76
  self.has_key? "grouped"
73
77
  end
74
78
 
75
- module Response
76
- def response
77
- self[:response] || {}
78
- end
79
-
80
- # short cut to response['numFound']
81
- def total
82
- response[:numFound].to_s.to_i
83
- end
84
-
85
- def start
86
- response[:start].to_s.to_i
87
- end
79
+ def export_formats
80
+ documents.map { |x| x.export_formats.keys }.flatten.uniq
81
+ end
82
+
83
+ private
88
84
 
89
- def empty?
90
- total == 0
85
+ def force_to_utf8(value)
86
+ case value
87
+ when Hash
88
+ value.each { |k, v| value[k] = force_to_utf8(v) }
89
+ when Array
90
+ value.each { |v| force_to_utf8(v) }
91
+ when String
92
+ value.force_encoding("utf-8") if value.respond_to?(:force_encoding)
93
+ end
94
+ value
91
95
  end
92
-
93
- end
94
96
  end