blacklight 6.18.0 → 6.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop_todo.yml +1 -1
  3. data/.travis.yml +5 -0
  4. data/Gemfile +1 -0
  5. data/VERSION +1 -1
  6. data/app/controllers/concerns/blacklight/bookmarks.rb +17 -3
  7. data/app/controllers/concerns/blacklight/catalog.rb +4 -2
  8. data/app/controllers/concerns/blacklight/controller.rb +10 -7
  9. data/app/controllers/concerns/blacklight/search_context.rb +5 -3
  10. data/app/controllers/concerns/blacklight/token_based_user.rb +3 -1
  11. data/app/models/blacklight/suggest_search.rb +3 -14
  12. data/app/models/concerns/blacklight/document.rb +3 -1
  13. data/app/models/concerns/blacklight/suggest/response.rb +5 -3
  14. data/app/presenters/blacklight/index_presenter.rb +3 -3
  15. data/blacklight.gemspec +5 -4
  16. data/lib/blacklight.rb +4 -4
  17. data/lib/blacklight/abstract_repository.rb +13 -1
  18. data/lib/blacklight/configuration.rb +2 -1
  19. data/lib/blacklight/configuration/fields.rb +46 -41
  20. data/lib/blacklight/engine.rb +2 -1
  21. data/lib/blacklight/solr/repository.rb +36 -3
  22. data/lib/generators/blacklight/assets_generator.rb +7 -2
  23. data/lib/generators/blacklight/install_generator.rb +1 -1
  24. data/lib/generators/blacklight/templates/catalog_controller.rb +3 -0
  25. data/lib/railties/blacklight.rake +11 -16
  26. data/spec/controllers/bookmarks_controller_spec.rb +35 -0
  27. data/spec/models/blacklight/configuration_spec.rb +81 -79
  28. data/spec/models/blacklight/solr/repository_spec.rb +11 -4
  29. data/spec/models/blacklight/suggest/response_spec.rb +5 -4
  30. data/spec/models/blacklight/suggest_search_spec.rb +6 -13
  31. data/spec/presenters/index_presenter_spec.rb +9 -0
  32. data/spec/spec_helper.rb +10 -6
  33. data/tasks/blacklight.rake +4 -4
  34. metadata +36 -16
@@ -28,7 +28,8 @@ module Blacklight
28
28
  end
29
29
 
30
30
  initializer "blacklight.assets.precompile" do |app|
31
- app.config.assets.precompile += %w(favicon.ico)
31
+ # When Rails has been generated in API mode, it does not have sprockets available
32
+ app.config.assets.precompile += %w(favicon.ico) if defined? Sprockets
32
33
  end
33
34
 
