blacklight 5.9.3 → 5.9.4

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -3
  3. data/Rakefile +1 -2
  4. data/VERSION +1 -1
  5. data/app/helpers/blacklight/blacklight_helper_behavior.rb +4 -2
  6. data/app/helpers/blacklight/configuration_helper_behavior.rb +5 -7
  7. data/app/models/bookmark.rb +4 -1
  8. data/app/models/search.rb +6 -3
  9. data/app/views/catalog/_home_text.html.erb +48 -8
  10. data/app/views/catalog/_sms_form.html.erb +1 -1
  11. data/blacklight.gemspec +1 -1
  12. data/config/jetty.yml +3 -0
  13. data/doc/Adding-new-document-actions.md +94 -0
  14. data/doc/Atom-Responses.md +90 -0
  15. data/doc/Blacklight-Add-ons.md +23 -0
  16. data/doc/Blacklight-configuration.md +411 -0
  17. data/doc/Blacklight-on-Heroku.md +100 -0
  18. data/doc/Blacklight-out-of-the-box.md +47 -0
  19. data/doc/Bookmarks.md +1 -0
  20. data/doc/Code4Lib-2014.md +94 -0
  21. data/doc/Configuration---Facet-Fields.md +130 -0
  22. data/doc/Configuration---Results-View.md +224 -0
  23. data/doc/Configuration---Solr-fields.md +106 -0
  24. data/doc/Configuring-and-Customizing-Blacklight.md +257 -0
  25. data/doc/Configuring-rails-routes.md +13 -0
  26. data/doc/Contributing-to-Blacklight.md +43 -0
  27. data/doc/Examples.md +120 -0
  28. data/doc/Extending-or-Modifying-Blacklight-Search-Behavior.md +141 -0
  29. data/doc/Home.md +100 -0
  30. data/doc/How-to-release-a-version.md +45 -0
  31. data/doc/Indexing-your-data-into-solr.md +36 -0
  32. data/doc/Internationalization.md +32 -0
  33. data/doc/JSON-API.md +83 -0
  34. data/doc/Pagination.md +52 -0
  35. data/doc/Providing-your-own-view-templates.md +69 -0
  36. data/doc/Quickstart.md +153 -0
  37. data/doc/README_SOLR.md +245 -0
  38. data/doc/Saved-Searches.md +5 -0
  39. data/doc/Solr-Configuration.md +154 -0
  40. data/doc/Sunspot-for-indexing.md +46 -0
  41. data/doc/Support.md +33 -0
  42. data/doc/Theming.md +62 -0
  43. data/doc/Understanding-Rails-and-Blacklight.md +75 -0
  44. data/doc/User-Authentication.md +60 -0
  45. data/doc/_Sidebar.md +9 -0
  46. data/doc/testing.md +58 -0
  47. data/lib/blacklight.rb +11 -3
  48. data/lib/blacklight/catalog.rb +16 -5
  49. data/lib/blacklight/catalog/search_context.rb +2 -0
  50. data/lib/blacklight/configuration/facet_field.rb +1 -1
  51. data/lib/blacklight/configuration/search_field.rb +1 -1
  52. data/lib/blacklight/routes.rb +3 -1
  53. data/lib/blacklight/solr/document.rb +24 -8
  54. data/lib/blacklight/solr_repository.rb +2 -2
  55. data/lib/blacklight/utils.rb +23 -0
  56. data/lib/generators/blacklight/install_generator.rb +1 -1
  57. data/lib/generators/blacklight/models_generator.rb +3 -1
  58. data/lib/generators/blacklight/templates/config/jetty.yml +3 -0
  59. data/spec/controllers/catalog_controller_spec.rb +9 -20
  60. data/spec/helpers/blacklight_helper_spec.rb +44 -0
  61. data/spec/helpers/configuration_helper_spec.rb +7 -0
  62. data/spec/lib/blacklight/configuration_spec.rb +33 -6
  63. data/spec/test_app_templates/lib/generators/test_app_generator.rb +1 -1
  64. data/tasks/blacklight.rake +6 -4
  65. metadata +38 -4
