umlaut 4.0.3 → 4.1.0.pre.2
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.
- checksums.yaml +8 -8
- data/README.md +6 -0
- data/app/assets/javascripts/umlaut/update_html.js +81 -23
- data/app/assets/stylesheets/umlaut/_misc.scss +1 -2
- data/app/assets/stylesheets/umlaut/_resolve.scss +44 -10
- data/app/controllers/export_email_controller.rb +2 -2
- data/app/controllers/feedback_controller.rb +1 -1
- data/app/controllers/umlaut/controller_behavior.rb +14 -0
- data/app/controllers/umlaut_configurable.rb +52 -21
- data/app/helpers/open_search_helper.rb +1 -1
- data/app/helpers/resolve_helper.rb +36 -35
- data/app/helpers/umlaut/section_highlights.rb +85 -0
- data/app/mixin_logic/metadata_helper.rb +11 -5
- data/app/models/collection.rb +129 -96
- data/app/models/dispatched_service.rb +4 -0
- data/app/models/referent.rb +7 -1
- data/app/models/request.rb +21 -0
- data/app/models/service_store.rb +16 -3
- data/app/presentation/section_renderer.rb +16 -17
- data/app/service_adaptors/blacklight.rb +11 -4
- data/app/service_adaptors/internet_archive.rb +58 -25
- data/app/service_adaptors/isi.rb +14 -4
- data/app/service_adaptors/jcr.rb +13 -4
- data/app/views/resolve/_fulltext.html.erb +1 -1
- data/app/views/resolve/_section_display.html.erb +1 -1
- data/app/views/resolve/_service_errors.html.erb +3 -3
- data/app/views/search/books.html.erb +1 -1
- data/app/views/search/journal_search.html.erb +2 -1
- data/app/views/search/journals.html.erb +2 -1
- data/db/orig_fixed_data/service_type_values.yml +15 -37
- data/lib/aws_product_sign.rb +1 -1
- data/lib/generators/templates/umlaut_services.yml +5 -2
- data/lib/generators/umlaut/install_generator.rb +1 -0
- data/{app/models → lib}/service_type_value.rb +36 -22
- data/lib/umlaut/routes.rb +34 -5
- data/lib/umlaut/test_help.rb +159 -0
- data/lib/umlaut/version.rb +2 -2
- data/lib/umlaut.rb +44 -9
- metadata +10 -8
@@ -108,31 +108,30 @@ class InternetArchive < Service
|
|
108
108
|
timeout(@http_timeout.to_i) {
|
109
109
|
response = open(link).read
|
110
110
|
}
|
111
|
+
|
111
112
|
if response.blank?
|
112
113
|
raise Exception.new("InternetArchive returned empty response for #{link}")
|
113
114
|
end
|
114
115
|
|
115
|
-
|
116
116
|
doc = MultiJson.load(response)
|
117
117
|
results = doc['response']['docs']
|
118
118
|
|
119
119
|
@mediatypes.each do |type|
|
120
|
-
|
121
|
-
|
122
|
-
|
120
|
+
hits = matching_hits(request, search_terms, results, type)
|
123
121
|
|
124
122
|
|
125
123
|
# if we have more results than we want to show in the main view
|
126
124
|
# we can ceate a link (highlighted_link) to the search in the sidebar
|
127
|
-
|
128
|
-
|
125
|
+
|
126
|
+
num_found = hits.length #doc['response']['numFound']
|
127
|
+
if (@show_web_link and not hits.empty? and @num_results_for_types[type] < num_found )
|
129
128
|
do_web_link(request, search_terms, type, num_found)
|
130
129
|
end
|
131
130
|
|
132
131
|
# Check for search inside only for first result of type 'text'
|
133
132
|
if (@include_search_inside &&
|
134
133
|
type == 'texts' &&
|
135
|
-
(first_hit =
|
134
|
+
(first_hit = hits[0]) &&
|
136
135
|
(identifier = first_hit["identifier"])
|
137
136
|
)
|
138
137
|
direct_url = URI.parse("http://www.archive.org/stream/" + identifier)
|
@@ -152,21 +151,21 @@ class InternetArchive < Service
|
|
152
151
|
)
|
153
152
|
end
|
154
153
|
end
|
155
|
-
|
154
|
+
|
155
|
+
|
156
|
+
|
156
157
|
# add a service response for each result for this mediatype
|
157
|
-
|
158
|
-
break if index
|
158
|
+
hits.each_with_index do |result, index|
|
159
|
+
break if index >= @num_results_for_types[type]
|
160
|
+
|
159
161
|
display_name = @display_name
|
160
162
|
|
161
|
-
if
|
163
|
+
if result["contributor"] && result["contributor"].first
|
164
|
+
display_name += ": " + result["contributor"].first
|
165
|
+
elsif ( result["collection"] && COLLECTION_LABELS[result["collection"][0]])
|
162
166
|
display_name += ": " + COLLECTION_LABELS[result["collection"][0]]
|
163
|
-
elsif ( result["collection"])
|
164
|
-
display_name += ": " + result["collection"][0].titlecase
|
165
167
|
end
|
166
168
|
|
167
|
-
#note = result['title']
|
168
|
-
#note << " by " << result['creator'].join(', ') if result['creator']
|
169
|
-
|
170
169
|
service_type = SERVICE_TYPE_MAP[type]
|
171
170
|
request.add_service_response(
|
172
171
|
:service=>self,
|
@@ -175,7 +174,7 @@ class InternetArchive < Service
|
|
175
174
|
:url=>create_result_url(result),
|
176
175
|
:match_reliability => ServiceResponse::MatchUnsure,
|
177
176
|
:edition_str => edition_str(result),
|
178
|
-
:service_type_value => service_type )
|
177
|
+
:service_type_value => service_type )
|
179
178
|
end
|
180
179
|
end
|
181
180
|
end
|
@@ -262,20 +261,54 @@ class InternetArchive < Service
|
|
262
261
|
|
263
262
|
return output
|
264
263
|
end
|
265
|
-
|
266
264
|
|
267
|
-
def
|
268
|
-
|
265
|
+
def matching_hits(request, search_terms, results, type)
|
266
|
+
full_title = raw_search_title(request.referent)
|
267
|
+
|
268
|
+
hits = results.find_all do |r|
|
269
|
+
r["mediatype"] == type &&
|
270
|
+
titles_sufficiently_matched(search_terms[:title], full_title, r["title"])
|
271
|
+
end
|
272
|
+
|
273
|
+
return hits
|
274
|
+
end
|
275
|
+
|
276
|
+
# Some obtuse code to heuristically decide if our query title and a result
|
277
|
+
# title fuzzily match sufficiently to be considered a match.
|
278
|
+
def titles_sufficiently_matched(query_title, full_title, result)
|
279
|
+
normalized_query = normalize_title(query_title)
|
280
|
+
normalized_full_title = normalize_title(full_title)
|
281
|
+
# If the title has more than 3 words, and our IA query returned
|
282
|
+
# a result for it -- that's probably good enough.
|
283
|
+
return true if normalized_query.split(" ").length > 3
|
284
|
+
|
285
|
+
|
286
|
+
# Otherwise, make multiple versions of the candidate
|
287
|
+
# title -- the whole thing, the title until the first colon,
|
288
|
+
# and the title until the first comma or semi-colon or other punct. Normalize
|
289
|
+
# them all. See if any of them match EITHER our search title or
|
290
|
+
# our full title.
|
291
|
+
candidates = [
|
292
|
+
result,
|
293
|
+
result.split(":").first,
|
294
|
+
result.split(/[\;\,\(\)]/).first
|
295
|
+
].compact.uniq.collect {|a| normalize_title(a)}
|
296
|
+
|
297
|
+
return (candidates & [normalized_query, normalized_full_title]).present?
|
269
298
|
end
|
270
299
|
|
271
300
|
def edition_str(result)
|
272
|
-
|
301
|
+
edition_str = ""
|
273
302
|
|
274
|
-
|
275
|
-
parts.push( result['publisher'] ) unless result['publisher'].blank?
|
276
|
-
parts.push( result['year']) unless result['year'].blank?
|
303
|
+
edition_str << result['title'] unless result['title'].blank?
|
277
304
|
|
278
|
-
edition_str
|
305
|
+
edition_str << " / #{result['creator'].first}" unless result['creator'].blank?
|
306
|
+
edition_str << ". #{result["publisher"].first}" unless result['publisher'].blank?
|
307
|
+
unless result['date'].blank?
|
308
|
+
year = result['date'].slice(0,4)
|
309
|
+
edition_str << ": #{year}"
|
310
|
+
end
|
311
|
+
|
279
312
|
edition_str = nil if edition_str.blank?
|
280
313
|
|
281
314
|
return edition_str
|
data/app/service_adaptors/isi.rb
CHANGED
@@ -11,8 +11,9 @@
|
|
11
11
|
# (LAMR) service api, which is used here. To register, see:
|
12
12
|
# http://wokinfo.com/products_tools/products/related/amr/
|
13
13
|
#
|
14
|
-
# You register by IP address, so no
|
15
|
-
# goes through
|
14
|
+
# You can register by IP address, so no auth key is needed once your registration
|
15
|
+
# goes through -- or fill out 'username' and 'password' config elements in service
|
16
|
+
# setup, and they will be used.
|
16
17
|
#
|
17
18
|
# If you later need to change the IP addresses entitled to use this API, use
|
18
19
|
# http://scientific.thomson.com/scientific/techsupport/cpe/form.html.
|
@@ -126,8 +127,17 @@ class Isi < Service
|
|
126
127
|
builder.request(:xmlns => "http://www.isinet.com/xrpc41", :src => "app.id=Umlaut") do
|
127
128
|
builder.fn(:name => "LinksAMR.retrieve") do
|
128
129
|
builder.list do
|
129
|
-
# first map is authentication info. empty 'map' element
|
130
|
-
|
130
|
+
# first map is authentication info. empty 'map' element if we are IP authenticated.
|
131
|
+
if @username && @password
|
132
|
+
builder.map do
|
133
|
+
builder.val(@username, :name => "username")
|
134
|
+
builder.val(@password, :name => "password")
|
135
|
+
end
|
136
|
+
else
|
137
|
+
builder.map
|
138
|
+
end
|
139
|
+
|
140
|
+
|
131
141
|
# specify what we're requesting
|
132
142
|
builder.map do
|
133
143
|
builder.list(:name=>"WOS") do
|
data/app/service_adaptors/jcr.rb
CHANGED
@@ -12,8 +12,9 @@
|
|
12
12
|
# register, see:
|
13
13
|
# http://wokinfo.com/products_tools/products/related/amr/
|
14
14
|
#
|
15
|
-
# You register by IP address, so no
|
16
|
-
# goes through
|
15
|
+
# You register by IP address, so no auth info is needed once your registration
|
16
|
+
# goes through -- or you can receive a username and password, in which case
|
17
|
+
# you should configure keys 'username' and 'password'
|
17
18
|
#
|
18
19
|
# If you later need to change the IP addresses entitled to use this API, use
|
19
20
|
# http://scientific.thomson.com/scientific/techsupport/cpe/form.html.
|
@@ -76,8 +77,16 @@ class Jcr < Service
|
|
76
77
|
builder.request(:xmlns => "http://www.isinet.com/xrpc41", :src => "app.id=Umlaut") do
|
77
78
|
builder.fn(:name => "LinksAMR.retrieve") do
|
78
79
|
builder.list do
|
79
|
-
# first map is authentication info. empty 'map' element
|
80
|
-
|
80
|
+
# first map is authentication info. empty 'map' element if we are IP authenticated.
|
81
|
+
if @username && @password
|
82
|
+
builder.map do
|
83
|
+
builder.val(@username, :name => "username")
|
84
|
+
builder.val(@password, :name => "password")
|
85
|
+
end
|
86
|
+
else
|
87
|
+
builder.map
|
88
|
+
end
|
89
|
+
|
81
90
|
# specify what we're requesting
|
82
91
|
builder.map do
|
83
92
|
builder.list(:name=>"JCR") do
|
@@ -6,7 +6,7 @@ end
|
|
6
6
|
# order em with full fulltxt before title_level_fulltxt
|
7
7
|
all_responses = fulltxt + title_level_fulltxt
|
8
8
|
%>
|
9
|
-
<div class="<%= section_css_classes(@user_request, "fulltext"
|
9
|
+
<div class="<%= section_css_classes(@user_request, "fulltext").join(" ") %>">
|
10
10
|
<%= render 'section_heading', :presenter => renderer, :force_render => true %>
|
11
11
|
<div class="umlaut_section_content">
|
12
12
|
<%= list_with_limit('umlaut_fulltext', all_responses,
|
@@ -4,7 +4,7 @@
|
|
4
4
|
-%>
|
5
5
|
<% if presenter.visible? %>
|
6
6
|
<% unless presenter.show_partial_only? %>
|
7
|
-
<div class="<%= section_css_classes(@user_request, presenter.div_id
|
7
|
+
<div class="<%= section_css_classes(@user_request, presenter.div_id).join(" ") %>">
|
8
8
|
<% end %>
|
9
9
|
<%= render 'section_heading', :presenter => presenter %>
|
10
10
|
<% unless presenter.show_partial_only? %>
|
@@ -1,14 +1,14 @@
|
|
1
1
|
<%
|
2
2
|
failed_dispatches = failed_service_dispatches()
|
3
3
|
unless ( failed_dispatches.nil? || failed_dispatches.empty? ) %>
|
4
|
-
<div id="service_errors_content">
|
4
|
+
<div id="service_errors_content" class="alert alert-danger">
|
5
5
|
<h5 class="warning"><i class="umlaut_icons-famfamfam-error"></i> <%= t 'umlaut.error.service_errors_title' %></h5>
|
6
6
|
<ul class="list-unstyled">
|
7
7
|
<% failed_dispatches.each do | dispatch | %>
|
8
8
|
<li class="text-small">
|
9
9
|
<%= t 'umlaut.error.services_missing' %><strong> <%= dispatch.service.service_types_generated.collect { |type|
|
10
|
-
type.display_name_pluralize}.join(", ")%></strong>
|
11
|
-
<%= t 'umlaut.resolve.from_service' %> <a class="collapse-toggle" data-target="<%= "#failed_dispatch_#{dispatch.id}"%>" data-toggle="collapse"><strong><%= dispatch.service.display_name %></strong></a>
|
10
|
+
type.display_name_pluralize}.uniq.join(", ")%></strong>
|
11
|
+
<%= t 'umlaut.resolve.from_service' %> <a class="collapse-toggle alert-link" data-target="<%= "#failed_dispatch_#{dispatch.id}"%>" data-toggle="collapse"><strong><%= dispatch.service.display_name %></strong></a>
|
12
12
|
<% exception_info = dispatch.exception_info %>
|
13
13
|
<div id="<%= "failed_dispatch_#{dispatch.id}"%>" class="collapse">
|
14
14
|
<ul class="nav nav-list">
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<h1>Books</h1>
|
4
4
|
<%= form_tag({:controller=>'resolve', :action=>@submit_action}, {:method=>'get', :class=>"form-horizontal"}) %>
|
5
5
|
<fieldset class="citationLinker">
|
6
|
-
<%= hidden_field_tag "rfr_id", "
|
6
|
+
<%= hidden_field_tag "rfr_id", umlaut_config.lookup!("rfr_ids.citation") %>
|
7
7
|
<%= hidden_field_tag "url_ver", "Z39.88-2004" %>
|
8
8
|
<%= hidden_field_tag "url_ctx_fmt", "info:ofi/fmt:kev:mtx:ctx" %>
|
9
9
|
<%= hidden_field_tag "ctx_ver", "Z39.88-2004" %>
|
@@ -2,7 +2,8 @@
|
|
2
2
|
<%= form_tag({:controller=>'search', :action=>'journal_search'}, {:method=>'get', :name=>'OpenURL', :id=>'OpenURL', :class => "form-inline form-very-inline"}) %>
|
3
3
|
<div class="umlaut-search-form">
|
4
4
|
<fieldset>
|
5
|
-
|
5
|
+
|
6
|
+
<%= hidden_field_tag "rfr_id", umlaut_config.lookup!("rfr_ids.citation") %>
|
6
7
|
<%= hidden_field_tag "rft.title", "", {:class => "rft_title"} %>
|
7
8
|
<%= hidden_field_tag "rft.object_id", "", {:class => "rft_object_id"} %>
|
8
9
|
<%= hidden_field_tag "rft.issn", "" %>
|
@@ -8,7 +8,8 @@
|
|
8
8
|
<div class="umlaut-search-form">
|
9
9
|
<fieldset>
|
10
10
|
<legend><%=t 'umlaut.search.journals_instructions' %></legend>
|
11
|
-
|
11
|
+
|
12
|
+
<%= hidden_field_tag "rfr_id", umlaut_config.lookup!("rfr_ids.citation") %>
|
12
13
|
<%= hidden_field_tag "rft.date", "" %>
|
13
14
|
<%= hidden_field_tag "rft.title", "", {:class => "rft_title"} %>
|
14
15
|
<%= hidden_field_tag "rft.object_id", "", {:class => "rft_object_id"} %>
|
@@ -3,129 +3,107 @@
|
|
3
3
|
#
|
4
4
|
# Which makes this file at present just a list of names and ids; if we had
|
5
5
|
# to do it over, we'd do this differently.
|
6
|
+
#
|
7
|
+
# You can add your own additional service types in a local app config/service_type_values.yml,
|
8
|
+
# or by calling ServiceTypeValue.merge_yml_file!(path_to_yml_file)
|
6
9
|
fulltext:
|
7
|
-
|
8
|
-
|
9
|
-
display_name_plural: electronic_versions
|
10
|
+
display_name: Electronic Version
|
11
|
+
display_name_plural: Electronic Versions
|
10
12
|
|
11
13
|
holding:
|
12
|
-
id: 2
|
13
14
|
display_name: Copy in Library
|
14
|
-
display_name_plural:
|
15
|
+
display_name_plural: Copies in Library
|
15
16
|
|
16
17
|
document_delivery:
|
17
|
-
id: 3
|
18
18
|
display_name: Request Service
|
19
|
-
display_name_plural:
|
19
|
+
display_name_plural: Request Services
|
20
20
|
|
21
21
|
help:
|
22
|
-
id: 4
|
23
22
|
display_name: Help Link
|
24
|
-
display_name_plural:
|
23
|
+
display_name_plural: Help Links
|
25
24
|
|
26
25
|
# Not currently used
|
27
26
|
web_link:
|
28
|
-
id: 5
|
29
27
|
display_name: Web Result
|
30
|
-
display_name_plural:
|
28
|
+
display_name_plural: Web Results
|
31
29
|
|
32
30
|
# Not currently used.
|
33
31
|
relevant_link:
|
34
|
-
id: 6
|
35
32
|
display_name: Closest Web Result
|
36
33
|
|
37
34
|
abstract:
|
38
|
-
id: 11
|
39
35
|
display_name: Abstract
|
40
|
-
display_name_plural:
|
36
|
+
display_name_plural: Abstracts
|
41
37
|
|
42
38
|
table_of_contents:
|
43
|
-
id: 12
|
44
39
|
display_name: Table of Contents
|
45
|
-
display_name_plural:
|
40
|
+
display_name_plural: Tables of Contents
|
46
41
|
|
47
42
|
cover_image:
|
48
|
-
id: 13
|
49
43
|
display_name: Cover Image
|
50
|
-
display_name_plural:
|
44
|
+
display_name_plural: Cover Images
|
51
45
|
|
52
46
|
# "See also" links to known destinations, like Amazon or OCLC
|
53
47
|
highlighted_link:
|
54
|
-
id: 14
|
55
48
|
display_name: See Also Link
|
56
|
-
display_name_plural:
|
49
|
+
display_name_plural: See Also Links
|
57
50
|
|
58
51
|
# Link to search holdings, generally with a count given, ie "5 possible matches".
|
59
52
|
holding_search:
|
60
|
-
id: 15
|
61
53
|
display_name: Copy in Library
|
62
|
-
display_name_plural:
|
54
|
+
display_name_plural: Copies in Library
|
63
55
|
|
64
56
|
# This is meant for 'fulltext' from such sources as the OPAC/ILS, where
|
65
57
|
# it will always be a title-level link, and dates of coverage usually
|
66
58
|
# aren't checked. DEPRECATED. No longer used, use a fulltext wtih :coverage_checked
|
67
59
|
# and/or :can_link_to_article set to false.
|
68
60
|
fulltext_title_level:
|
69
|
-
id: 16
|
70
61
|
display_name: Electronic Text Version
|
71
62
|
|
72
63
|
audio:
|
73
|
-
id: 17
|
74
64
|
display_name: Digital Audio
|
75
65
|
|
76
66
|
# A search inside tool, presented with a search box for user.
|
77
67
|
search_inside:
|
78
|
-
id: 18
|
79
68
|
display_name: Search Inside Tool
|
80
69
|
|
81
70
|
# A tool that will enhance the Referent metadata. Not always advertised
|
82
71
|
# properly yet.
|
83
72
|
referent_enhance:
|
84
|
-
id: 19
|
85
73
|
display_name: More Information
|
86
74
|
|
87
75
|
# Link to partial text, as in Amazon or Google Books that don't have
|
88
76
|
# full text, only excerpts.
|
89
77
|
excerpts:
|
90
|
-
id: 20
|
91
78
|
display_name: Limited Excerpts
|
92
79
|
|
93
80
|
cited_by:
|
94
|
-
id: 21
|
95
81
|
display_name: Article that cites this
|
96
82
|
display_name_plural: Articles that cite this
|
97
83
|
|
98
84
|
# Used by ISI and Scopus at present. Maybe more later.
|
99
85
|
# "More like this" links.
|
100
86
|
similar:
|
101
|
-
id: 22
|
102
87
|
display_name: "Similar Articles"
|
103
88
|
|
104
89
|
|
105
90
|
# Not sure what this is used for. Think it's a typo for abstract.
|
106
91
|
description:
|
107
|
-
id: 100
|
108
92
|
display_name: Description
|
109
93
|
|
110
94
|
# Not sure if this is used for anything yet, but some services generate
|
111
95
|
subject:
|
112
|
-
id: 101
|
113
96
|
display_name: Subject
|
114
97
|
|
115
98
|
# Not used yet by views
|
116
99
|
similar_item:
|
117
|
-
id: 102
|
118
100
|
display_name: Similar Item
|
119
101
|
|
120
102
|
# Used to save/send the citation/holdings
|
121
103
|
export_citation:
|
122
|
-
id: 103
|
123
104
|
display_name: Export tool
|
124
|
-
display_name_plural:
|
105
|
+
display_name_plural: Export Tools
|
125
106
|
|
126
107
|
primo_source:
|
127
|
-
id: 104
|
128
108
|
display_name: Primo Source
|
129
109
|
|
130
|
-
# If you want to add your own custom ones, make them start with ids at 100000,
|
131
|
-
# to leave plenty of space for future standard umlaut ones.
|
data/lib/aws_product_sign.rb
CHANGED
@@ -85,7 +85,7 @@ class AwsProductSign
|
|
85
85
|
|
86
86
|
# chomp is important! the base64 encoded version will have a newline at the end
|
87
87
|
# which amazon does not want.
|
88
|
-
digest = OpenSSL::Digest
|
88
|
+
digest = OpenSSL::Digest.new('sha256')
|
89
89
|
signature = Base64.encode64(OpenSSL::HMAC.digest(digest, secret_key, string_to_sign)).chomp
|
90
90
|
|
91
91
|
params["Signature"] = signature
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
# Configure what service plugins are used by Umlaut. This skeleton file
|
3
2
|
# has been generated into your app to help you get started.
|
4
3
|
#
|
@@ -8,10 +7,14 @@
|
|
8
7
|
# Most services take other options for custom configuration too, not
|
9
8
|
# all options are neccesarily listed as examples here, see source
|
10
9
|
# or source-generated docs for more info.
|
11
|
-
|
10
|
+
#
|
12
11
|
# The services in the 'default' group are loaded every time.
|
13
12
|
# You can optionally create other groups of services, that can be loaded
|
14
13
|
# by URL query params, or based on other request params. More info?
|
14
|
+
#
|
15
|
+
# This file is run through ERB, so you can use <%= %> tags for dynamic
|
16
|
+
# ruby content if you like.
|
17
|
+
#
|
15
18
|
|
16
19
|
default:
|
17
20
|
services:
|
@@ -2,7 +2,11 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
|
4
4
|
# This model is the actual list of valid service types. Not ActiveRecord,
|
5
|
-
# just load from config
|
5
|
+
# just load from config/service_type_values.yml into memory (loaded on file load, initialization)
|
6
|
+
#
|
7
|
+
# This is stored in lib/ intentionally, to avoid Rails dev-mode auto-reloading,
|
8
|
+
# because we store state in this class, and reloading was losing state we
|
9
|
+
# intentionally set, eg for plugins adding new service types.
|
6
10
|
#
|
7
11
|
# ServiceTypeValues have human-displayable names, that are controlled by Rails I18n,
|
8
12
|
# using standard Rails I18n pluralization forms, so for instance:
|
@@ -13,6 +17,10 @@ require 'yaml'
|
|
13
17
|
#
|
14
18
|
# Other languages may have more complex pluralization rules, but Umlaut at present only
|
15
19
|
# looks up a plural form for 10 items, so 'other' is probably all that is used.
|
20
|
+
#
|
21
|
+
# If you want to load additional custom service type values from your own custom .yml file
|
22
|
+
# (say in a plugin), do `ServiceTypeValue.merge_yml_file!( filepath_to_yml )`, perhaps
|
23
|
+
# in an initializer.
|
16
24
|
class ServiceTypeValue
|
17
25
|
attr_accessor :name, :id
|
18
26
|
attr_writer :display_name, :display_name_plural
|
@@ -25,10 +33,10 @@ class ServiceTypeValue
|
|
25
33
|
end
|
26
34
|
end
|
27
35
|
|
28
|
-
def self.find(name)
|
29
|
-
load_values! if values.nil?
|
36
|
+
def self.find(name)
|
30
37
|
values[name.to_sym] or raise ArgumentError.new("No ServiceTypeValue found for #{name}")
|
31
38
|
end
|
39
|
+
|
32
40
|
def self.[](name)
|
33
41
|
find(name)
|
34
42
|
end
|
@@ -52,24 +60,30 @@ class ServiceTypeValue
|
|
52
60
|
|
53
61
|
# Loads from config files, distro and local, into memory.
|
54
62
|
def self.load_values!
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
service_type_values.each_pair do |name, hash|
|
72
|
-
self.values[name.to_sym] = ServiceTypeValue.new(hash.merge(:name => name))
|
73
|
-
end
|
63
|
+
# Load in starting set of ServiceTypeValue, merge in local defines.
|
64
|
+
self.merge_yml_file! @@distro_conf_file
|
65
|
+
|
66
|
+
|
67
|
+
if File.exists?( @@local_conf_file )
|
68
|
+
self.merge_yml_file! @@local_conf_file
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.merge_hash!(definition_hash)
|
74
|
+
self.values ||= {}
|
75
|
+
|
76
|
+
definition_hash.each_pair do |name, value_hash|
|
77
|
+
self.values[name.to_sym] = ServiceTypeValue.new(value_hash.merge(:name => name))
|
78
|
+
end
|
74
79
|
end
|
80
|
+
|
81
|
+
def self.merge_yml_file!(filepath)
|
82
|
+
self.merge_hash! YAML.load_file(filepath)
|
83
|
+
end
|
84
|
+
|
85
|
+
# We're doing this outside of a method body on purpose, when this
|
86
|
+
# file gets loaded, immediately load the default values.
|
87
|
+
self.load_values!
|
88
|
+
|
75
89
|
end
|
data/lib/umlaut/routes.rb
CHANGED
@@ -7,6 +7,8 @@ module Umlaut
|
|
7
7
|
# app routes.rb, that line is generated into local app by Umlaut generator.
|
8
8
|
# options include :only and :except to limit what route groups are generated.
|
9
9
|
class Routes
|
10
|
+
class_attribute :default_route_sets
|
11
|
+
self.default_route_sets = [:root, :permalinks, :a_z, :resolve, :open_search, :link_router, :export_email, :resources, :search, :javascript, :feedback]
|
10
12
|
|
11
13
|
def initialize(router, options ={})
|
12
14
|
@router = router
|
@@ -19,6 +21,37 @@ module Umlaut
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
24
|
+
|
25
|
+
# Experimental functionality for a plugin to add routes that automatically
|
26
|
+
# will get applied by Umlaut::Routes
|
27
|
+
#
|
28
|
+
# Umlaut::Routes.register_routes( YourPlugin::RouteSets )
|
29
|
+
#
|
30
|
+
# Where YourPlugin::RouteSets is a module containing methods that defines
|
31
|
+
# routes similar to Umlaut::Routes::RouteSets below.
|
32
|
+
#
|
33
|
+
# If some methods included in the module are not route-defining methods,
|
34
|
+
# pass a second arg listing just those that are:
|
35
|
+
#
|
36
|
+
# Umlaut::Routes.register_routes(YourPlugin::RouteSets, [:magic, :underwater])
|
37
|
+
#
|
38
|
+
# All route_set_methods will be applied by default, but can be excluded
|
39
|
+
# on application with the standard Umlaut::RouteSet :only and :except args.
|
40
|
+
#
|
41
|
+
# This design is somewhat experimental, we'll see if it meets real world use cases
|
42
|
+
# with maintainable code.
|
43
|
+
def self.register_routes(module_obj, route_set_methods = nil)
|
44
|
+
if route_set_methods.nil?
|
45
|
+
# default to all methods defined in module
|
46
|
+
route_set_methods = module_obj.instance_methods
|
47
|
+
end
|
48
|
+
|
49
|
+
include module_obj
|
50
|
+
self.default_route_sets.concat route_set_methods
|
51
|
+
|
52
|
+
return self
|
53
|
+
end
|
54
|
+
|
22
55
|
protected
|
23
56
|
|
24
57
|
def add_routes &blk
|
@@ -30,10 +63,6 @@ module Umlaut
|
|
30
63
|
(@options[:only] || default_route_sets) - (@options[:except] || []) + (@options[:admin] == true ? [:admin] : [])
|
31
64
|
end
|
32
65
|
|
33
|
-
def default_route_sets
|
34
|
-
[:root, :permalinks, :a_z, :resolve, :open_search, :link_router, :export_email, :resources, :search, :javascript, :feedback]
|
35
|
-
end
|
36
|
-
|
37
66
|
module RouteSets
|
38
67
|
# for now include root generation in Umlaut auto-generation
|
39
68
|
def root
|
@@ -101,7 +130,7 @@ module Umlaut
|
|
101
130
|
# legacy with the index, to keep old bookmarks working, needs to come first
|
102
131
|
get 'link_router/index(/:id)' => "link_router#index"
|
103
132
|
|
104
|
-
get 'link_router/:id' => "link_router#index"
|
133
|
+
get 'link_router/:id' => "link_router#index", :as => "link_router"
|
105
134
|
|
106
135
|
end
|
107
136
|
end
|