bento_search 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +299 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/images/bento_search/large_loader.gif +0 -0
  5. data/app/assets/javascripts/bento_search.js +3 -0
  6. data/app/assets/javascripts/bento_search/ajax_load.js +22 -0
  7. data/app/assets/stylesheets/bento_search/bento.css +4 -0
  8. data/app/controllers/bento_search/bento_search_controller.rb +7 -0
  9. data/app/controllers/bento_search/search_controller.rb +72 -0
  10. data/app/helpers/bento_search_helper.rb +138 -0
  11. data/app/item_decorators/bento_search/only_premade_openurl.rb +16 -0
  12. data/app/item_decorators/bento_search/openurl_add_other_link.rb +35 -0
  13. data/app/item_decorators/bento_search/openurl_main_link.rb +30 -0
  14. data/app/models/bento_search/author.rb +25 -0
  15. data/app/models/bento_search/link.rb +30 -0
  16. data/app/models/bento_search/multi_searcher.rb +109 -0
  17. data/app/models/bento_search/openurl_creator.rb +128 -0
  18. data/app/models/bento_search/registrar.rb +70 -0
  19. data/app/models/bento_search/result_item.rb +203 -0
  20. data/app/models/bento_search/results.rb +54 -0
  21. data/app/models/bento_search/results/pagination.rb +67 -0
  22. data/app/models/bento_search/search_engine.rb +219 -0
  23. data/app/models/bento_search/search_engine/capabilities.rb +65 -0
  24. data/app/search_engines/bento_search/#Untitled-1# +11 -0
  25. data/app/search_engines/bento_search/ebsco_host_engine.rb +356 -0
  26. data/app/search_engines/bento_search/eds_engine.rb +557 -0
  27. data/app/search_engines/bento_search/google_books_engine.rb +184 -0
  28. data/app/search_engines/bento_search/primo_engine.rb +231 -0
  29. data/app/search_engines/bento_search/scopus_engine.rb +295 -0
  30. data/app/search_engines/bento_search/summon_engine.rb +398 -0
  31. data/app/search_engines/bento_search/xerxes_engine.rb +168 -0
  32. data/app/views/bento_search/_link.html.erb +4 -0
  33. data/app/views/bento_search/_search_error.html.erb +22 -0
  34. data/app/views/bento_search/_std_item.html.erb +39 -0
  35. data/app/views/bento_search/search/search.html.erb +1 -0
  36. data/config/locales/en.yml +25 -0
  37. data/lib/bento_search.rb +29 -0
  38. data/lib/bento_search/engine.rb +5 -0
  39. data/lib/bento_search/routes.rb +45 -0
  40. data/lib/bento_search/version.rb +3 -0
  41. data/lib/generators/bento_search/pull_ebsco_dbs_generator.rb +24 -0
  42. data/lib/generators/bento_search/templates/ebsco_global_var.erb +6 -0
  43. data/lib/http_client_patch/include_client.rb +86 -0
  44. data/lib/tasks/bento_search_tasks.rake +4 -0
  45. data/test/dummy/README.rdoc +261 -0
  46. data/test/dummy/Rakefile +7 -0
  47. data/test/dummy/app/assets/javascripts/application.js +15 -0
  48. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  49. data/test/dummy/app/controllers/application_controller.rb +3 -0
  50. data/test/dummy/app/helpers/application_helper.rb +2 -0
  51. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  52. data/test/dummy/config.ru +4 -0
  53. data/test/dummy/config/application.rb +56 -0
  54. data/test/dummy/config/boot.rb +10 -0
  55. data/test/dummy/config/database.yml +25 -0
  56. data/test/dummy/config/environment.rb +5 -0
  57. data/test/dummy/config/environments/development.rb +37 -0
  58. data/test/dummy/config/environments/production.rb +67 -0
  59. data/test/dummy/config/environments/test.rb +37 -0
  60. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  61. data/test/dummy/config/initializers/inflections.rb +15 -0
  62. data/test/dummy/config/initializers/mime_types.rb +5 -0
  63. data/test/dummy/config/initializers/secret_token.rb +7 -0
  64. data/test/dummy/config/initializers/session_store.rb +8 -0
  65. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  66. data/test/dummy/config/locales/en.yml +5 -0
  67. data/test/dummy/config/routes.rb +6 -0
  68. data/test/dummy/db/test.sqlite3 +0 -0
  69. data/test/dummy/log/test.log +3100 -0
  70. data/test/dummy/public/404.html +26 -0
  71. data/test/dummy/public/422.html +26 -0
  72. data/test/dummy/public/500.html +25 -0
  73. data/test/dummy/public/favicon.ico +0 -0
  74. data/test/dummy/script/rails +6 -0
  75. data/test/functional/bento_search/search_controller_test.rb +81 -0
  76. data/test/helper/bento_search_helper_test.rb +125 -0
  77. data/test/integration/navigation_test.rb +10 -0
  78. data/test/support/mock_engine.rb +23 -0
  79. data/test/support/test_with_cassette.rb +38 -0
  80. data/test/test_helper.rb +52 -0
  81. data/test/unit/#vcr_test.rb# +68 -0
  82. data/test/unit/ebsco_host_engine_test.rb +134 -0
  83. data/test/unit/eds_engine_test.rb +105 -0
  84. data/test/unit/google_books_engine_test.rb +93 -0
  85. data/test/unit/item_decorators_test.rb +66 -0
  86. data/test/unit/multi_searcher_test.rb +49 -0
  87. data/test/unit/openurl_creator_test.rb +111 -0
  88. data/test/unit/pagination_test.rb +59 -0
  89. data/test/unit/primo_engine_test.rb +37 -0
  90. data/test/unit/register_engine_test.rb +50 -0
  91. data/test/unit/result_item_display_test.rb +39 -0
  92. data/test/unit/result_item_test.rb +36 -0
  93. data/test/unit/scopus_engine_test.rb +130 -0
  94. data/test/unit/search_engine_base_test.rb +178 -0
  95. data/test/unit/search_engine_test.rb +95 -0
  96. data/test/unit/summon_engine_test.rb +161 -0
  97. data/test/unit/xerxes_engine_test.rb +70 -0
  98. data/test/vcr_cassettes/ebscohost/error_bad_db.yml +45 -0
  99. data/test/vcr_cassettes/ebscohost/error_bad_password.yml +45 -0
  100. data/test/vcr_cassettes/ebscohost/get_info.yml +3626 -0
  101. data/test/vcr_cassettes/ebscohost/live_search.yml +45 -0
  102. data/test/vcr_cassettes/ebscohost/live_search_smoke_test.yml +1311 -0
  103. data/test/vcr_cassettes/eds/basic_search_smoke_test.yml +1811 -0
  104. data/test/vcr_cassettes/eds/get_auth_token.yml +75 -0
  105. data/test/vcr_cassettes/eds/get_auth_token_failure.yml +39 -0
  106. data/test/vcr_cassettes/eds/get_with_auth.yml +243 -0
  107. data/test/vcr_cassettes/eds/get_with_auth_recovers_from_bad_auth.yml +368 -0
  108. data/test/vcr_cassettes/gbs/error_condition.yml +40 -0
  109. data/test/vcr_cassettes/gbs/pagination.yml +702 -0
  110. data/test/vcr_cassettes/gbs/search.yml +340 -0
  111. data/test/vcr_cassettes/primo/search_smoke_test.yml +1112 -0
  112. data/test/vcr_cassettes/scopus/bad_api_key_should_return_error_response.yml +60 -0
  113. data/test/vcr_cassettes/scopus/escaped_chars.yml +187 -0
  114. data/test/vcr_cassettes/scopus/fielded_search.yml +176 -0
  115. data/test/vcr_cassettes/scopus/simple_search.yml +227 -0
  116. data/test/vcr_cassettes/scopus/zero_results_search.yml +67 -0
  117. data/test/vcr_cassettes/summon/bad_auth.yml +54 -0
  118. data/test/vcr_cassettes/summon/proper_tags_for_snippets.yml +216 -0
  119. data/test/vcr_cassettes/summon/search.yml +242 -0
  120. data/test/vcr_cassettes/xerxes/live_search.yml +2580 -0
  121. data/test/view/std_item_test.rb +98 -0
  122. metadata +421 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Jonathan Rochkind/Johns Hopkins Universities
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,299 @@
1
+ # BentoSearch
2
+
3
+ [![Build Status](https://secure.travis-ci.org/jrochkind/bento_search.png)](http://travis-ci.org/jrochkind/bento_search)
4
+
5
+
6
+ (**in progress*, not yet ready for use, mainly because we need more
7
+ out of the box search engines supported).
8
+
9
+ bento_search provides an abstraction/normalization layer for querying and
10
+ displaying results for external search engines, in Ruby on Rails. Requires
11
+ Rails3 and tested only under ruby 1.9.3.
12
+
13
+ * It is focused on use cases for academic libraries, but may be useful in generic
14
+ cases too. Initially, engine adapters are planned to be provided for:
15
+ Google Books, Scopus, SerialSolutions Summon, Ex Libris Primo,
16
+ EBSCO Discovery Service, and EBSCO traditional 'EIT' api. Most
17
+ of these search engines require a vendor license to use.
18
+
19
+ * bento_search could be considered building blocks for a type of 'federated
20
+ search' functionality, but it does not and will never support merging results
21
+ from multiple engines into one result set. It is meant to support displaying the
22
+ first few results from multiple engines on one page, "bento box" style (as
23
+ named by Tito Sierra@NCSU), as well as more expanded single-search-on-a-page
24
+ uses.
25
+
26
+ * bento_search provides abstract functionality for pagination, sorting,
27
+ and single-field-specified queries. Faceting, limiting, and 'advanced'
28
+ multi-field searches are not yet supported, but planned. Not all
29
+ search engine adapters support all features. Search engine adapters can
30
+ declare search fields and sort options with 'semantics', so you can for
31
+ instance search or sort by 'title' across search engines without regard
32
+ to internal engine-specific field names.
33
+
34
+ bento_search is designed to allow code to be written agnostic of the search
35
+ provider, so you can switch out the search provider, minimizing dependent
36
+ code in your app that needs to be rewritten. As well as letting you get
37
+ started quick without reinventing the wheel and figuring out poorly
38
+ documented vendor API's yourself.
39
+
40
+
41
+ ## Usage
42
+
43
+ ### Instantiate an engine, and search
44
+
45
+ When you instantiate an engine, you can provide configuration keys. There
46
+ are a few standard keys (see BentoSearch::SearchEngine), and others that
47
+ may be engine-specific. Some engine-specific keys (such as api auth keys)
48
+ may be required for certain engines.
49
+
50
+ engine = BentoSearch::GoogleBooksEngine.new(:api_key => "my_gbs_api_key")
51
+ results = engine.search("a query")
52
+
53
+ `results` are a BentoSearch::Results object, which acts like an array of
54
+ BentoSearch::Item objects, along with some meta-information about the
55
+ search itself (pagination keys, etc). BentoSearch::Results and Item fields
56
+ are standardized accross engines. BentoSearch::Items provide semantic
57
+ values (title, author, etc.), as available from the particular engine.
58
+
59
+ To see which engines come bundled with BentoSearch, and any special
60
+ engine-specific instructions, look at BentoSearch source in `./app/search_engines`
61
+
62
+ ### Register engines in global configuration
63
+
64
+ It can be convenient to register an engine in global configuration, and is
65
+ required for certain functionality (like out-of-the-box AJAX loading).
66
+
67
+ In an initializer in your app, like say `./config/initializers/bento_search.rb`:
68
+
69
+ BentoSearch.register_engine("gbs") do |conf|
70
+ conf.engine = "BentoSearch::GoogleBooksEngine"
71
+ conf.api_key = "my_google_api_key"
72
+ # any other configuration
73
+ end
74
+
75
+ Then you can refer to it, for instance in a controller, by the id you registered:
76
+
77
+ @results = BentoSearch.get_engine("gbs").search("my query")
78
+
79
+ ### Display results
80
+
81
+ You can of course write your own code to display a BentoSearch::Results object
82
+ however you like. But BentoSearch comes with a helper method for displaying
83
+ a list of BentoSearch::Results in a standard way, using the bento_search
84
+ helper method.
85
+
86
+ <%= bento_search(@results) %>
87
+
88
+ ### Fielded searching.
89
+
90
+ You can search by an internal engine-specific field name:
91
+
92
+ google_books_engine.search("smith", :search_field => "inauthor")
93
+
94
+ Or, if the engine provides it, you can search by normalized semantic search
95
+ field type names:
96
+
97
+ google_books_engine.search("smith", :semantic_earch_field => :title)
98
+
99
+ This will raise if an engine doesn't support that semantic search field.
100
+ You can find out what fields a particular engine supports.
101
+
102
+ BentoSearch::GoogleBooksEngine.search_keys # => internal keys
103
+ BentoSearch::GoogleBooksEngine.semantic_search_keys
104
+
105
+ You can also provide all arguments in a single hash when it's convenient
106
+ to do so:
107
+
108
+ google_books_engine.search(:query => "smith", :search_field => "inauthor")
109
+
110
+ ### Sorting
111
+
112
+ An engine advertises what sort types it supports:
113
+
114
+ BentoSearch::GoogleBooksEngine.sort_definitions
115
+
116
+ That returns a hash, where the keys are sort identifiers, where possible
117
+ chosen from a standard list of semantics. (See list in config/i18n/en.yml,
118
+ bento_search.sort_keys).
119
+
120
+ google_books_engine.search("my query", :sort => "date_desc")
121
+
122
+ For help creating your UI, you can use built-in helper method:
123
+
124
+ bento_sort_hash_for(engine)
125
+ #=> returns a Hash suitable as first argument for rails
126
+ # options_for_select helper, with sort options and labels from I18n.
127
+
128
+
129
+ ### Pagination
130
+
131
+ You can tell the search engine how many items you want per-page, and
132
+ use _either_ `:start` (0-based item offset) or `:page` (1-based page
133
+ offset) keys to paginate into the results.
134
+
135
+ results = google_books_engine.search("my query", :per_page => 20, :start => 40)
136
+ results = google_books_engine.search("my query", :per_page => 20, :page => 2) # means same as above
137
+
138
+ An engine instance advertises it's maximum per-page values.
139
+
140
+ google_books_engine.max_per_page
141
+
142
+ bento_search fixes the default per_page at 10.
143
+
144
+ For help creating your UI, you can ask a BentoSearch::Results for
145
+ `results.pagination`, which returns a BentoSearch::Results::Pagination
146
+ object which should be suitable for passing to [kaminari](https://github.com/amatsuda/kaminari)
147
+ `paginate`, or else have convenient methods for roll your own pagination UI.
148
+ Kaminari's paginate method:
149
+
150
+ <%= paginate results.pagination %>
151
+
152
+ ### Concurrent searching
153
+
154
+ If you're going to search 2 or more search engines at once, you'll want to execute
155
+ those searches concurrently. For instance, if GoogleBooks results take 2 second
156
+ to come in, and Scopus results take 3 seconds -- you don't want to first wait
157
+ the 2 second then wait the 3 seconds for a total of 5 -- you instead want
158
+ to execute concurrently in seperate threads, so the total wait time is the slowest
159
+ engine, not the sum of the engines.
160
+
161
+ You can write your own logic using ruby threads to do this, but
162
+ BentoSearch provides a multi-searching helper using [Celluloid](https://github.com/celluloid/celluloid)
163
+ to help you do this easily. Say, in a controller:
164
+
165
+ ~~~~ruby
166
+ # constructor takes id's registered with BentoSearch.register_engine
167
+ searcher = BentoSearch::MultiSearcher.new(:gbs, :scopus, :summon)
168
+
169
+ # Call 'start' with any parameters you would give to an_engine.search
170
+ searcher.start("my query", :semantic_search_field => :author, :sort => "title")
171
+
172
+ # At this point, all searches are executing asynchronously in seperate threads.
173
+ # To get the results, blocking until all complete:
174
+ @results = searcher.results
175
+
176
+ # @results will be a hash, keyed by registered engine id, values
177
+ # are BentoSearch::Results
178
+ ~~~~
179
+
180
+ Even if you are only searching one engine, this may be useful to have the
181
+ search execute in a seperate thread, so you can continue doing other work
182
+ in the main thread (like search a local store of some kind outside of
183
+ bento_search)
184
+
185
+ You will need to add the 'celluloid' gem to your app to use this feature,
186
+ BentoSearch doesn't automatically include the celluloid dependency right now
187
+ (should it?).
188
+
189
+ For more info, see BentoSearch::MultiSearcher.
190
+
191
+ ### Delayed results loading via AJAX (actually more like AJAHtml)
192
+
193
+ BentoSearch provides some basic support for initially displaying a placeholder
194
+ progress spinner, and having Javascript call back to get the actual results.
195
+
196
+ * **Setup Pre-requisites**
197
+ * In your `./config/routes.rb`, you need `BentoSearch::Routes.new(self).draw` in order
198
+ to route to the ajax loader.
199
+ * In your asset pipeline, you must have `//= require 'bento_search/ajax_load`
200
+ to get JS for ajax loading. (or require 'bento_search' to get all bento_search JS)
201
+ * **Note** that this is not a panacea for a very slow search engine -- if the
202
+ search results take 20 seconds to come in, when the AJAX call back happens,
203
+ your Rails process _will_ be blocked from serving any other requests for that 20
204
+ seconds. In fact, that makes this feature of very limited applicability in general,
205
+ think carefully about what this will do for you.
206
+ * **Beware** that there are some authorization considerations if your search
207
+ engine is not publically configurable, see BentoSearch::SearchController
208
+ for more details.
209
+
210
+ You have have registered a configured engine globally, and given it the special
211
+ `:allow_routable_results` key.
212
+
213
+ BentoSearch.register_engine("gbs") do |conf|
214
+ conf.api_key = "x"
215
+ conf.allow_routable_results = true
216
+ end
217
+
218
+ Now you can use the `bento_search` helper method with the registered id
219
+ and query, instead of with results as before, and with an option for
220
+ ajax auto-load.
221
+
222
+ <%= bento_search("gbs", :query => "my query",
223
+ :semantic_search_field => :title,
224
+ :load => :ajax_auto) %>
225
+
226
+
227
+
228
+ ### Item Decorators, and Links
229
+
230
+ You can configure Decorators, in the form of plain old ruby modules, to be
231
+ applied to BentoSearch::Items, on an engine-by-engine basis. These can modify,
232
+ add, or remove Item data, as well as over-ride some presentational methods.
233
+
234
+ One common use for these Decorators is changing, adding, or removing links
235
+ associated with an item. For instance, to link to your local OpenURL
236
+ link resolver.
237
+
238
+ BentoSearch::Items can have a main link associated with them (generally
239
+ hyperlinked from title), as well as a list of additional links. Most engines
240
+ do not provide additional links by default, custom local Decorators would
241
+ be used to add them.
242
+
243
+ BentoSearch.register_engine("something") do |conf|
244
+ conf.engine = SomeEngine
245
+ conf.item_decorators = [ SomeModule, OtherModule]
246
+ end
247
+
248
+ See BentoSearch::Item for more information on decorators, and BentoSearch::Link
249
+ on links.
250
+
251
+ ## Planned Features
252
+
253
+ I am trying to keep BentoSearch as simple as it can be to conveniently meet
254
+ actual use cases. Trying to avoid premature over-engineering, and pave
255
+ the cowpaths as needed.
256
+
257
+ Probably:
258
+
259
+ * Support for display facets for engines that support such, as well as
260
+ search with limits from controlled vocabulary (ie, selected facet, but
261
+ also may be supported by some engines that do not support facetting).
262
+ * Support for multi-field, multi-entry-box 'advanced search' UI's, in
263
+ a normalized cross-engine way.
264
+ * More mindless support for displaying pagination UI with kaminari.
265
+
266
+ Other needs or suggestions?
267
+
268
+
269
+ ## Developing
270
+
271
+ BentoSearch is fairly well covered by automated tests. We simply use Test::Unit.
272
+ Run tests with `rake test`.
273
+
274
+ The testing environment was generated with `rails plugin new`, and includes
275
+ a dummy app used when testing at `./test/dummy`.
276
+
277
+ For integration tests against live external search API's, we use the awesome
278
+ [VCR](https://github.com/myronmarston/vcr) gem to cache responses.
279
+ To write your own Test::Unit tests using VCR, take note of the
280
+ `test_with_cassette` method provided in `./test/support/test_with_cassette.rb`.
281
+
282
+ Also note use of VCR.filter_sensitive_data to make sure your API keys
283
+ do not get saved in cached response in the repo, while still allowing
284
+ tests to be run against cached responses even for engines that require
285
+ auth.
286
+
287
+ To re-generate cached responses, delete the relevant files in
288
+ `./test/vcr_cassettes` and re-run tests. You may have to set an ENV
289
+ variable with your own API keys to re-run tests without cached response
290
+ like this.
291
+
292
+ Also note `./test/support/mock_engine.rb`, a simple mock/dummy SearchEngine
293
+ implementation that can be used in other tests.
294
+
295
+ Pull requests welcome. Pull requests with additional search engine implementations
296
+ welcome. See more info on writing a BentoSearch::SearchEngine in the inline
297
+ docs in that file.
298
+
299
+
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'BentoSearch'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+
28
+ Bundler::GemHelper.install_tasks
29
+
30
+ require 'rake/testtask'
31
+
32
+ Rake::TestTask.new(:test) do |t|
33
+ t.libs << 'lib'
34
+ t.libs << 'test'
35
+ t.pattern = 'test/**/*_test.rb'
36
+ t.verbose = false
37
+ end
38
+
39
+
40
+ task :default => :test
@@ -0,0 +1,3 @@
1
+ // require all bento_search javascript.
2
+ //
3
+ //= require_tree ./bento_search
@@ -0,0 +1,22 @@
1
+ jQuery(document).ready(function($) {
2
+ //Intentionally wait for window.load, not just onready, to
3
+ //prevent interfering with rest of page load.
4
+ $(window).bind("load", function() {
5
+ $(".bento_search_ajax_wait").each(function(i, div) {
6
+ div = $(div);
7
+ // from html5 data-bento-ajax-url
8
+ $.ajax({
9
+ url: div.data("bentoAjaxUrl"),
10
+ success: function(response, status, xhr) {
11
+ div.replaceWith(response);
12
+ },
13
+ error: function(xhr, status, errorThrown) {
14
+ var msg = "Sorry but there was an error: ";
15
+ div.html(msg + xhr.status + " " + xhr.statusText + ", " + status);
16
+ }
17
+ });
18
+
19
+ });
20
+ });
21
+
22
+ });
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,7 @@
1
+ module BentoSearch
2
+ # Master superclass for all controllers included in
3
+ # bento_search, note it inherits from host app's
4
+ # ApplicationController
5
+ class BentoSearchController < ::ApplicationController
6
+ end
7
+ end
@@ -0,0 +1,72 @@
1
+ module BentoSearch
2
+ # This is a controller that provides stand-alone search results
3
+ # for registered engines. Right now, this is only for automatic
4
+ # AJAX delayed loading. In the future it may be used for atom results,
5
+ # or other such.
6
+ #
7
+ # You need to make sure to include routing for this controller in your
8
+ # app to use it, for instance with `BentoSearch::Routes.new(self).draw`
9
+ # in your ./config/routes.rb
10
+ #
11
+ # # Authorization Issues
12
+ #
13
+ # You may have some engines which should not be publically searchable,
14
+ # they should only be searchable by certain auth'd users. This controller
15
+ # could accidentally provide a non-protected endpoint to get results if
16
+ # nothing were done to prevent it.
17
+ #
18
+ # Only engines which have a :allow_routable_results => true key
19
+ # in their config will be served by this controller.
20
+ #
21
+ # If you need routable results on an engine which ALSO needs to
22
+ # be protected by auth, you can add your own Rails before_filter
23
+ # to provide auth. Say, in an initializer in your app:
24
+ #
25
+ # SearchController.before_filter do |controller|
26
+ # unless controller.current_user
27
+ # raise BentoSearch::SearchController::AccessDenied
28
+ # end
29
+ # end
30
+ #
31
+ #
32
+ # We may provide fancier/nicer API for this in the future, if there's
33
+ # demand.
34
+ class SearchController < BentoSearchController
35
+ class AccessDenied < Exception ; end
36
+
37
+
38
+ rescue_from AccessDenied, :with => :deny_access
39
+ rescue_from NoSuchEngine, :with => :render_404
40
+
41
+ # returns partial HTML results, suitable for
42
+ # AJAX to insert into DOM.
43
+ # arguments for engine.search are taken from URI request params.
44
+ # (TODO: Is this a security issue, do we need to whitelist em? )
45
+ def search
46
+ engine = BentoSearch.get_engine(params[:engine_id])
47
+
48
+
49
+ unless engine.configuration.allow_routable_results == true
50
+ raise AccessDenied.new("engine needs to be registered with :allow_routable_results => true")
51
+ end
52
+
53
+ @results = engine.search(params.to_hash.symbolize_keys)
54
+
55
+ render :layout => false # partial HTML results
56
+ end
57
+
58
+
59
+
60
+ protected
61
+
62
+ def deny_access(exception)
63
+ render :text => exception.message, :status => 403
64
+ end
65
+
66
+ def render_404(exception)
67
+ render :text => exception.message, :status => 404
68
+ end
69
+
70
+
71
+ end
72
+ end