bento_search 1.5.0 → 2.0.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 (61) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +27 -24
  3. data/Rakefile +30 -11
  4. data/app/assets/javascripts/bento_search/ajax_load.js +54 -22
  5. data/app/controllers/bento_search/search_controller.rb +31 -30
  6. data/app/helpers/bento_search_helper.rb +72 -74
  7. data/app/models/bento_search/concurrent_searcher.rb +136 -0
  8. data/app/models/bento_search/result_item.rb +15 -12
  9. data/app/models/bento_search/results/serialization.rb +22 -13
  10. data/app/models/bento_search/search_engine.rb +170 -140
  11. data/app/search_engines/bento_search/doaj_articles_engine.rb +20 -20
  12. data/app/search_engines/bento_search/ebsco_host_engine.rb +3 -3
  13. data/app/search_engines/bento_search/eds_engine.rb +326 -206
  14. data/app/search_engines/bento_search/google_books_engine.rb +2 -2
  15. data/app/search_engines/bento_search/scopus_engine.rb +87 -87
  16. data/app/search_engines/bento_search/summon_engine.rb +1 -1
  17. data/app/views/bento_search/_ajax_loading.html.erb +17 -0
  18. data/app/views/bento_search/_item_title.html.erb +2 -4
  19. data/app/views/bento_search/_link.html.erb +3 -3
  20. data/lib/bento_search.rb +24 -9
  21. data/lib/bento_search/engine.rb +2 -0
  22. data/lib/bento_search/version.rb +1 -1
  23. data/lib/generators/bento_search/install/ajax_load_js_generator.rb +15 -0
  24. data/test/decorator/standard_decorator_test.rb +30 -30
  25. data/test/dummy/app/assets/config/manifest.js +4 -0
  26. data/test/dummy/config/application.rb +7 -0
  27. data/test/dummy/config/boot.rb +4 -9
  28. data/test/dummy/config/environments/development.rb +2 -0
  29. data/test/dummy/config/environments/production.rb +7 -1
  30. data/test/dummy/config/environments/test.rb +10 -3
  31. data/test/functional/bento_search/search_controller_test.rb +68 -58
  32. data/test/helper/bento_search_helper_test.rb +103 -103
  33. data/test/search_engines/doaj_articles_engine_test.rb +9 -9
  34. data/test/search_engines/eds_engine_test.rb +91 -59
  35. data/test/search_engines/google_site_search_test.rb +48 -48
  36. data/test/search_engines/scopus_engine_test.rb +51 -51
  37. data/test/search_engines/search_engine_base_test.rb +108 -86
  38. data/test/search_engines/search_engine_test.rb +68 -56
  39. data/test/support/atom.xsd.xml +3 -3
  40. data/test/support/xml.xsd +117 -0
  41. data/test/test_helper.rb +23 -12
  42. data/test/unit/concurrent_searcher_test.rb +75 -0
  43. data/test/unit/pagination_test.rb +12 -12
  44. data/test/vcr_cassettes/eds/FullText_CustomLink.yml +198 -0
  45. data/test/vcr_cassettes/eds/basic_search_smoke_test.yml +1036 -1729
  46. data/test/vcr_cassettes/eds/catalog_ebook_query.yml +218 -0
  47. data/test/vcr_cassettes/eds/catalog_query.yml +255 -0
  48. data/test/vcr_cassettes/eds/get_auth_token.yml +11 -44
  49. data/test/vcr_cassettes/eds/get_auth_token_failure.yml +10 -7
  50. data/test/vcr_cassettes/eds/get_with_auth.yml +144 -153
  51. data/test/vcr_cassettes/eds/get_with_auth_recovers_from_bad_auth.yml +167 -223
  52. data/test/view/atom_results_test.rb +94 -94
  53. metadata +36 -46
  54. data/app/assets/javascripts/bento_search.js +0 -3
  55. data/app/item_decorators/bento_search/ebscohost/conditional_openurl_main_link.rb +0 -36
  56. data/app/item_decorators/bento_search/only_premade_openurl.rb +0 -20
  57. data/app/item_decorators/bento_search/openurl_add_other_link.rb +0 -39
  58. data/app/item_decorators/bento_search/openurl_main_link.rb +0 -34
  59. data/app/models/bento_search/multi_searcher.rb +0 -131
  60. data/test/dummy/config/initializers/secret_token.rb +0 -8
  61. data/test/unit/multi_searcher_test.rb +0 -49
