Skip to content

Commit 22eb852

Browse files
authored
Merge pull request #242 from MITLibraries/use-73-timdex-normalization
Refactor how TIMDEX records are nomalized
2 parents 04e57ad + a7d2d68 commit 22eb852

16 files changed

+560
-81
lines changed

app/controllers/search_controller.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ def load_gdt_results
4747

4848
# Handle errors
4949
@errors = extract_errors(response)
50-
@pagination = Analyzer.new(@enhanced_query, response).pagination if @errors.nil?
51-
@results = extract_results(response)
50+
return unless @errors.nil?
51+
52+
@pagination = Analyzer.new(@enhanced_query, response).pagination
53+
raw_results = extract_results(response)
54+
@results = NormalizeTimdexResults.new(raw_results, @enhanced_query[:q]).normalize
5255
@filters = extract_filters(response)
5356
end
5457

@@ -77,8 +80,11 @@ def load_timdex_results
7780
response = query_timdex(query)
7881

7982
@errors = extract_errors(response)
80-
@pagination = Analyzer.new(@enhanced_query, response).pagination if @errors.nil?
81-
@results = extract_results(response)
83+
return unless @errors.nil?
84+
85+
@pagination = Analyzer.new(@enhanced_query, response).pagination
86+
raw_results = extract_results(response)
87+
@results = NormalizeTimdexResults.new(raw_results, @enhanced_query[:q]).normalize
8288
end
8389

8490
def active_filters

app/helpers/search_helper.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ def format_highlight_label(field_name)
1515
end
1616

1717
def view_online(result)
18-
return unless result['sourceLink'].present?
18+
return unless result['source_link'].present?
1919

20-
link_to 'View online', result['sourceLink'], class: 'button button-primary'
20+
link_to 'View online', result['source_link'], class: 'button button-primary'
2121
end
2222

2323
def view_record(record_id)

app/models/normalize_primo_record.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Transforms a PNX doc from Primo Search API into a normalized record.
1+
# Transforms a Primo Search API result into a normalized record.
22
class NormalizePrimoRecord
33
def initialize(record, query)
44
@record = record
@@ -7,22 +7,24 @@ def initialize(record, query)
77

