bento_search 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +131 -74
- data/app/assets/javascripts/bento_search/ajax_load.js +12 -4
- data/app/assets/stylesheets/bento_search/suggested_styles.css +4 -4
- data/app/helpers/bento_search_helper.rb +114 -27
- data/app/item_decorators/bento_search/decorator_base.rb +53 -0
- data/app/item_decorators/bento_search/ebscohost/conditional_openurl_main_link.rb +36 -0
- data/app/item_decorators/bento_search/no_links.rb +3 -2
- data/app/item_decorators/bento_search/only_premade_openurl.rb +4 -0
- data/app/item_decorators/bento_search/openurl_add_other_link.rb +4 -0
- data/app/item_decorators/bento_search/openurl_main_link.rb +4 -0
- data/app/item_decorators/bento_search/standard_decorator.rb +122 -0
- data/app/models/bento_search/multi_searcher.rb +13 -6
- data/app/models/bento_search/openurl_creator.rb +25 -5
- data/app/models/bento_search/result_item.rb +25 -83
- data/app/models/bento_search/results/pagination.rb +8 -2
- data/app/models/bento_search/search_engine.rb +29 -23
- data/app/search_engines/bento_search/ebsco_host_engine.rb +161 -25
- data/app/search_engines/bento_search/eds_engine.rb +1 -44
- data/app/search_engines/bento_search/google_books_engine.rb +61 -14
- data/app/search_engines/bento_search/google_site_search_engine.rb +3 -1
- data/app/search_engines/bento_search/mock_engine.rb +4 -0
- data/app/search_engines/bento_search/primo_engine.rb +2 -3
- data/app/search_engines/bento_search/scopus_engine.rb +1 -0
- data/app/search_engines/bento_search/summon_engine.rb +5 -1
- data/app/search_engines/bento_search/worldcat_sru_dc_engine.rb +36 -8
- data/app/views/bento_search/_item_title.html.erb +29 -0
- data/app/views/bento_search/_no_results.html.erb +3 -0
- data/app/views/bento_search/_search_error.html.erb +19 -15
- data/app/views/bento_search/_std_item.html.erb +55 -30
- data/app/views/bento_search/search/search.html.erb +7 -0
- data/config/locales/en.yml +22 -0
- data/lib/bento_search/util.rb +63 -1
- data/lib/bento_search/version.rb +1 -1
- data/test/decorator/decorator_base_test.rb +72 -0
- data/test/decorator/standard_decorator_test.rb +55 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/log/development.log +12 -0
- data/test/dummy/log/test.log +119757 -0
- data/test/functional/bento_search/search_controller_test.rb +28 -0
- data/test/helper/bento_search_helper_test.rb +71 -0
- data/test/helper/bento_truncate_helper_test.rb +71 -0
- data/test/unit/ebsco_host_engine_test.rb +110 -3
- data/test/unit/google_books_engine_test.rb +22 -14
- data/test/unit/google_site_search_test.rb +11 -4
- data/test/unit/item_decorators_test.rb +6 -65
- data/test/unit/openurl_creator_test.rb +87 -8
- data/test/unit/result_item_test.rb +1 -11
- data/test/unit/search_engine_base_test.rb +25 -2
- data/test/unit/search_engine_test.rb +16 -0
- data/test/unit/summon_engine_test.rb +3 -0
- data/test/vcr_cassettes/ebscohost/another_dissertation.yml +148 -0
- data/test/vcr_cassettes/ebscohost/dissertation_example.yml +218 -0
- data/test/vcr_cassettes/ebscohost/fulltext_info.yml +1306 -0
- data/test/vcr_cassettes/ebscohost/live_book_example.yml +130 -0
- data/test/vcr_cassettes/ebscohost/live_dissertation.yml +148 -0
- data/test/vcr_cassettes/ebscohost/live_pathological_book_item_example.yml +215 -0
- data/test/vcr_cassettes/google_site/gets_format_string.yml +232 -0
- data/test/vcr_cassettes/max_out_pagination.yml +155 -0
- data/test/vcr_cassettes/worldcat_sru_dc/max_out_pagination.yml +167 -0
- data/test/view/std_item_test.rb +25 -8
- metadata +45 -12
- data/test/unit/result_item_display_test.rb +0 -39
- data/test/unit/worldcat_sru_dc_engine_test.rb +0 -120
@@ -5,6 +5,9 @@
|
|
5
5
|
#
|
6
6
|
# You don't normally create one of these yourself, you get one returned
|
7
7
|
# from Results#pagination
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# <%= paginate @results.pagination %>
|
8
11
|
class BentoSearch::Results::Pagination
|
9
12
|
|
10
13
|
# first arg is results.total_items, second is result
|
@@ -12,9 +15,11 @@ class BentoSearch::Results::Pagination
|
|
12
15
|
#
|
13
16
|
# We don't do the page/start normalization calc here,
|
14
17
|
# we count on them both being passed in, already calculated
|
15
|
-
# by normalize_arguments in SearchResults.
|
16
|
-
# :start, and :per_page
|
18
|
+
# by normalize_arguments in SearchResults. Expects :page, 0-based
|
19
|
+
# :start, and 1-based :per_page to all be passed in in initializer.
|
17
20
|
def initialize(total, normalized_args)
|
21
|
+
normalized_args ||= {} # in some error cases, we end up with nil
|
22
|
+
|
18
23
|
@total_count = total || 0
|
19
24
|
@per_page = normalized_args[:per_page] || 10
|
20
25
|
@current_page = normalized_args[:page] || 1
|
@@ -42,6 +47,7 @@ class BentoSearch::Results::Pagination
|
|
42
47
|
def count_records
|
43
48
|
@total_count
|
44
49
|
end
|
50
|
+
alias count count_records
|
45
51
|
|
46
52
|
def total_pages
|
47
53
|
(@total_count.to_f / @per_page).ceil
|
@@ -49,13 +49,11 @@ module BentoSearch
|
|
49
49
|
# Additional standard configuration keys that are implemented by the bento_search
|
50
50
|
# framework:
|
51
51
|
#
|
52
|
-
# [
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
# item metadata. (Needs more documentation).
|
58
|
-
#
|
52
|
+
# [for_display.decorator]
|
53
|
+
# String name of decorator class that will be applied by #bento_decorate
|
54
|
+
# helper in standard view. See wiki for more info on decorators. Must be
|
55
|
+
# string name, actual class object not supported (to make it easier
|
56
|
+
# to serialize and transport configuration).
|
59
57
|
#
|
60
58
|
# == Implementing a SearchEngine
|
61
59
|
#
|
@@ -143,8 +141,7 @@ module BentoSearch
|
|
143
141
|
# merge in current instance config
|
144
142
|
self.configuration.configure ( aConfiguration )
|
145
143
|
|
146
|
-
# global defaults?
|
147
|
-
self.configuration[:item_decorators] ||= []
|
144
|
+
# global defaults?
|
148
145
|
self.configuration[:for_display] ||= {}
|
149
146
|
|
150
147
|
# check for required keys -- have to be present, and not nil
|
@@ -185,6 +182,9 @@ module BentoSearch
|
|
185
182
|
#
|
186
183
|
# Ask an engine what semantic field names it supports with `engine.semantic_search_keys`
|
187
184
|
#
|
185
|
+
# Unrecognized search fields will be ignored, unless you pass in
|
186
|
+
# :unrecognized_search_field => :raise (or do same in config).
|
187
|
+
#
|
188
188
|
# Ask an engine what sort fields it supports with `engine.sort_keys`. See
|
189
189
|
# list of standard sort keys in I18n file at ./config/locales/en.yml, in
|
190
190
|
# `en.bento_search.sort_keys`.
|
@@ -207,8 +207,7 @@ module BentoSearch
|
|
207
207
|
arguments = normalized_search_arguments(*arguments)
|
208
208
|
|
209
209
|
results = search_implementation(arguments)
|
210
|
-
|
211
|
-
decorate(results)
|
210
|
+
|
212
211
|
|
213
212
|
# standard result metadata
|
214
213
|
results.start = arguments[:start] || 0
|
@@ -220,6 +219,7 @@ module BentoSearch
|
|
220
219
|
results.timing = (Time.now - start_t)
|
221
220
|
|
222
221
|
results.display_configuration = configuration.for_display
|
222
|
+
results.each {|item| item.decorator = configuration.lookup!("for_display.decorator") }
|
223
223
|
|
224
224
|
return results
|
225
225
|
rescue *auto_rescue_exceptions => e
|
@@ -301,14 +301,17 @@ module BentoSearch
|
|
301
301
|
|
302
302
|
# translate semantic_search_field to search_field, or raise if
|
303
303
|
# can't.
|
304
|
-
if (semantic = arguments.delete(:semantic_search_field)) && ! semantic.blank?
|
305
|
-
|
304
|
+
if (semantic = arguments.delete(:semantic_search_field)) && ! semantic.blank?
|
306
305
|
mapped = self.semantic_search_map[semantic.to_s]
|
307
|
-
|
306
|
+
if config_arg(arguments, :unrecognized_search_field) == "raise" && ! mapped
|
308
307
|
raise ArgumentError.new("#{self.class.name} does not know about :semantic_search_field #{semantic}")
|
309
308
|
end
|
310
309
|
arguments[:search_field] = mapped
|
310
|
+
end
|
311
|
+
if config_arg(arguments, :unrecognized_search_field) == "raise" && ! search_keys.include?(arguments[:search_field])
|
312
|
+
raise ArgumentError.new("#{self.class.name} does not know about :search_field #{arguments[:search_field]}")
|
311
313
|
end
|
314
|
+
|
312
315
|
|
313
316
|
return arguments
|
314
317
|
end
|
@@ -328,16 +331,19 @@ module BentoSearch
|
|
328
331
|
|
329
332
|
protected
|
330
333
|
|
331
|
-
#
|
332
|
-
#
|
333
|
-
#
|
334
|
-
def
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
end
|
334
|
+
# get value of an arg that can be supplied in search args OR config,
|
335
|
+
# with search_args over-ridding config. Also normalizes value to_s
|
336
|
+
# (for symbols/strings).
|
337
|
+
def config_arg(arguments, key, default = nil)
|
338
|
+
value = if arguments[key].present?
|
339
|
+
arguments[key]
|
340
|
+
else
|
341
|
+
configuration[key]
|
340
342
|
end
|
343
|
+
|
344
|
+
value = value.to_s if value.kind_of? Symbol
|
345
|
+
|
346
|
+
return value
|
341
347
|
end
|
342
348
|
|
343
349
|
# What exceptions should our #search wrapper rescue and turn
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'nokogiri'
|
2
4
|
|
3
5
|
require 'http_client_patch/include_client'
|
@@ -10,7 +12,41 @@ require 'httpclient'
|
|
10
12
|
#
|
11
13
|
# * profile_id
|
12
14
|
# * profile_password
|
13
|
-
# * databases: ARRAY of ebsco shortcodes of what databases to include in search. If you specify one you don't have access to, you get an error message from ebsco, alas.
|
15
|
+
# * databases: ARRAY of ebsco shortcodes of what databases to include in search. If you specify one you don't have access to, you get an error message from ebsco, alas.
|
16
|
+
#
|
17
|
+
#
|
18
|
+
# == Limits
|
19
|
+
#
|
20
|
+
# While waiting for a future bento_box generalized limit api, this engine
|
21
|
+
# accepts custom search arguments to apply limits:
|
22
|
+
#
|
23
|
+
# [:peer_reviewed_only] Set to boolean true or string 'true', to restrict
|
24
|
+
# results to peer-reviewed only. (Or ask EBSCOHost
|
25
|
+
# api to do so, what we get is what we get).
|
26
|
+
# [:pubyear_start]
|
27
|
+
# [:pubyear_end] Date range limiting, pass in custom search args,
|
28
|
+
# one or both of pubyear_start and pubyear_end
|
29
|
+
# #to_i will be called on it, so can be string.
|
30
|
+
# .search(:query => "foo", :pubyear_start => 2000)
|
31
|
+
#
|
32
|
+
# == Custom response data
|
33
|
+
#
|
34
|
+
# Iff EBSCO API reports that fulltext is available for the hit, then
|
35
|
+
# result.custom_data["fulltext_formats"] will be non-nil, and will be an array of
|
36
|
+
# one or more of EBSCO's internal codes (P=PDF, T=HTML, C=HTML+Images). If
|
37
|
+
# no fulltext is avail according to EBSCO API, result.custom_data["fulltext_formats"]
|
38
|
+
# will be nil.
|
39
|
+
#
|
40
|
+
# #link_is_fulltext also set to true/false
|
41
|
+
#
|
42
|
+
# You can use this to, for instance, hyperlink the displayed title directly
|
43
|
+
# to record on EBSCO if and only if there's fulltext. By writing a custom
|
44
|
+
# decorator. See wiki on decorators.
|
45
|
+
#
|
46
|
+
# == Limitations
|
47
|
+
# We do set language of ResultItems based on what ebsco tells us, but ebsoc
|
48
|
+
# seems to often leave out language or say 'english' for things that are not
|
49
|
+
# (maybe cause abstract is in English?). Config variable to tell us to ignore language?
|
14
50
|
#
|
15
51
|
# == Note on including databases
|
16
52
|
#
|
@@ -59,12 +95,11 @@ require 'httpclient'
|
|
59
95
|
# * DTD of XML Response, hard to interpret but all we've got: http://support.ebsco.com/eit/docs/DTD_EIT_WS_searchResponse.zip
|
60
96
|
#
|
61
97
|
# Hard to find docs page on embedding EBSCO limiters (like peer reviewed only "RV Y") in search query:
|
62
|
-
# http://
|
98
|
+
# http://support.epnet.com/knowledge_base/detail.php?id=5397
|
63
99
|
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
|
67
|
-
# English?). Config variable to tell us to ignore language?
|
100
|
+
# EBSCO searchable support portal has a section for the EIT api we use here:
|
101
|
+
# http://support.epnet.com/knowledge_base/search.php?keyword=&interface_id=1082&document_type=&page_function=search
|
102
|
+
|
68
103
|
class BentoSearch::EbscoHostEngine
|
69
104
|
include BentoSearch::SearchEngine
|
70
105
|
|
@@ -100,6 +135,7 @@ class BentoSearch::EbscoHostEngine
|
|
100
135
|
(fault = xml.at_xpath("./Fault")))
|
101
136
|
|
102
137
|
results.error ||= {}
|
138
|
+
results.error[:api_url] = url
|
103
139
|
results.error[:exception] = exception if exception
|
104
140
|
results.error[:status] = response.status if response
|
105
141
|
|
@@ -126,6 +162,19 @@ class BentoSearch::EbscoHostEngine
|
|
126
162
|
|
127
163
|
end
|
128
164
|
|
165
|
+
# pass in nokogiri record xml for the records/rec node.
|
166
|
+
# Returns nil if NO fulltext is avail on ebsco platform,
|
167
|
+
# non-nil if fulltext is available. Non-nil value will
|
168
|
+
# actually be a non-empty ARRAY of internal EBSCO codes, P=PDF, T=HTML, C=HTML with images.
|
169
|
+
# http://support.epnet.com/knowledge_base/detail.php?topic=996&id=3778&page=1
|
170
|
+
def fulltext_formats(record_xml)
|
171
|
+
fulltext_formats = record_xml.xpath("./header/controlInfo/artinfo/formats/fmt/@type").collect {|n| n.text }
|
172
|
+
|
173
|
+
return nil if fulltext_formats.empty?
|
174
|
+
|
175
|
+
return fulltext_formats
|
176
|
+
end
|
177
|
+
|
129
178
|
|
130
179
|
# Pass in a nokogiri node, return node.text, or nil if
|
131
180
|
# arg was nil or node.text was blank?
|
@@ -144,13 +193,22 @@ class BentoSearch::EbscoHostEngine
|
|
144
193
|
def sniff_format(xml_node)
|
145
194
|
return nil if xml_node.nil?
|
146
195
|
|
147
|
-
|
148
|
-
|
196
|
+
if xml_node.at_xpath("./dissinfo/*")
|
197
|
+
:dissertation
|
198
|
+
elsif xml_node.at_xpath("./jinfo/*") && xml_node.at_xpath("./artinfo/*")
|
149
199
|
"Article"
|
200
|
+
elsif xml_node.at_xpath("./dissinfo/disstl")
|
201
|
+
:dissertation
|
202
|
+
elsif xml_node.at_xpath("./bkinfo") && xml_node.at_xpath("./chapinfo")
|
203
|
+
:book_item
|
204
|
+
elsif xml_node.at_xpath("./bkinfo/btl") && xml_node.at_xpath("./artinfo/tig/atl") &&
|
205
|
+
(text_if_present(xml_node.at_xpath "./bkinfo/btl") != text_if_present(xml_node.at_xpath "./artinfo/tig/atl"))
|
206
|
+
# pathological case of book_item, if it has a bkinfo and an artinfo
|
207
|
+
# but the titles in both sections MATCH, it's just a book. If they're
|
208
|
+
# differnet, it's a book section, bah@
|
209
|
+
:book_item
|
150
210
|
elsif xml_node.at_xpath("./bkinfo/*")
|
151
211
|
"Book"
|
152
|
-
elsif xml_node.at_xpath("./dissinfo/*")
|
153
|
-
:dissertation
|
154
212
|
elsif xml_node.at_xpath("./jinfo/*")
|
155
213
|
:serial
|
156
214
|
else
|
@@ -174,10 +232,15 @@ class BentoSearch::EbscoHostEngine
|
|
174
232
|
components = components.collect {|a| a.titlecase if a}
|
175
233
|
components.uniq! # no need to have the same thing twice
|
176
234
|
|
235
|
+
|
177
236
|
# some hard-coded cases for better user-displayable string, and other
|
178
237
|
# normalization.
|
179
238
|
if ["Academic Journal", "Journal"].include?(components.first) && ["Article", "Journal Article"].include?(components.last)
|
180
239
|
return "Journal Article"
|
240
|
+
elsif components.last == "Book: Monograph"
|
241
|
+
return "Book" # Book: Monograph what??
|
242
|
+
elsif components.first == "Book Article"
|
243
|
+
return "Book Chapter"
|
181
244
|
elsif components.first == "Periodical" && components.length > 1
|
182
245
|
return components.last
|
183
246
|
elsif components.size == 2 && components.first.include?(components.last)
|
@@ -207,7 +270,19 @@ class BentoSearch::EbscoHostEngine
|
|
207
270
|
|
208
271
|
# undocumented but question mark seems to cause a problem for ebsco,
|
209
272
|
# even inside quoted phrases, not sure why.
|
210
|
-
txt.gsub(/[)(\?]/, ' ')
|
273
|
+
txt = txt.gsub(/[)(\?]/, ' ')
|
274
|
+
|
275
|
+
# 'and' and 'or' need to be in phrase quotes to avoid being
|
276
|
+
# interpreted as boolean. For instance, when people just
|
277
|
+
# paste in a title: << A strategy for decreasing anxiety of ICU transfer patients and their families >>
|
278
|
+
# You'd think 'and' as boolean would still work there, but it resulted
|
279
|
+
# in zero hits unless quoted, I dunno. lowercase and uppercase and/or/not
|
280
|
+
# both cause observed weirdness.
|
281
|
+
if ['and', 'or', 'not'].include?( txt.downcase )
|
282
|
+
txt = %Q{"#{txt}"}
|
283
|
+
end
|
284
|
+
|
285
|
+
return txt
|
211
286
|
end
|
212
287
|
|
213
288
|
# Actually turn the user's query into an EBSCO "AND" boolean query,
|
@@ -223,14 +298,12 @@ class BentoSearch::EbscoHostEngine
|
|
223
298
|
ebsco_query_escape(t)
|
224
299
|
end
|
225
300
|
|
226
|
-
|
227
|
-
# make things weird. In phrase quotes they are okay.
|
301
|
+
|
228
302
|
# Remove empty strings. Remove terms that are solely punctuation
|
229
303
|
# without any letters.
|
230
304
|
terms.delete_if do |term|
|
231
305
|
(
|
232
306
|
term.blank? ||
|
233
|
-
["AND", "OR", "NOT"].include?(term) ||
|
234
307
|
term =~ /\A[^[[:alnum:]]]+\Z/
|
235
308
|
)
|
236
309
|
end
|
@@ -251,6 +324,22 @@ class BentoSearch::EbscoHostEngine
|
|
251
324
|
query = "(#{args[:search_field]} #{query})"
|
252
325
|
end
|
253
326
|
|
327
|
+
# peer-reviewed only?
|
328
|
+
if [true, "true"].include? args[:peer_reviewed_only]
|
329
|
+
query += " AND (RV Y)"
|
330
|
+
end
|
331
|
+
|
332
|
+
if args[:pubyear_start] || args[:pubyear_end]
|
333
|
+
from = args[:pubyear_start].to_i
|
334
|
+
from = nil if from == 0
|
335
|
+
|
336
|
+
to = args[:pubyear_end].to_i
|
337
|
+
to = nil if to == 0
|
338
|
+
|
339
|
+
query += " AND (DT #{from}-#{to})"
|
340
|
+
end
|
341
|
+
|
342
|
+
|
254
343
|
url += "&query=#{CGI.escape query}"
|
255
344
|
|
256
345
|
# startrec is 1-based for ebsco, not 0-based like for us.
|
@@ -280,8 +369,33 @@ class BentoSearch::EbscoHostEngine
|
|
280
369
|
item.link = get_link(xml_rec)
|
281
370
|
|
282
371
|
item.issn = text_if_present info.at_xpath("./jinfo/issn")
|
283
|
-
|
284
|
-
|
372
|
+
|
373
|
+
# Dealing with titles is a bit crazy, while articles usually have atitles and
|
374
|
+
# jtitles, sometimes they have a btitle instead. A book will usually have
|
375
|
+
# both btitle and atitle, but sometimes just atitle. Book chapter, oh boy.
|
376
|
+
|
377
|
+
jtitle = text_if_present(info.at_xpath("./jinfo/jtl"))
|
378
|
+
btitle = text_if_present info.at_xpath("./bkinfo/btl")
|
379
|
+
atitle = text_if_present info.at_xpath("./artinfo/tig/atl")
|
380
|
+
|
381
|
+
if jtitle && atitle
|
382
|
+
item.title = atitle
|
383
|
+
item.source_title = jtitle
|
384
|
+
elsif btitle && atitle && atitle != btitle
|
385
|
+
# for a book, sometimes there's an atitle block and a btitle block
|
386
|
+
# when they're identical, this ain't a book section, it's a book.
|
387
|
+
item.title = atitle
|
388
|
+
item.source_title = btitle
|
389
|
+
else
|
390
|
+
item.title = atitle || btitle
|
391
|
+
end
|
392
|
+
# EBSCO sometimes has crazy long titles, truncate em.
|
393
|
+
if item.title.present?
|
394
|
+
item.title = text_helper.truncate(item.title, :length => 200, :separator => ' ', :omission => '…')
|
395
|
+
end
|
396
|
+
|
397
|
+
|
398
|
+
|
285
399
|
item.publisher = text_if_present info.at_xpath("./pubinfo/pub")
|
286
400
|
# if no publisher, but a dissertation institution, use that
|
287
401
|
# as publisher.
|
@@ -294,11 +408,22 @@ class BentoSearch::EbscoHostEngine
|
|
294
408
|
item.isbn = text_if_present info.at_xpath("./bkinfo/isbn")
|
295
409
|
|
296
410
|
item.year = text_if_present info.at_xpath("./pubinfo/dt/@year")
|
411
|
+
# fill in complete publication_date too only if we've got it.
|
412
|
+
if (item.year &&
|
413
|
+
(month = text_if_present info.at_xpath("./pubinfo/dt/@month")) &&
|
414
|
+
(day = text_if_present info.at_xpath("./pubinfo/dt/@day"))
|
415
|
+
)
|
416
|
+
if (item.year.to_i != 0 && month.to_i != 0 && day.to_i != 0)
|
417
|
+
item.publication_date = Date.new(item.year.to_i, month.to_i, day.to_i)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
297
421
|
item.volume = text_if_present info.at_xpath("./pubinfo/vid")
|
298
422
|
item.issue = text_if_present info.at_xpath("./pubinfo/iid")
|
299
423
|
|
300
|
-
|
301
|
-
|
424
|
+
|
425
|
+
|
426
|
+
|
302
427
|
item.start_page = text_if_present info.at_xpath("./artinfo/ppf")
|
303
428
|
|
304
429
|
item.doi = text_if_present info.at_xpath("./artinfo/ui[@type='doi']")
|
@@ -315,15 +440,21 @@ class BentoSearch::EbscoHostEngine
|
|
315
440
|
item.authors << a
|
316
441
|
end
|
317
442
|
|
318
|
-
|
319
|
-
item.
|
320
|
-
item.format_str = sniff_format_str info
|
443
|
+
item.format = sniff_format info
|
444
|
+
item.format_str = sniff_format_str info
|
321
445
|
|
322
446
|
# Totally unreliable, seems to report english for everything? Maybe
|
323
|
-
# because abstracts are in english? Nevertheless we include for now.
|
447
|
+
# because abstracts are in english? Nevertheless we include for now.
|
324
448
|
item.language_code = text_if_present info.at_xpath("./language/@code")
|
325
|
-
|
326
|
-
|
449
|
+
# why does EBSCO return 'undetermined' sometimes? That might as well be
|
450
|
+
# not there, bah.
|
451
|
+
item.language_code = nil if item.language_code == "und"
|
452
|
+
|
453
|
+
# array of custom ebsco codes (or nil) for fulltext formats avail.
|
454
|
+
item.custom_data["fulltext_formats"] = fulltext_formats xml_rec
|
455
|
+
# if any fulltext format, mark present
|
456
|
+
item.link_is_fulltext = item.custom_data["fulltext_formats"].present?
|
457
|
+
|
327
458
|
return item
|
328
459
|
end
|
329
460
|
|
@@ -343,6 +474,10 @@ class BentoSearch::EbscoHostEngine
|
|
343
474
|
return noko
|
344
475
|
end
|
345
476
|
|
477
|
+
def public_settable_search_args
|
478
|
+
super + [:peer_reviewed_only, :pubyear_start, :pubyear_end]
|
479
|
+
end
|
480
|
+
|
346
481
|
# David Walker says pretty much only relevance and date are realiable
|
347
482
|
# in EBSCOhost cross-search.
|
348
483
|
def sort_definitions
|
@@ -351,9 +486,10 @@ class BentoSearch::EbscoHostEngine
|
|
351
486
|
"date_desc" => {:implementation => "date"}
|
352
487
|
}
|
353
488
|
end
|
354
|
-
|
489
|
+
|
355
490
|
def search_field_definitions
|
356
491
|
{
|
492
|
+
nil => {:semantic => :general},
|
357
493
|
"AU" => {:semantic => :author},
|
358
494
|
"TI" => {:semantic => :title},
|
359
495
|
"SU" => {:semantic => :subject},
|
@@ -21,11 +21,6 @@ require 'http_client_patch/include_client'
|
|
21
21
|
# If turned on, you may get <b class="bento_search_highlight"> tags
|
22
22
|
# in title and abstract output if it's on, marked html_safe.
|
23
23
|
#
|
24
|
-
# If highlighting is on, since the abstract will be marked html safe, the
|
25
|
-
# view layer won't be able to safely truncate it. In fact, it's very hard
|
26
|
-
# to do here too, but we do it anyway, by default to approx configuration
|
27
|
-
# truncate_highlighted num of chars (default 280). Set to nil if you don't
|
28
|
-
# want this.
|
29
24
|
#
|
30
25
|
# == Linking
|
31
26
|
#
|
@@ -394,45 +389,7 @@ class BentoSearch::EdsEngine
|
|
394
389
|
else substr.html_safe
|
395
390
|
end
|
396
391
|
end
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
# Crazy ass method to truncate without getting in the middle of our
|
403
|
-
# html tags. This is wacky hacky, yeah.
|
404
|
-
if configuration.truncate_highlighted
|
405
|
-
remainingLength = configuration.truncate_highlighted
|
406
|
-
in_tag = false
|
407
|
-
elipses_added = false
|
408
|
-
|
409
|
-
truncated_parts = []
|
410
|
-
parts.each do |substr|
|
411
|
-
if remainingLength <=0 && ! in_tag
|
412
|
-
truncated_parts << "..."
|
413
|
-
break
|
414
|
-
end
|
415
392
|
|
416
|
-
if substr =~ /^<b.*\>$/
|
417
|
-
truncated_parts << substr
|
418
|
-
in_tag = true
|
419
|
-
elsif substr == "</b>"
|
420
|
-
truncated_parts << substr
|
421
|
-
in_tag = false
|
422
|
-
elsif ((remainingLength - substr.length) > 0) || in_tag
|
423
|
-
truncated_parts << substr
|
424
|
-
else
|
425
|
-
truncated_parts << helper.truncate(substr, :length => remainingLength, :separator => ' ')
|
426
|
-
break
|
427
|
-
end
|
428
|
-
|
429
|
-
remainingLength = remainingLength - substr.length
|
430
|
-
end
|
431
|
-
|
432
|
-
parts = truncated_parts
|
433
|
-
end
|
434
|
-
|
435
|
-
|
436
393
|
return helper.safe_join(parts, '')
|
437
394
|
end
|
438
395
|
|
@@ -552,7 +509,7 @@ class BentoSearch::EdsEngine
|
|
552
509
|
|
553
510
|
def search_field_definitions
|
554
511
|
{
|
555
|
-
"TX" => {:semantic => :
|
512
|
+
"TX" => {:semantic => :general},
|
556
513
|
"AU" => {:semantic => :author},
|
557
514
|
"TI" => {:semantic => :title},
|
558
515
|
"SU" => {:semantic => :subject},
|