@@ -1,3 +0,0 @@
1
- // require all bento_search javascript.
2
- //
3
- //= require_tree ./bento_search
@@ -1,36 +0,0 @@
1
- # DEPRECATED. Just write the logic into a custom Decorator yourself.
2
- # See wiki on decorators.
3
- #
4
- #
5
- # For ebscohost connector, example of an Item Decorator that replaces the main
6
- # 'link' with an openurl ONLY if there is NOT fulltext avail from EBSCO.
7
- #
8
- # This example uses crazy metaprogramming to dynamically create
9
- # a module configured with your base url etc. You don't need to use
10
- # crazy method like that; just define your own local decorator doing
11
- # exactly what you need, it's meant to be simple.
12
- #
13
- # config.item_decorators = [ BentoSearch::Ebscohost::ConditionalOpenurlMainLink[:base_url => "http://resolve.somewhere.edu/foo", :extra_query => "&foo=bar"] ]
14
- #
15
- module BentoSearch::Ebscohost::ConditionalOpenurlMainLink
16
- def self.[](options)
17
- base_url = options[:base_url]
18
- extra_query = options[:extra_query] || ""
19
- Module.new do
20
-
21
- define_method :link do
22
- if custom_data["fulltext_formats"]
23
- super()
24
- elsif (ou = to_openurl)
25
- "#{base_url}?#{ou.kev}#{extra_query}"
26
- else
27
- nil
28
- end
29
- end
30
-
31
- end
32
- end
33
-
34
-
35
-
36
- end
@@ -1,20 +0,0 @@
1
- # DEPRECATED. Just write the logic into a custom Decorator yourself.
2
- # See wiki on decorators.
3
-
4
-
5
- require 'openurl'
6
-
7
- # A Decorator that will make #to_openurl refuse to construct
8
- # an openurl from individual elements, it'll use the #openurl_kev_co
9
- # or nothing.
10
- module BentoSearch::OnlyPremadeOpenurl
11
-
12
- def to_openurl
13
- if self.openurl_kev_co
14
- return OpenURL::ContextObject.new_from_kev( self.openurl_kev_co )
15
- else
16
- return nil
17
- end
18
- end
19
-
20
- end
@@ -1,39 +0,0 @@
1
- # DEPRECATED. Just write the logic into a custom Decorator yourself.
2
- # See wiki on decorators.
3
- #
4
- #
5
- # Example of an Item Decorator that ADDs an 'other link' with an openurl.
6
- #
7
- # This example uses crazy metaprogramming to dynamically create
8
- # a module configured with your base url etc. You don't need to use
9
- # crazy method like that; just define your own local decorator doing
10
- # exactly what you need, it's meant to be simple.
11
- #
12
- # config.item_decorators = [ BentoSearch::OpenurlAddOtherLink[:base_url => "http://resolve.somewhere.edu/foo", :extra_query => "&foo=bar"] ]
13
- #
14
- module BentoSearch::OpenurlAddOtherLink
15
- def self.[](options)
16
- base_url = options[:base_url]
17
- extra_query = options[:extra_query] || ""
18
- link_name = options[:link_name] || "Find It"
19
- # overwrite: if true, overwrite previously existing other_links, if
20
- # false add on to previously existing.
21
- overwrite = options.has_key?(:overwrite) ? options[:overwrite] : false
22
-
23
- Module.new do
24
-
25
- define_method :other_links do
26
- start = overwrite ? [] : super()
27
- if (ou = to_openurl)
28
- start + [BentoSearch::Link.new(:url => "#{base_url}?#{ou.kev}#{extra_query}", :label => link_name)]
29
- else
30
- start
31
- end
32
- end
33
-
34
- end
35
- end
36
-
37
-
38
-
39
- end
@@ -1,34 +0,0 @@
1
- # DEPRECATED. Just write the logic into a custom Decorator yourself.
2
- # See wiki on decorators.
3
-
4
-
5
- # Example of an Item Decorator that replaces the main 'link'
6
- # with an openurl.
7
- #
8
- # This example uses crazy metaprogramming to dynamically create
9
- # a module configured with your base url etc. You don't need to use
10
- # crazy method like that; just define your own local decorator doing
11
- # exactly what you need, it's meant to be simple.
12
- #
13
- # config.item_decorators = [ BentoSearch::OpenurlMainLink[:base_url => "http://resolve.somewhere.edu/foo", :extra_query => "&foo=bar"] ]
14
- #
15
- module BentoSearch::OpenurlMainLink
16
- def self.[](options)
17
- base_url = options[:base_url]
18
- extra_query = options[:extra_query] || ""
19
- Module.new do
20
-
21
- define_method :link do
22
- if (ou = to_openurl)
23
- "#{base_url}?#{ou.kev}#{extra_query}"
24
- else
25
- nil
26
- end
27
- end
28
-
29
- end
30
- end
31
-
32
-
33
-
34
- end
@@ -1,131 +0,0 @@
1
- begin
2
- require 'celluloid'
3
-
4
- # Based on Celluloid, concurrently runs multiple searches in
5
- # seperate threads. You must include 'celluloid' gem dependency
6
- # into your local app to use this class. Requires celluloid 0.12.0
7
- # or above (for new preferred async syntax).
8
- #
9
- # Warning, if you don't have celluloid in your app, this class simply
10
- # won't load. TODO: We should put this file in a different directory
11
- # so it's never auto-loaded, and requires a "require 'bento_search/multi_searcher'",
12
- # such that it will raise without celluloid only then, and we don't need this
13
- # rescue LoadError stuff.
14
- #
15
- # I am not an expert at use of Celluloid, it's possible there's a better
16
- # way to do this all, but seems to work.
17
- #
18
- # ## Usage
19
- #
20
- # initialize with id's of registered engines:
21
- # searcher = BentoBox::MultiSearcher.new(:gbs, :scopus)
22
- #
23
- # start the concurrent searches, params same as engine.search
24
- # searcher.search( query_params )
25
- #
26
- # retrieve results, blocking until each is completed:
27
- # searcher.results
28
- #
29
- # returns a Hash keyed by engine id, values BentoSearch::Results objects.
30
- #
31
- # Can only call #results once per #start, after that it'll return empty hash.
32
- # (should we make it actually raise instead?). .
33
- #
34
- # important to call results at some point after calling start, in order
35
- # to make sure Celluloid::Actors are properly terminated to avoid
36
- # resource leakage. May want to do it in an ensure block.
37
- #
38
- # Note that celluloid uses multi-threading in such a way that you
39
- # may have to set config.cache_classes=true even in development
40
- # to avoid problems. Rails class reloading is not thread-safe.
41
- #
42
- #
43
- # TODO: have a method that returns Futures instead of only supplying the blocking
44
- # results method? Several tricks, including making sure to properly terminate actors.
45
- class BentoSearch::MultiSearcher
46
-
47
- def initialize(*engine_ids)
48
- @engines = []
49
- @actors = []
50
- engine_ids.each do |id|
51
- add_engine( BentoSearch.get_engine id )
52
- end
53
- end
54
-
55
- # Adds an instantiated engine directly, rather than by id from global
56
- # registry.
57
- def add_engine(engine)
58
- @engines << engine
59
- end
60
-
61
- # Starts all searches, returns self so you can chain method calls if you like.
62
- def search(*search_args)
63
- @engines.each do |engine|
64
- a = Actor.new(engine)
65
- @actors << a
66
- a.async.start *search_args
67
- end
68
- return self
69
- end
70
- alias_method :start, :search # backwards compat
71
-
72
- # Call after #start. Blocks until each included engine is finished
73
- # then returns a Hash keyed by engine registered id, value is a
74
- # BentoSearch::Results object.
75
- #
76
- # Can only call _once_ per invocation of #start, after that it'll return
77
- # an empty hash.
78
- def results
79
- results = {}
80
-
81
- # we use #delete_if to get an iterator that deletes
82
- # each item after iteration.
83
- @actors.delete_if do |actor|
84
- result_key = (actor.engine.configuration.id || actor.engine.class.name)
85
- results[result_key] = actor.results
86
- actor.terminate
87
-
88
- true
89
- end
90
-
91
- return results
92
- end
93
-
94
-
95
- class Actor
96
- include Celluloid
97
-
98
- attr_accessor :engine
99
-
100
- def initialize(a_engine)
101
- self.engine = a_engine
102
- end
103
-
104
- # call as .async.start, to invoke async.
105
- def start(*search_args)
106
- begin
107
- @results = self.engine.search(*search_args)
108
- rescue StandardError => e
109
- Rails.logger.error("\nBentoSearch:MultiSearcher caught exception: #{e}\n#{e.backtrace.join(" \n")}")
110
- # Make a fake results with caught exception.
111
- @results = BentoSearch::Results.new
112
- self.engine.fill_in_search_metadata_for(@results, self.engine.normalized_search_arguments(search_args))
113
-
114
- @results.error ||= {}
115
- @results.error["exception"] = e
116
- end
117
- end
118
-
119
- def results
120
- @results
121
- end
122
-
123
- end
124
-
125
- end
126
-
127
- rescue LoadError
128
- # you can use bento_search without celluloid, just not
129
- # this class.
130
- end
131
-
@@ -1,8 +0,0 @@
1
- # Be sure to restart your server when you modify this file.
2
-
3
- # Your secret key for verifying the integrity of signed cookies.
4
- # If you change this key, all old signed cookies will become invalid!
5
- # Make sure the secret is at least 30 characters and all random,
6
- # no regular words or you'll be exposed to dictionary attacks.
7
- Dummy::Application.config.secret_token = '78ee4771fe1d7704b7dd8f47b879db32af098e4cf67f9910e9cf7fe8de18353ff52dc3ccb48ed341745aaedbad9ba79f031867b0e37680f2fb5b66b76838db22'
8
- Dummy::Application.config.secret_key_base = '60f73d25f61301b1ea3119011efb9fd9a741fcc010757599341d45765fbda7676daf5d602fb17bb5085c3163a04e20c0750ad02562ee9cb7f03f813d1b62c639'
@@ -1,49 +0,0 @@
1
- require 'test_helper'
2
-
3
- # Doesn't really test the concurrency, but basic smoke test with fake
4
- # searchers.
5
- class MultiSearcherTest < ActiveSupport::TestCase
6
- setup do
7
- BentoSearch.register_engine("one") do |conf|
8
- conf.engine = "MockEngine"
9
- end
10
- BentoSearch.register_engine("two") do |conf|
11
- conf.engine = "MockEngine"
12
- end
13
- BentoSearch.register_engine("three") do |conf|
14
- conf.engine = "MockEngine"
15
- end
16
- end
17
-
18
- teardown do
19
- BentoSearch.reset_engine_registrations!
20
- end
21
-
22
-
23
- def test_multisearch
24
- searcher = BentoSearch::MultiSearcher.new(:one, :two, :three)
25
- start_returnval = searcher.start("cancer")
26
-
27
- assert_same searcher, start_returnval
28
-
29
- results = searcher.results
30
-
31
- assert_kind_of Hash, results
32
- assert_equal ["one", "two", "three"].sort, results.keys.sort
33
-
34
- ["one", "two", "three"].each do |key|
35
- assert_kind_of BentoSearch::Results, results[key]
36
- end
37
-
38
- # call results again, we get an empty hash, can only call
39
- # results once per start.
40
- new_results = searcher.results
41
- assert_kind_of Hash, new_results
42
- assert_empty new_results
43
-
44
- end
45
-
46
-
47
-
48
-
49
- end