88
def normalize
99
{
10+
# Core fields
1011
'title' => title,
1112
'creators' => creators,
1213
'source' => source,
1314
'year' => year,
1415
'format' => format,
1516
'links' => links,
1617
'citation' => citation,
17-
'container' => container_title,
1818
'identifier' => record_id,
1919
'summary' => summary,
20-
'numbering' => numbering,
21-
'chapter_numbering' => chapter_numbering,
22-
'thumbnail' => thumbnail,
2320
'publisher' => publisher,
2421
'location' => best_location,
2522
'subjects' => subjects,
23+
# Primo-specific fields
24+
'container' => container_title,
25+
'numbering' => numbering,
26+
'chapter_numbering' => chapter_numbering,
27+
'thumbnail' => thumbnail,
2628
'availability' => best_availability,
2729
'other_availability' => other_availability?
2830
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Transforms a TIMDEX result into a normalized record.
2+
class NormalizeTimdexRecord
3+
def initialize(record, query)
4+
@record = record
5+
@query = query
6+
end
7+
8+
def normalize
9+
{
10+
# Core fields
11+
'title' => title,
12+
'creators' => creators,
13+
'source' => source,
14+
'year' => year,
15+
'format' => format,
16+
'links' => links,
17+
'citation' => citation,
18+
'identifier' => identifier,
19+
'summary' => summary,
20+
'publisher' => publisher,
21+
'location' => location,
22+
'subjects' => subjects,
23+
# TIMDEX-specific fields
24+
'content_type' => content_type,
25+
'dates' => dates,
26+
'contributors' => contributors,
27+
'highlight' => highlight,
28+
'source_link' => source_link
29+
}
30+
end
31+
32+
private
33+
34+
def title
35+
@record['title'] || 'Unknown title'
36+
end
37+
38+
def creators
39+
return [] unless @record['contributors']
40+
41+
# Convert TIMDEX contributors to Primo-style creators format
42+
@record['contributors']
43+
.select { |c| %w[Creator Author].include?(c['kind']) }
44+
.map { |creator| { 'value' => creator['value'], 'link' => nil } }
45+
end
46+
47+
def source
48+
return 'Unknown source' unless @record['source']
49+
50+
@record['source']
51+
end
52+
53+
def year
54+
# Extract year from dates
55+
return nil unless @record['dates']
56+
57+
pub_date = @record['dates'].find { |date| date['kind'] == 'Publication date' }
58+
return pub_date['value']&.match(/\d{4}/)&.to_s if pub_date
59+
60+
# Fallback to any date with a year
61+
@record['dates'].each do |date|
62+
year_match = date['value']&.match(/\d{4}/)
63+
return year_match.to_s if year_match
64+
end
65+
end
66+
67+
def format
68+
return '' unless @record['contentType']
69+
70+
@record['contentType'].map { |type| type['value'] }.join(' ; ')
71+
end
72+
73+
def links
74+
links = []
75+
76+
# Add source link if available
77+
if @record['sourceLink']
78+
links << {
79+
'kind' => 'full record',
80+
'url' => @record['sourceLink'],
81+
'text' => 'View full record'
82+
}
83+
end
84+
85+
links
86+
end
87+
88+
def citation
89+
@record['citation'] || nil
90+
end
91+
92+
def summary
93+
return nil unless @record['summary']
94+
95+
@record['summary'].is_a?(Array) ? @record['summary'].join(' ') : @record['summary']
96+
end
97+
98+
def publisher
99+
# Extract from contributors or other fields
100+
return nil unless @record['contributors']
101+
102+
publisher = @record['contributors'].find { |c| c['kind'] == 'Publisher' }
103+
publisher&.dig('value')
104+
end
105+
106+
def location
107+
return nil unless @record['locations']
108+
109+
@record['locations'].map { |loc| loc['value'] }.compact.join('; ')
110+
end
111+
112+
def subjects
113+
return [] unless @record['subjects']
114+
115+
@record['subjects'].map { |subject| subject['value'] }
116+
end
117+
118+
def identifier
119+
@record['timdexRecordId']
120+
end
121+
122+
# TIMDEX-specific methods
123+
def content_type
124+
@record['contentType']
125+
end
126+
127+
def dates
128+
@record['dates']
129+
end
130+
131+
def contributors
132+
@record['contributors']
133+
end
134+
135+
def highlight
136+
@record['highlight']
137+
end
138+
139+
def source_link
140+
@record['sourceLink']
141+
end
142+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Batch normalization for TIMDEX API results
2+
class NormalizeTimdexResults
3+
def initialize(results, query)
4+
@results = results
5+
@query = query
6+
end
7+
8+
def normalize
9+
return [] unless @results.is_a?(Array)
10+
11+
@results.filter_map do |doc|
12+
NormalizeTimdexRecord.new(doc, @query).normalize
13+
end
14+
end
15+
end

app/views/search/_result.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<li class="result">
22
<div class="result-content">
33
<h3 class="record-title">
4-
<span class="sr">Title: </span><%= link_to(result['title'], record_path(result['timdexRecordId'])) %>
4+
<span class="sr">Title: </span><%= link_to(result['title'], record_path(result['identifier'])) %>
55
</h3>
66

77
<p class="pub-info">
8-
<span><%= result['contentType']&.each { |type| type['value'] }&.join(' ; ') %></span>
8+
<span><%= result['content_type']&.each { |type| type['value'] }&.join(' ; ') %></span>
99
<span>
1010
<% result['dates']&.each do |date| %>
1111
<%= date['value'] if date['kind'] == 'Publication date' %>
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,38 @@
11
<li class="result">
22
<div class="result-content">
33
<h3 class="record-title">
4-
<span class="sr">Title: </span><%= link_to(result_geo['title'], record_path(result_geo['timdexRecordId'])) %>
4+
<span class="sr">Title: </span><%= link_to(result_geo['title'], record_path(result_geo['identifier'])) %>
55
</h3>
66

77
<div class="data-info">
88
<%= render partial: 'shared/geo_data_info', locals: { metadata: result_geo } %>
99
</div>
1010

11-
<% if result_geo['contributors'] %>
11+
<% if result_geo['creators'].present? || result_geo['contributors'].present? %>
1212
<span class="sr">Contributors: </span>
1313
<ul class="list-inline truncate-list contributors">
14-
<%= render partial: 'shared/contributors', locals: { contributors: result_geo['contributors'] } %>
14+
<!-- Use normalized creators if available, otherwise fall back to raw contributors -->
15+
<% contributors = result_geo['creators'].present? ? result_geo['creators'] : result_geo['contributors'] %>
16+
<% if contributors %>
17+
<%= render partial: 'shared/contributors', locals: { contributors: contributors } %>
18+
<% end %>
1519
</ul>
1620
<% end %>
1721

18-
<% if result_geo['summary'] %>
22+
<% if result_geo['summary'].present? %>
1923
<p class="result-summary truncate-list">
20-
<span class="sr">Summary: </span><%= result_geo['summary'].join(' ') %>
24+
<span class="sr">Summary: </span><%= result_geo['summary'] %>
2125
</p>
2226
<% end %>
2327

2428
<% if result_geo['highlight'] %>
2529
<div class="result-highlights">
26-
<%= render partial: 'search/highlights', locals: { result: result_geo } %>
30+
<%= render partial: 'search/highlights', locals: { result: { 'highlight' => result_geo['highlight'] } } %>
2731
</div>
2832
<% end %>
2933

3034
<div class="result-record">
31-
<%= view_record(result_geo['timdexRecordId']) %>
35+
<%= view_record(result_geo['identifier']) %>
3236
</div>
3337
</div>
3438
</li>

app/views/search/_result_primo.html.erb

Lines changed: 14 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
<div class="result-content">
33
<h3 class="record-title">
44
<span class="sr">Title: </span>
5-
<% if result_primo['links']&.find { |link| link['kind'] == 'full record' } %>
6-
<%= link_to(result_primo['title'], result_primo['links'].find { |link| link['kind'] == 'full record' }['url']) %>
5+
<% if result['links']&.find { |link| link['kind'] == 'full record' } %>
6+
<%= link_to(result['title'], result['links'].find { |link| link['kind'] == 'full record' }['url']) %>
77
<% else %>
8-
<%= result_primo['title'] %>
8+
<%= result['title'] %>
99
<% end %>
1010
</h3>
1111

1212
<p class="pub-info">
13-
<span><%= result_primo['format'] %></span>
14-
<span><%= result_primo['year'] %></span>
13+
<span><%= result['format'] %></span>
14+
<span><%= result['year'] %></span>
1515
</p>
1616

17-
<% if result_primo['creators'].present? %>
17+
<% if result['creators'].present? %>
1818
<span class="sr">Contributors: </span>
1919
<ul class="list-inline truncate-list contributors">
20-
<% result_primo['creators'].each do |creator| %>
20+
<% result['creators'].each do |creator| %>
2121
<li>
2222
<% if creator[:link] %>
2323
<%= link_to creator[:value], creator[:link] %>
@@ -29,49 +29,12 @@
2929
</ul>
3030
<% end %>
3131

32-
<% if result_primo['container'].present? %>
33-
<p class="pub-info">
34-
<span class="sr">Published in: </span>
35-
<em><%= result_primo['container'] %></em>
36-
</p>
37-
<% end %>
38-
39-
<% if result_primo['citation'].present? %>
40-
<p class="citation">
41-
<span class="sr">Citation: </span>
42-
<%= result_primo['citation'] %>
43-
</p>
44-
<% end %>
45-
46-
<% if result_primo['summary'].present? %>
47-
<p class="summary">
48-
<span class="sr">Summary: </span>
49-
<%= truncate(result_primo['summary'], length: 300) %>
50-
</p>
51-
<% end %>
52-
53-
<% if result_primo['subjects'].present? %>
54-
<p class="subjects">
55-
<span class="sr">Subjects: </span>
56-
<%= result_primo['subjects'].join('; ') %>
57-
</p>
58-
<% end %>
59-
60-
<% if result_primo['links'].present? %>
61-
<ul class="list-inline links">
62-
<% result_primo['links'].each do |link| %>
63-
<li>
64-
<%= link_to link['kind'].titleize, link['url'], class: 'link-button' %>
65-
</li>
32+
<div class="result-get">
33+
<% if result['links'].present? %>
34+
<% result['links'].each do |link| %>
35+
<%= link_to link['kind'].titleize, link['url'], class: 'link-button' %>
6636
<% end %>
67-
</ul>
68-
<% end %>
69-
70-
<% if result_primo['availability'].present? %>
71-
<p class="availability">
72-
<span class="sr">Availability: </span>
73-
<span class="availability-status"><%= result_primo['availability'] %></span>
74-
</p>
75-
<% end %>
37+
<% end %>
38+
</div>
7639
</div>
77-
</li>
40+
</li>

app/views/search/results.html.erb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@
3838
<% if @results.present? && @errors.blank? %>
3939
<h2 class="hd-3 results-context"><%= results_summary(@pagination[:hits]) %> returned</h2>
4040
<ol class="results-list" start="<%= @pagination[:start] %>">
41-
<% if @active_tab == 'primo' %>
42-
<%= render(partial: 'search/result_primo', collection: @results) %>
43-
<% else %>
44-
<%= render(partial: 'search/result', collection: @results) %>
41+
<% case @active_tab %>
42+
<% when 'primo' %>
43+
<%= render(partial: 'search/result_primo', collection: @results, as: :result) %>
44+
<% when 'timdex' %>
45+
<%= render(partial: 'search/result', collection: @results, as: :result) %>
4546
<% end %>
4647
</ol>
4748
<% elsif @errors.blank? %>

0 commit comments

Comments
 (0)