34
35
  Blacklight::Engine.config.sms_mappings = {
@@ -22,8 +22,31 @@ module Blacklight::Solr
22
22
  send_and_receive blacklight_config.solr_path, params.reverse_merge(qt: blacklight_config.qt)
23
23
  end
24
24
 
25
+ # @param [Hash] params
26
+ # @return [Blacklight::Suggest::Response]
27
+ def suggestions(request_params)
28
+ suggest_results = connection.send_and_receive(suggest_handler_path, params: request_params)
29
+ Blacklight::Suggest::Response.new suggest_results, request_params, suggest_handler_path, suggester_name
30
+ end
31
+
32
+ ##
33
+ # Gets a list of available fields
34
+ # @return [Hash]
35
+ def reflect_fields
36
+ send_and_receive('admin/luke', params: { fl: '*', 'json.nl' => 'map' })['fields']
37
+ end
38
+
39
+ ##
40
+ # @return [boolean] true if the repository is reachable
41
+ def ping
42
+ response = connection.send_and_receive 'admin/ping', {}
43
+ Blacklight.logger.info("Ping [#{connection.uri}] returned: '#{response['status']}'")
44
+ response['status'] == "OK"
45
+ end
46
+
25
47
  ##
26
48
  # Execute a solr query
49
+ # TODO: Make this private after we have a way to abstract admin/luke and ping
27
50
  # @see [RSolr::Client#send_and_receive]
28
51
  # @overload find(solr_path, params)
29
52
  # Execute a solr query at the given path with the parameters
@@ -51,8 +74,18 @@ module Blacklight::Solr
51
74
 
52
75
  protected
53
76
 
54
- def build_connection
55
- RSolr.connect(connection_config.merge(adapter: connection_config[:http_adapter]))
56
- end
77
+ ##
78
+ # @return [String]
79
+ def suggest_handler_path
80
+ blacklight_config.autocomplete_path
81
+ end
82
+
83
+ def suggester_name
84
+ blacklight_config.autocomplete_suggester
85
+ end
86
+
87
+ def build_connection
88
+ RSolr.connect(connection_config.merge(adapter: connection_config[:http_adapter]))
89
+ end
57
90
  end
58
91
  end
@@ -1,8 +1,13 @@
1
- # frozen_string_literal: true
2
1
  module Blacklight
3
2
  class Assets < Rails::Generators::Base
4
3
  source_root File.expand_path('../templates', __FILE__)
5
-
4
+
5
+ # This could be skipped if you want to use webpacker
6
+ def add_javascript_dependencies
7
+ gem 'bootstrap-sass', '~> 3.0'
8
+ gem 'twitter-typeahead-rails', '0.11.1.pre.corejavascript'
9
+ end
10
+
6
11
  def assets
7
12
  copy_file "blacklight.scss", "app/assets/stylesheets/blacklight.scss"
8
13
 
@@ -12,7 +12,7 @@ module Blacklight
12
12
  class_option :devise , type: :boolean, default: false, aliases: "-d", desc: "Use Devise as authentication logic."
13
13
  class_option :jettywrapper, type: :boolean, default: false, desc: "Use jettywrapper to download and control Jetty"
14
14
  class_option :marc , type: :boolean, default: false, aliases: "-m", desc: "Generate MARC-based demo ."
15
- class_option :'skip-assets', type: :boolean, default: false, desc: "Skip generating javascript and css assets into the application"
15
+ class_option :'skip-assets', type: :boolean, default: !defined?(Sprockets), desc: "Skip generating javascript and css assets into the application"
16
16
  class_option :'skip-solr', type: :boolean, default: false, desc: "Skip generating solr configurations."
17
17
 
18
18
  desc <<-EOS
@@ -190,5 +190,8 @@ class <%= controller_name.classify %>Controller < ApplicationController
190
190
  # Configuration for autocomplete suggestor
191
191
  config.autocomplete_enabled = true
192
192
  config.autocomplete_path = 'suggest'
193
+ # if the name of the solr.SuggestComponent provided in your solrcongig.xml is not the
194
+ # default 'mySuggester', uncomment and provide it below
195
+ # config.autocomplete_suggester = 'mySuggester'
193
196
  end
194
197
  end
@@ -2,11 +2,11 @@
2
2
  namespace :blacklight do
3
3
  # task to clean out old, unsaved searches
4
4
  # rake blacklight:delete_old_searches[days_old]
5
- # example cron entry to delete searches older than 7 days at 2:00 AM every day:
5
+ # example cron entry to delete searches older than 7 days at 2:00 AM every day:
6
6
  # 0 2 * * * cd /path/to/your/app && /path/to/rake blacklight:delete_old_searches[7] RAILS_ENV=your_env
7
7
  desc "Removes entries in the searches table that are older than the number of days given."
8
8
  task :delete_old_searches, [:days_old] => [:environment] do |t, args|
9
- args.with_defaults(:days_old => 7)
9
+ args.with_defaults(:days_old => 7)
10
10
  Search.delete_old_searches(args[:days_old].to_i)
11
11
  end
12
12
 
@@ -24,24 +24,19 @@ namespace :blacklight do
24
24
 
25
25
  namespace :check do
26
26
  desc "Check the Solr connection and controller configuration"
27
- task :solr, [:controller_name] => [:environment] do |_, args|
28
- errors = 0
29
- verbose = ENV.fetch('VERBOSE', false).present?
30
-
31
- conn = Blacklight.default_index.connection
32
- puts "[#{conn.uri}]"
33
-
34
- print " - admin/ping: "
27
+ task :solr, [:controller_name] => [:environment] do
35
28
  begin
36
- response = conn.send_and_receive 'admin/ping', {}
37
- puts response['status']
38
- errors += 1 unless response['status'] == "OK"
29
+ conn = Blacklight.default_index
30
+ if conn.ping
31
+ puts "OK"
32
+ else
33
+ puts "Unable to reach: #{conn.uri}"
34
+ exit 1
35
+ end
39
36
  rescue => e
40
- errors += 1
41
37
  puts e.to_s
38
+ exit 1
42
39
  end
43
-
44
- exit 1 if errors > 0
45
40
  end
46
41
 
47
42
  task :controller, [:controller_name] => [:environment] do |_, args|
@@ -25,6 +25,25 @@ describe BookmarksController do
25
25
  expect(response.code).to eq "500"
26
26
  end
27
27
  end
28
+
29
+ describe "create" do
30
+ it "can create bookmarks via params bookmarks attribute" do
31
+ @controller.send(:current_or_guest_user).save
32
+ put :create, xhr: true, params: {
33
+ id: "notused",
34
+ bookmarks: [
35
+ { document_id: "2007020969", document_type: "SolrDocument" },
36
+ { document_id: "2007020970", document_type: "SolrDocument" },
37
+ { document_id: "2007020971", document_type: "SolrDocument" }
38
+ ],
39
+ format: :js
40
+ }
41
+
42
+ expect(response).to be_success
43
+ expect(response.code).to eq "200"
44
+ expect(JSON.parse(response.body)["bookmarks"]["count"]).to eq 3
45
+ end
46
+ end
28
47
 
29
48
  describe "delete" do
30
49
  before do
@@ -39,6 +58,22 @@ describe BookmarksController do
39
58
  expect(JSON.parse(response.body)["bookmarks"]["count"]).to eq 0
40
59
  end
41
60
 
61
+ it "can handle bookmark deletion via :bookmarks param" do
62
+ class FooDocument < SolrDocument; end
63
+ @controller.send(:current_or_guest_user).bookmarks.create! document_id: '2007020970', document_type: "FooDocument"
64
+ delete :destroy, xhr: true, params: {
65
+ id: 'notused',
66
+ bookmarks: [
67
+ { document_id: '2007020969', document_type: 'SolrDocument' },
68
+ { document_id: '2007020970', document_type: 'FooDocument' }
69
+ ],
70
+ format: :js
71
+ }
72
+ expect(response).to be_success
73
+ expect(response.code).to eq "200"
74
+ expect(JSON.parse(response.body)["bookmarks"]["count"]).to eq 0
75
+ end
76
+
42
77
  it "has a 500 status code when delete is not success" do
43
78
  bm = instance_double(Bookmark)
44
79
  allow(@controller).to receive_message_chain(:current_or_guest_user, :existing_bookmark_for).and_return(bm)
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe "Blacklight::Configuration" do
4
-
4
+
5
5
  before(:each) do
6
- @config = Blacklight::Configuration.new
6
+ @config = config
7
7
  end
8
8
 
9
+ let(:config) { Blacklight::Configuration.new }
10
+
9
11
  it "supports arbitrary configuration values" do
10
12
  @config.a = 1
11
13
 
@@ -78,7 +80,7 @@ describe "Blacklight::Configuration" do
78
80
  it "defaults to 5" do
79
81
  expect(Blacklight::Configuration.new.spell_max).to eq 5
80
82
  end
81
-
83
+
82
84
  it "accepts config'd value" do
83
85
  expect(Blacklight::Configuration.new(:spell_max => 10).spell_max).to eq 10
84
86
  end
@@ -148,7 +150,7 @@ describe "Blacklight::Configuration" do
148
150
  config.add_my_custom_field 'qwerty', :label => "asdf"
149
151
  end
150
152
 
151
-
153
+
152
154
 
153
155
  expect(config.my_custom_fields.keys).to include('qwerty')
154
156
  end
@@ -161,17 +163,17 @@ describe "Blacklight::Configuration" do
161
163
  config.add_my_custom_facet_field 'qwerty', :label => "asdf"
162
164
  end
163
165
 
164
-
166
+
165
167
 
166
168
  expect(config.my_custom_facet_fields['qwerty']).to be_a_kind_of(Blacklight::Configuration::FacetField)
167
169
  end
168
170
 
169
171
  end
170
-
172
+
171
173
  describe "add_facet_field" do
172
174
  it "accepts field name and hash form arg" do
173
175
  @config.add_facet_field('format', :label => "Format", :limit => true)
174
-
176
+
175
177
  expect(@config.facet_fields["format"]).to_not be_nil
176
178
  expect(@config.facet_fields["format"]["label"]).to eq "Format"
177
179
  expect(@config.facet_fields["format"]["limit"]).to be true
@@ -179,17 +181,17 @@ describe "Blacklight::Configuration" do
179
181
 
180
182
  it "accepts FacetField obj arg" do
181
183
  @config.add_facet_field("format", Blacklight::Configuration::FacetField.new( :label => "Format"))
182
-
184
+
183
185
  expect(@config.facet_fields["format"]).to_not be_nil
184
186
  expect(@config.facet_fields["format"]["label"]).to eq "Format"
185
187
  end
186
-
188
+
187
189
  it "accepts field name and block form" do
188
- @config.add_facet_field("format") do |facet|
190
+ @config.add_facet_field("format") do |facet|
189
191
  facet.label = "Format"
190
192
  facet.limit = true
191
193
  end
192
-
194
+
193
195
  expect(@config.facet_fields["format"]).to_not be_nil
194
196
  expect(@config.facet_fields["format"].limit).to be true
195
197
  end
@@ -223,38 +225,38 @@ describe "Blacklight::Configuration" do
223
225
 
224
226
  it "creates default label from titleized solr field" do
225
227
  @config.add_facet_field("publication_date")
226
-
228
+
227
229
  expect(@config.facet_fields["publication_date"].label).to eq "Publication Date"
228
230
  end
229
231
 
230
232
  it "allows you to not show the facet in the facet bar" do
231
233
  @config.add_facet_field("publication_date", :show=>false)
232
-
234
+
233
235
  expect(@config.facet_fields["publication_date"]['show']).to be false
234
236
  end
235
-
237
+
236
238
  it "raises on nil solr field name" do
237
239
  expect { @config.add_facet_field(nil) }.to raise_error ArgumentError
238
240
  end
239
241
 
240
242
  it "looks up and match field names" do
241
- allow(@config).to receive_messages(luke_fields: {
242
- "some_field_facet" => {},
243
+ allow(config).to receive_messages(reflected_fields: {
244
+ "some_field_facet" => {},
243
245
  "another_field_facet" => {},
244
246
  "a_facet_field" => {},
245
247
  })
246
- expect { |b| @config.add_facet_field match: /_facet$/, &b }.to yield_control.twice
248
+ expect { |b| config.add_facet_field match: /_facet$/, &b }.to yield_control.twice
247
249
 
248
250
  expect(@config.facet_fields.keys).to eq ["some_field_facet", "another_field_facet"]
249
251
  end
250
252
 
251
253
  it "takes wild-carded field names and dereference them to solr fields" do
252
- allow(@config).to receive_messages(luke_fields: {
254
+ allow(config).to receive(:reflected_fields).and_return(
253
255
  "some_field_facet" => {},
254
256
  "another_field_facet" => {},
255
- "a_facet_field" => {},
256
- })
257
- expect { |b| @config.add_facet_field "*_facet", &b }.to yield_control.twice
257
+ "a_facet_field" => {}
258
+ )
259
+ expect { |b| config.add_facet_field "*_facet", &b }.to yield_control.twice
258
260
 
259
261
  expect(@config.facet_fields.keys).to eq ["some_field_facet", "another_field_facet"]
260
262
  end
@@ -275,45 +277,45 @@ describe "Blacklight::Configuration" do
275
277
  end
276
278
  end
277
279
  end
278
-
280
+
279
281
  describe "add_index_field" do
280
282
  it "takes hash form" do
281
283
  @config.add_index_field("title_display", :label => "Title")
282
-
284
+
283
285
  expect(@config.index_fields["title_display"]).to_not be_nil
284
286
  expect(@config.index_fields["title_display"].label).to eq "Title"
285
287
  end
286
288
  it "takes IndexField param" do
287
289
  @config.add_index_field("title_display", Blacklight::Configuration::IndexField.new(:field => "title_display", :label => "Title"))
288
-
290
+
289
291
  expect(@config.index_fields["title_display"]).to_not be_nil
290
292
  expect(@config.index_fields["title_display"].label).to eq "Title"
291
293
  end
292
294
  it "takes block form" do
293
- @config.add_index_field("title_display") do |field|
295
+ @config.add_index_field("title_display") do |field|
294
296
  field.label = "Title"
295
297
  end
296
298
  expect(@config.index_fields["title_display"]).to_not be_nil
297
299
  expect(@config.index_fields["title_display"].label).to eq "Title"
298
300
  end
299
-
301
+
300
302
  it "creates default label from titleized field" do
301
303
  @config.add_index_field("title_display")
302
-
304
+
303
305
  expect(@config.index_fields["title_display"].label).to eq "Title Display"
304
306
  end
305
-
307
+
306
308
  it "raises on nil solr field name" do
307
309
  expect { @config.add_index_field(nil) }.to raise_error ArgumentError
308
310
  end
309
311
 
310
312
  it "takes wild-carded field names and dereference them to solr fields" do
311
- allow(@config).to receive_messages(luke_fields: {
312
- "some_field_display" => {},
313
+ allow(config).to receive(:reflected_fields).and_return(
314
+ "some_field_display" => {},
313
315
  "another_field_display" => {},
314
- "a_facet_field" => {},
315
- })
316
- @config.add_index_field "*_display"
316
+ "a_facet_field" => {}
317
+ )
318
+ config.add_index_field "*_display"
317
319
 
318
320
  expect(@config.index_fields.keys).to eq ["some_field_display", "another_field_display"]
319
321
  end
@@ -323,53 +325,53 @@ describe "Blacklight::Configuration" do
323
325
  expect(@config.index_fields.keys).to include "subtitle_display", "subtitle_vern_display", "title_display", "title_vern_display"
324
326
  end
325
327
  end
326
-
328
+
327
329
  describe "add_show_field" do
328
330
  it "takes hash form" do
329
331
  @config.add_show_field("title_display", :label => "Title")
330
-
332
+
331
333
  expect(@config.show_fields["title_display"]).to_not be_nil
332
334
  expect(@config.show_fields["title_display"].label).to eq "Title"
333
335
  end
334
336
  it "takes ShowField argument" do
335
337
  @config.add_show_field("title_display", Blacklight::Configuration::ShowField.new(:field => "title_display", :label => "Title"))
336
-
338
+
337
339
  expect(@config.show_fields["title_display"]).to_not be_nil
338
340
  expect(@config.show_fields["title_display"].label).to eq "Title"
339
341
  end
340
342
  it "takes block form" do
341
- @config.add_show_field("title_display") do |f|
343
+ @config.add_show_field("title_display") do |f|
342
344
  f.label = "Title"
343
345
  end
344
-
346
+
345
347
  expect(@config.show_fields["title_display"]).to_not be_nil
346
348
  expect(@config.show_fields["title_display"].label).to eq "Title"
347
349
  end
348
-
350
+
349
351
  it "creates default label humanized from field" do
350
352
  @config.add_show_field("my_custom_field")
351
-
353
+
352
354
  expect(@config.show_fields["my_custom_field"].label).to eq "My Custom Field"
353
355
  end
354
-
356
+
355
357
  it "raises on nil solr field name" do
356
358
  expect { @config.add_show_field(nil) }.to raise_error ArgumentError
357
359
  end
358
-
360
+
359
361
  it "takes wild-carded field names and dereference them to solr fields" do
360
- allow(@config).to receive_messages(luke_fields: {
361
- "some_field_display" => {},
362
+ allow(config).to receive(:reflected_fields).and_return(
363
+ "some_field_display" => {},
362
364
  "another_field_display" => {},
363
- "a_facet_field" => {},
364
- })
365
- @config.add_show_field "*_display"
365
+ "a_facet_field" => {}
366
+ )
367
+ config.add_show_field "*_display"
366
368
 
367
369
  expect(@config.show_fields.keys).to eq ["some_field_display", "another_field_display"]
368
370
  end
369
371
 
370
372
  end
371
-
372
-
373
+
374
+
373
375
  describe "add_search_field" do
374
376
  it "accepts hash form" do
375
377
  c = Blacklight::Configuration.new
@@ -379,55 +381,55 @@ describe "Blacklight::Configuration" do
379
381
 
380
382
  it "accepts two-arg hash form" do
381
383
  c = Blacklight::Configuration.new
382
-
384
+
383
385
  c.add_search_field("my_search_type",
384
386
  :key => "my_search_type",
385
- :solr_parameters => { :qf => "my_field_qf^10" },
387
+ :solr_parameters => { :qf => "my_field_qf^10" },
386
388
  :solr_local_parameters => { :pf=>"$my_field_pf"})
387
-
389
+
388
390
  field = c.search_fields["my_search_type"]
389
-
391
+
390
392
  expect(field).to_not be_nil
391
-
392
-
393
+
394
+
393
395
  expect(field.solr_parameters).to_not be_nil
394
- expect(field.solr_local_parameters).to_not be_nil
395
-
396
-
396
+ expect(field.solr_local_parameters).to_not be_nil
397
+
398
+
397
399
  end
398
-
400
+
399
401
  it "accepts block form" do
400
402
  c = Blacklight::Configuration.new
401
-
402
- c.add_search_field("some_field") do |field|
403
+
404
+ c.add_search_field("some_field") do |field|
403
405
  field.solr_parameters = {:qf => "solr_field^10"}
404
406
  field.solr_local_parameters = {:pf => "$some_field_pf"}
405
407
  end
406
-
408
+
407
409
  f = c.search_fields["some_field"]
408
-
410
+
409
411
  expect(f).to_not be_nil
410
412
  expect(f.solr_parameters).to_not be_nil
411
- expect(f.solr_local_parameters).to_not be_nil
413
+ expect(f.solr_local_parameters).to_not be_nil
412
414
  end
413
-
415
+
414
416
  it "accepts SearchField object" do
415
417
  c = Blacklight::Configuration.new
416
-
418
+
417
419
  f = Blacklight::Configuration::SearchField.new( :foo => "bar")
418
-
420
+
419
421
  c.add_search_field("foo", f)
420
-
422
+
421
423
  expect(c.search_fields["foo"]).to_not be_nil
422
424
  end
423
-
425
+
424
426
  it "raises on nil key" do
425
427
  expect {@config.add_search_field(nil, :foo => "bar")}.to raise_error ArgumentError
426
428
  end
427
-
429
+
428
430
  it "creates default label from titleized field key" do
429
431
  @config.add_search_field("author_name")
430
-
432
+
431
433
  expect(@config.search_fields["author_name"].label).to eq "Author Name"
432
434
  end
433
435
 
@@ -447,7 +449,7 @@ describe "Blacklight::Configuration" do
447
449
  end
448
450
  end
449
451
  end
450
-
452
+
451
453
  describe "add_sort_field" do
452
454
  it "takes a hash" do
453
455
  c = Blacklight::Configuration.new
@@ -456,29 +458,29 @@ describe "Blacklight::Configuration" do
456
458
  end
457
459
 
458
460
  it "takes a two-arg form with a hash" do
459
- @config.add_sort_field("score desc, pub_date_sort desc, title_sort asc", :label => "relevance")
461
+ @config.add_sort_field("score desc, pub_date_sort desc, title_sort asc", :label => "relevance")
462
+
460
463
 
461
-
462
464
  expect(@config.sort_fields.values.find{|f| f.label == "relevance"}).to_not be_nil
463
465
  end
464
-
466
+
465
467
  it "takes a SortField object" do
466
468
  @config.add_sort_field(Blacklight::Configuration::SortField.new(:label => "relevance", :sort => "score desc, pub_date_sort desc, title_sort asc"
467
- ))
469
+ ))
468
470
  expect(@config.sort_fields.values.find{|f| f.label == "relevance"}).to_not be_nil
469
471
  end
470
-
472
+
471
473
  it "takes block form" do
472
474
  @config.add_sort_field do |field|
473
475
  field.label = "relevance"
474
476
  field.sort = "score desc, pub_date_sort desc, title_sort asc"
475
477
  end
476
-
478
+
477
479
  expect(@config.sort_fields.values.find{|f| f.label == "relevance"}).to_not be_nil
478
480
 
479
481
  end
480
482
  end
481
-
483
+
482
484
  describe "#default_search_field" do
483
485
  it "uses the field with a :default key" do
484
486
  @config.add_search_field('search_field_1')