data/doc/testing.md ADDED
@@ -0,0 +1,58 @@
1
+ ## Using Blacklight source checkout as gem for development
2
+
3
+ The ordinary install instructions install the BL gem (which is not
4
+ full source code) in wherever your system installs gems.
5
+
6
+ Sometimes, especially for development, it's useful to check out
7
+ a complete copy of the blacklight source code, and link your app
8
+ to that as a 'gem' instead.
9
+
10
+ Checkout the code:
11
+
12
+ $ git clone git@github.com:projectblacklight/blacklight.git
13
+
14
+
15
+ ## Automatically generate a test application (and run the tests)
16
+
17
+ To run the Blacklight test suite, Blacklight comes with a rake task that creates local dependencies like a Solr with indexed test data and a test Rails application, and then runs tests.
18
+
19
+ Requirements:
20
+
21
+ * Java (1.6 or above) (for Solr)
22
+ * phantomjs (used by integration tests, you may be able to install with your local package manager, for instance on OSX with `brew install phantomjs`)
23
+
24
+ Then from the root directory of your blacklight git checkout:
25
+
26
+ ```
27
+ bundle exec rake
28
+ ```
29
+
30
+ This ensure a test Solr exists and is running, creates a test application, and loads the fixtures and then runs specs and cucumber tests.
31
+
32
+ ### Step by step, with more control
33
+
34
+ `rake ci` will, every time you run it, re-index test data in solr, and re-build the test application. Re-building the test application in particular is kind of time-consuming. You may prefer to set up the environment and run tests as separate steps, to make development easier.
35
+
36
+ To create the dummy test app:
37
+
38
+ $ bundle exec rake engine_cart:generate
39
+
40
+ (If you have an existing dummy app that is outdated, `rake engine_cart:clean` first, then `rake engine_cart:generate).
41
+
42
+ Then start up the test jetty, on the port that tests will look for it, with:
43
+
44
+ $ RAILS_ENV=test bundle exec rake jetty:start
45
+
46
+ If you haven't yet indexed the test data in the test jetty. (??? Not sure how to do this. Run `rake ci` once to make sure test data has been indexed). Run `rake jetty:stop` when you're done with it.
47
+
48
+ Then run all the specs with:
49
+
50
+ $ bundle exec rake spec
51
+
52
+ Or just run one spec
53
+
54
+ $ bundle exec rake spec SPEC=just/one_spec.rb
55
+
56
+ And stop your test solr when you're done with it:
57
+
58
+ $ bundle exec rake jetty:stop
data/lib/blacklight.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  require 'kaminari'
3
3
  require 'rsolr'
4
+ require 'deprecation'
5
+ require 'blacklight/utils'
6
+
4
7
  module Blacklight
5
8
 
6
9
  autoload :Configurable, 'blacklight/configurable'
@@ -25,8 +28,7 @@ module Blacklight
25
28
  autoload :DocumentPresenter, 'blacklight/document_presenter'
26
29
 
27
30
  autoload :Routes, 'blacklight/routes'
28
-
29
- autoload :OpenStructWithHashAccess, 'blacklight/utils'
31
+
30
32
  autoload :SolrResponse, 'blacklight/solr_response'
31
33
  autoload :Facet, 'blacklight/facet'
32
34
 
@@ -92,7 +94,13 @@ module Blacklight
92
94
  end
93
95
 
94
96
  def self.logger
95
- ::Rails.logger
97
+ @logger ||= begin
98
+ ::Rails.logger if defined? Rails and Rails.respond_to? :logger
99
+ end
100
+ end
101
+
102
+ def self.logger= logger
103
+ @logger = logger
96
104
  end
97
105
 
98
106
  #############
@@ -33,7 +33,7 @@ module Blacklight::Catalog
33
33
  (@response, @document_list) = get_search_results
34
34
 
35
35
  respond_to do |format|
36
- format.html { preferred_view }
36
+ format.html { store_preferred_view }
37
37
  format.rss { render :layout => false }
38
38
  format.atom { render :layout => false }
39
39
  format.json do
@@ -45,7 +45,8 @@ module Blacklight::Catalog
45
45
  end
46
46
  end
47
47
 
48
- # get single document from the solr index
48
+ # get a single document from the index
49
+ # to add responses for formats other than html or json see _Blacklight::Document::Export_
49
50
  def show
50
51
  @response, @document = get_solr_response_for_doc_id params[:id]
51
52
 
@@ -134,13 +135,23 @@ module Blacklight::Catalog
134
135
  # do not specifiy the view, set the view parameter to the value stored in the
135
136
  # session. This enables a user with a session to do subsequent searches and have
136
137
  # them default to the last used view.
137
- def preferred_view
138
+ def store_preferred_view
138
139
  session[:preferred_view] = params[:view] if params[:view]
139
- params[:view] ||= session[:preferred_view]
140
140
  end
141
141
 
142
+ alias_method :preferred_view, :store_preferred_view
143
+ deprecation_deprecate :preferred_view
144
+
142
145
  ##
143
- # Render additional response formats, as provided by the blacklight configuration
146
+ # Render additional response formats for the index action, as provided by the
147
+ # blacklight configuration
148
+ #
149
+ # example:
150
+ #
151
+ # config.index.respond_to.txt = Proc.new { render text: "A list of docs." }
152
+ #
153
+ # Make sure your format has a well known mime-type or is registered in
154
+ # config/initializers/mime_types.rb
144
155
  def additional_response_formats format
145
156
  blacklight_config.index.respond_to.each do |key, config|
146
157
  format.send key do
@@ -101,6 +101,8 @@ module Blacklight::Catalog::SearchContext
101
101
  @previous_document = documents.first
102
102
  @next_document = documents.last
103
103
  end
104
+ rescue Blacklight::Exceptions::InvalidRequest => e
105
+ logger.warn "Unable to setup next and previous documents: #{e}"
104
106
  end
105
107
 
106
108
  end
@@ -10,7 +10,7 @@ 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
+ self.if = self.show if self.if.nil?
14
14
 
15
15
  super
16
16
  end
@@ -7,7 +7,7 @@ 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
10
+ self.if = self.include_in_simple_select if self.if.nil?
11
11
  super
12
12
  end
13
13
 
@@ -19,7 +19,9 @@ module Blacklight
19
19
  # klass.default_route_sets += [:widget_routing]
20
20
  # end
21
21
  # def widget_routing(primary_resource)
22
- # get "#{primary_resource}/widget", "#{primary_resource}#widget"
22
+ # add_routes do |options|
23
+ # get "#{primary_resource}/widget", "#{primary_resource}#widget"
24
+ # end
23
25
  # end
24
26
  # end
25
27
  # Blacklight::Routes.send(:include, MyWidget::Routes)
@@ -34,7 +34,7 @@ module Blacklight::Solr::Document
34
34
  include Blacklight::Solr::Document::Extensions
35
35
  end
36
36
 
37
- attr_reader :solr_response
37
+ attr_reader :solr_response, :_source
38
38
 
39
39
  def initialize(source_doc={}, solr_response=nil)
40
40
  @_source = source_doc.with_indifferent_access
@@ -54,11 +54,23 @@ module Blacklight::Solr::Document
54
54
  # If a method is missing, it gets sent to @_source
55
55
  # with all of the original params and block
56
56
  def method_missing(m, *args, &b)
57
- @_source.send(m, *args, &b)
57
+ if _source_responds_to?(m)
58
+ _source.send(m, *args, &b)
59
+ else
60
+ super
61
+ end
62
+ end
63
+
64
+ def respond_to_missing? *args
65
+ _source_responds_to?(*args) || super
58
66
  end
59
67
 
60
68
  def [] *args
61
- @_source.send :[], *args
69
+ _source.send :[], *args
70
+ end
71
+
72
+ def _read_attribute(attr)
73
+ self[attr]
62
74
  end
63
75
 
64
76
  # Helper method to check if value/multi-values exist for a given key.
@@ -83,8 +95,9 @@ module Blacklight::Solr::Document
83
95
  end
84
96
 
85
97
  def key? k
86
- @_source.key? k
98
+ _source.key? k
87
99
  end
100
+ alias_method :has_key?, :key?
88
101
 
89
102
  def has_highlight_field? k
90
103
  return false if @solr_response['highlighting'].blank? or @solr_response['highlighting'][self.id].blank?
@@ -126,7 +139,7 @@ module Blacklight::Solr::Document
126
139
  end
127
140
 
128
141
  def as_json(options = nil)
129
- @_source.as_json(options)
142
+ _source.as_json(options)
130
143
  end
131
144
 
132
145
  def to_partial_path
@@ -203,7 +216,10 @@ module Blacklight::Solr::Document
203
216
  @field_semantics ||= {}
204
217
  end
205
218
  end
206
-
207
-
208
-
219
+ private
220
+
221
+ def _source_responds_to? *args
222
+ _source && self != _source && _source.respond_to?(*args)
223
+ end
224
+
209
225
  end
@@ -49,8 +49,8 @@ module Blacklight
49
49
 
50
50
  solr_response = blacklight_config.solr_response_model.new(res, solr_params, solr_document_model: blacklight_config.solr_document_model)
51
51
 
52
- Rails.logger.debug("Solr query: #{solr_params.inspect}")
53
- Rails.logger.debug("Solr response: #{solr_response.inspect}") if defined?(::BLACKLIGHT_VERBOSE_LOGGING) and ::BLACKLIGHT_VERBOSE_LOGGING
52
+ Blacklight.logger.debug("Solr query: #{solr_params.inspect}")
53
+ Blacklight.logger.debug("Solr response: #{solr_response.inspect}") if defined?(::BLACKLIGHT_VERBOSE_LOGGING) and ::BLACKLIGHT_VERBOSE_LOGGING
54
54
  solr_response
55
55
  end
56
56
  rescue Errno::ECONNREFUSED => e
@@ -1,5 +1,28 @@
1
1
  require 'ostruct'
2
2
  module Blacklight
3
+
4
+ module Utils
5
+ def self.needs_attr_accessible?
6
+ if rails_3?
7
+ !strong_parameters_enabled?
8
+ else
9
+ protected_attributes_enabled?
10
+ end
11
+ end
12
+
13
+ def self.rails_3?
14
+ Rails::VERSION::MAJOR == 3
15
+ end
16
+
17
+ def self.strong_parameters_enabled?
18
+ defined?(ActionController::StrongParameters)
19
+ end
20
+
21
+ def self.protected_attributes_enabled?
22
+ defined?(ActiveModel::MassAssignmentSecurity)
23
+ end
24
+ end
25
+
3
26
  ##
4
27
  # An OpenStruct that responds to common Hash methods
5
28
  class OpenStructWithHashAccess < OpenStruct
@@ -72,7 +72,7 @@ module Blacklight
72
72
 
73
73
  def generate_blacklight_marc_demo
74
74
  if options[:marc]
75
- gem "blacklight-marc", "~> 5.0"
75
+ gem "blacklight-marc", "5.5.0"
76
76
 
77
77
  Bundler.with_clean_env do
78
78
  run "bundle install"
@@ -69,7 +69,9 @@ This generator makes the following changes to your application:
69
69
  file_path = "app/models/#{model_name.underscore}.rb"
70
70
  if File.exists?(file_path)
71
71
  inject_into_class file_path, model_name.classify do
72
- "\n attr_accessible :email, :password, :password_confirmation if Rails::VERSION::MAJOR < 4\n" +
72
+ "\n if Blacklight::Utils.needs_attr_accessible?\n" +
73
+ "\n attr_accessible :email, :password, :password_confirmation" +
74
+ "\n end\n" +
73
75
  "# Connects this user object to Blacklights Bookmarks. " +
74
76
  "\n include Blacklight::User\n"
75
77
  end
@@ -1,10 +1,13 @@
1
1
  development:
2
2
  startup_wait: 15
3
3
  jetty_port: 8983
4
+ java_version: ">= 1.7"
4
5
  test:
5
6
  startup_wait: 60
6
7
  jetty_port: <%= ENV['TEST_JETTY_PORT'] || 8888 %>
7
8
  <%= ENV['TEST_JETTY_PATH'] ? "jetty_home: " + ENV['TEST_JETTY_PATH'] : '' %>
9
+ java_version: ">= 1.7"
8
10
  production:
9
11
  startup_wait: 15
10
12
  jetty_port: 8983
13
+ java_version: ">= 1.7"
@@ -33,26 +33,6 @@ describe CatalogController do
33
33
  get :index, q: 'foo', view: 'gallery'
34
34
  expect(session[:preferred_view]).to eq 'gallery'
35
35
  end
36
-
37
- context "when they have a preferred view" do
38
- before do
39
- session[:preferred_view] = 'gallery'
40
- end
41
-
42
- context "and no view is specified" do
43
- it "should use the saved preference" do
44
- get :index, q: 'foo'
45
- expect(controller.params[:view]).to eq 'gallery'
46
- end
47
- end
48
-
49
- context "and a view is specified" do
50
- it "should use the saved preference" do
51
- get :index, q: 'foo', view: 'list'
52
- expect(controller.params[:view]).to eq 'list'
53
- end
54
- end
55
- end
56
36
  end
57
37
 
58
38
  # check each user manipulated parameter
@@ -313,6 +293,15 @@ describe CatalogController do
313
293
  get :show, :id => doc_id
314
294
  expect(assigns[:next_document]).to_not be_nil
315
295
  end
296
+
297
+ it "should not break if solr returns an exception" do
298
+ allow(controller).to receive(:get_previous_and_next_documents_for_search) {
299
+ raise Blacklight::Exceptions::InvalidRequest.new "Error"
300
+ }
301
+ get :show, :id => doc_id
302
+ expect(assigns[:previous_document]).to be_nil
303
+ expect(assigns[:next_document]).to be_nil
304
+ end
316
305
  end
317
306
 
318
307
  # NOTE: status code is always 200 in isolation mode ...
@@ -612,6 +612,50 @@ describe BlacklightHelper do
612
612
  end
613
613
  end
614
614
 
615
+ describe "#document_index_view_type" do
616
+ it "should default to the default view" do
617
+ allow(helper).to receive(:document_index_views).and_return(a: 1, b: 2)
618
+ allow(helper).to receive(:default_document_index_view_type).and_return(:xyz)
619
+ expect(helper.document_index_view_type).to eq :xyz
620
+ end
621
+
622
+ it "should use the query parameter" do
623
+ allow(helper).to receive(:document_index_views).and_return(a: 1, b: 2)
624
+ expect(helper.document_index_view_type(view: :a)).to eq :a
625
+ end
626
+
627
+ it "should use the default view if the requested view is not available" do
628
+ allow(helper).to receive(:default_document_index_view_type).and_return(:xyz)
629
+ allow(helper).to receive(:document_index_views).and_return(a: 1, b: 2)
630
+ expect(helper.document_index_view_type(view: :c)).to eq :xyz
631
+ end
632
+
633
+ context "when they have a preferred view" do
634
+ before do
635
+ session[:preferred_view] = :b
636
+ end
637
+
638
+ context "and no view is specified" do
639
+ it "should use the saved preference" do
640
+ allow(helper).to receive(:document_index_views).and_return(a: 1, b: 2, c: 3)
641
+ expect(helper.document_index_view_type).to eq :b
642
+ end
643
+
644
+ it "should use the default view if the preference is not available" do
645
+ allow(helper).to receive(:document_index_views).and_return(a: 1)
646
+ expect(helper.document_index_view_type).to eq :a
647
+ end
648
+ end
649
+
650
+ context "and a view is specified" do
651
+ it "should use the query parameter" do
652
+ allow(helper).to receive(:document_index_views).and_return(a: 1, b: 2, c: 3)
653
+ expect(helper.document_index_view_type(view: :c)).to eq :c
654
+ end
655
+ end
656
+ end
657
+ end
658
+
615
659
  describe "#presenter_class" do
616
660
  before do
617
661
  allow(helper).to receive(:blacklight_config).and_return(blacklight_config)
@@ -150,6 +150,13 @@ describe BlacklightConfigurationHelper do
150
150
 
151
151
  label = helper.solr_field_label :key_a, :key_b, "default text"
152
152
  end
153
+
154
+ it "should compact nil keys (fixes rails/rails#19419)" do
155
+ allow(helper).to receive(:t).with(:key_a, default: [:key_b])
156
+
157
+ label = helper.solr_field_label :key_a, nil, :key_b
158
+
159
+ end
153
160
  end
154
161
 
155
162
  describe "#default_per_page" do
@@ -213,11 +213,25 @@ describe "Blacklight::Configuration" do
213
213
  "another_field_facet" => {},
214
214
  "a_facet_field" => {},
215
215
  })
216
- expect { |b| @config.add_index_field "*_facet", &b }.to yield_control.twice
217
-
218
- expect(@config.index_fields.keys).to eq ["some_field_facet", "another_field_facet"]
216
+ expect { |b| @config.add_facet_field "*_facet", &b }.to yield_control.twice
217
+ expect(@config.facet_fields.keys).to eq ["some_field_facet", "another_field_facet"]
219
218
  end
220
219
 
220
+ describe "if/unless conditions with legacy show parameter" do
221
+ it "should be hidden if the if condition is false" do
222
+ expect(@config.add_facet_field("hidden", if: false).if).to eq false
223
+ expect(@config.add_facet_field("hidden_with_legacy", if: false, show: true).if).to eq false
224
+ end
225
+
226
+ it "should be true if the if condition is true" do
227
+ expect(@config.add_facet_field("hidden", if: true).if).to eq true
228
+ expect(@config.add_facet_field("hidden_with_legacy", if: true, show: false).if).to eq true
229
+ end
230
+
231
+ it "should be true if the if condition is missing" do
232
+ expect(@config.add_facet_field("hidden", show: true).if).to eq true
233
+ end
234
+ end
221
235
  end
222
236
 
223
237
  describe "add_index_field" do
@@ -261,7 +275,6 @@ describe "Blacklight::Configuration" do
261
275
 
262
276
  expect(@config.index_fields.keys).to eq ["some_field_display", "another_field_display"]
263
277
  end
264
-
265
278
  end
266
279
 
267
280
  describe "add_show_field" do
@@ -370,8 +383,22 @@ describe "Blacklight::Configuration" do
370
383
 
371
384
  expect(@config.search_fields["author_name"].label).to eq "Author Name"
372
385
  end
373
-
374
-
386
+
387
+ describe "if/unless conditions with legacy include_in_simple_search" do
388
+ it "should be hidden if the if condition is false" do
389
+ expect(@config.add_search_field("hidden", if: false).if).to eq false
390
+ expect(@config.add_search_field("hidden_with_legacy", if: false, include_in_simple_search: true).if).to eq false
391
+ end
392
+
393
+ it "should be true if the if condition is true" do
394
+ expect(@config.add_search_field("hidden", if: true).if).to eq true
395
+ expect(@config.add_search_field("hidden_with_legacy", if: true, include_in_simple_search: false).if).to eq true
396
+ end
397
+
398
+ it "should be true if the if condition is missing" do
399
+ expect(@config.add_search_field("hidden", include_in_simple_search: true).if).to eq true
400
+ end
401
+ end
375
402
  end
376
403
 
377
404
  describe "add_sort_field" do