pennmarc 1.0.22 → 1.0.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pennmarc/helpers/creator.rb +84 -21
- data/lib/pennmarc/helpers/date.rb +11 -9
- data/lib/pennmarc/mappings/locations.yml +6 -0
- data/lib/pennmarc/version.rb +1 -1
- data/spec/lib/pennmarc/helpers/creator_spec.rb +33 -0
- data/spec/lib/pennmarc/helpers/date_spec.rb +18 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59881d630f244bc6d8b76665df84f4b22297de2d51c44f5272df4226f4e27e75
|
4
|
+
data.tar.gz: 8d4e78c359dea40f482adc5b4deaa3fbb75bbe15a4fce5955ad48de054ce82c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a3a43ff1cecadf978a8c50d59b382c2592925116cacd757f368ea0a698e9b370a94e74fd98e1a6a06a3b837ab0dbdce2efece991aaf3da4b53c74396a73ee2e
|
7
|
+
data.tar.gz: 7f5468f9891c9fe15003160fb4d5a6c04cd8291ead5e803f0652368376e1fd67381195a7bdffd7ea9a7aa996c071b75240405dd956c46d879753f6811eca1b0a
|
@@ -21,6 +21,12 @@ module PennMARC
|
|
21
21
|
|
22
22
|
CONTRIBUTOR_TAGS = %w[700 710].freeze
|
23
23
|
|
24
|
+
FACET_SOURCE_MAP = {
|
25
|
+
100 => 'abcdjq', 110 => 'abcdjq', 111 => 'abcen',
|
26
|
+
700 => 'abcdjq', 710 => 'abcdjq', 711 => 'abcen',
|
27
|
+
800 => 'abcdjq', 810 => 'abcdjq', 811 => 'abcen'
|
28
|
+
}.freeze
|
29
|
+
|
24
30
|
# Author/Creator search field. Includes all subfield values (even ǂ0 URIs) from
|
25
31
|
# {https://www.oclc.org/bibformats/en/1xx/100.html 100 Main Entry--Personal Name} and
|
26
32
|
# {https://www.oclc.org/bibformats/en/1xx/110.html 110 Main Entry--Corporate Name}. Maps any relator codes found
|
@@ -51,19 +57,33 @@ module PennMARC
|
|
51
57
|
end
|
52
58
|
|
53
59
|
# Retrieve creator values for display from fields {https://www.loc.gov/marc/bibliographic/bd100.html 100}
|
54
|
-
# and {https://www.loc.gov/marc/bibliographic/bd110.html 110} and their linked alternates.
|
55
|
-
#
|
60
|
+
# and {https://www.loc.gov/marc/bibliographic/bd110.html 110} and their linked alternates. First, joins subfields
|
61
|
+
# other than $0, $1, $4, $6, $8, $e, and w. Then, appends any encoded relators found in $4.
|
62
|
+
# If there are no valid encoded relators, uses the value found in $e.
|
56
63
|
# @param [MARC::Record] record
|
57
64
|
# @return [Array<String>] array of author/creator values for display
|
58
65
|
def show(record, relator_map: Mappers.relator)
|
59
66
|
fields = record.fields(TAGS)
|
60
67
|
fields += record.fields('880').select { |field| subfield_value?(field, '6', /^(#{TAGS.join('|')})/) }
|
61
68
|
fields.filter_map { |field|
|
62
|
-
|
63
|
-
append_relator(field: field, joined_subfields: creator, relator_term_sf: 'e', relator_map: relator_map)
|
69
|
+
parse_show_value(field, relator_map: relator_map)
|
64
70
|
}.uniq
|
65
71
|
end
|
66
72
|
|
73
|
+
# Hash with main creator show values as the fields and the corresponding facet as the values.
|
74
|
+
# Does not include linked 880s.
|
75
|
+
# @param [MARC::Record] record
|
76
|
+
# @param [Hash] relator_map
|
77
|
+
# @return [Hash]
|
78
|
+
def show_facet_map(record, relator_map: Mappers.relator)
|
79
|
+
creators = record.fields(TAGS).filter_map do |field|
|
80
|
+
show = parse_show_value(field, relator_map: relator_map)
|
81
|
+
facet = parse_facet_value(field, FACET_SOURCE_MAP[field.tag.to_i].chars)
|
82
|
+
{ show: show, facet: facet }
|
83
|
+
end
|
84
|
+
creators.to_h { |h| [h[:show], h[:facet]] }
|
85
|
+
end
|
86
|
+
|
67
87
|
# All author/creator values for display (like #show, but multivalued?) - no 880 linkage
|
68
88
|
# Performs additional normalization of author names
|
69
89
|
# @note ported from get_author_creator_values (indexed as author_creator_a) - shown on results page
|
@@ -94,14 +114,9 @@ module PennMARC
|
|
94
114
|
# @param [MARC::Record] record
|
95
115
|
# @return [Array<String>] array of author/creator values for faceting
|
96
116
|
def facet(record)
|
97
|
-
|
98
|
-
100 => 'abcdjq', 110 => 'abcdjq', 111 => 'abcen',
|
99
|
-
700 => 'abcdjq', 710 => 'abcdjq', 711 => 'abcen',
|
100
|
-
800 => 'abcdjq', 810 => 'abcdjq', 811 => 'abcen'
|
101
|
-
}
|
102
|
-
source_map.flat_map { |field_num, subfields|
|
117
|
+
FACET_SOURCE_MAP.flat_map { |field_num, subfields|
|
103
118
|
record.fields(field_num.to_s).map do |field|
|
104
|
-
|
119
|
+
parse_facet_value(field, subfields.chars)
|
105
120
|
end
|
106
121
|
}.uniq
|
107
122
|
end
|
@@ -117,7 +132,11 @@ module PennMARC
|
|
117
132
|
}.uniq
|
118
133
|
end
|
119
134
|
|
120
|
-
# Conference detailed display, intended for record show page.
|
135
|
+
# Conference detailed display, intended for record show page. Retrieve conference values for record display from
|
136
|
+
# {https://www.loc.gov/marc/bibliographic/bd111.html 111}, {https://www.loc.gov/marc/bibliographic/bd711.html 711}
|
137
|
+
# , and their linked 880s. If there is no $i, we join subfield $i we join subfield values other than
|
138
|
+
# $0, $4, $5, $6, $8, $e, $j, and $w. to create the conference value. We then join the conference subunit value
|
139
|
+
# using subfields $e and $w. We append any relators, preferring those defined in $4 and using $j as a fallback.
|
121
140
|
# @note ported from get_conference_values
|
122
141
|
# @todo what is ǂi for?
|
123
142
|
# @param [MARC::Record] record
|
@@ -126,15 +145,7 @@ module PennMARC
|
|
126
145
|
conferences = record.fields(%w[111 711]).filter_map do |field|
|
127
146
|
next unless field.indicator2.in? ['', ' ']
|
128
147
|
|
129
|
-
|
130
|
-
join_subfields field, &subfield_not_in?(%w[0 4 5 6 8 e j w])
|
131
|
-
else
|
132
|
-
''
|
133
|
-
end
|
134
|
-
sub_unit = join_subfields(field, &subfield_in?(%w[e w]))
|
135
|
-
conf = [conf, sub_unit].compact_blank.join(' ')
|
136
|
-
|
137
|
-
append_relator(field: field, joined_subfields: conf, relator_term_sf: 'j', relator_map: relator_map)
|
148
|
+
parse_conference_detail_show_value(field, relator_map: relator_map)
|
138
149
|
end
|
139
150
|
conferences += record.fields('880').filter_map do |field|
|
140
151
|
next unless subfield_value? field, '6', /^(111|711)/
|
@@ -150,6 +161,24 @@ module PennMARC
|
|
150
161
|
conferences.uniq
|
151
162
|
end
|
152
163
|
|
164
|
+
# Return hash of detailed conference values mapped to their corresponding facets from fields
|
165
|
+
# {https://www.loc.gov/marc/bibliographic/bd111.html 111} and
|
166
|
+
# {https://www.loc.gov/marc/bibliographic/bd711.html 711}. Does not include linked 880s.
|
167
|
+
# @param [MARC::Record] record
|
168
|
+
# @param [Hash] relator_map
|
169
|
+
# @return [Hash]
|
170
|
+
def conference_detail_show_facet_map(record, relator_map: Mappers.relator)
|
171
|
+
conferences = record.fields(%w[111 711]).filter_map do |field|
|
172
|
+
next unless field.indicator2.in? ['', ' ']
|
173
|
+
|
174
|
+
show = parse_conference_detail_show_value(field, relator_map: relator_map)
|
175
|
+
facet = parse_facet_value(field, FACET_SOURCE_MAP[field.tag.to_i].chars)
|
176
|
+
{ show: show, facet: facet }
|
177
|
+
end
|
178
|
+
|
179
|
+
conferences.to_h { |conf| [conf[:show], conf[:facet]] }
|
180
|
+
end
|
181
|
+
|
153
182
|
# Conference name values for searching
|
154
183
|
# @param [MARC::Record] record
|
155
184
|
# @return [Array<String>]
|
@@ -264,6 +293,40 @@ module PennMARC
|
|
264
293
|
before_comma = substring_before(name, ', ')
|
265
294
|
"#{after_comma} #{before_comma}".squish
|
266
295
|
end
|
296
|
+
|
297
|
+
# Parse creator facet value from given creator field and desired subfields
|
298
|
+
# @param [MARC::Field] field
|
299
|
+
# @param [Array<String>] subfields
|
300
|
+
# @return [String]
|
301
|
+
def parse_facet_value(field, subfields)
|
302
|
+
trim_punctuation(join_subfields(field, &subfield_in?(subfields)))
|
303
|
+
end
|
304
|
+
|
305
|
+
# Parse creator show value from given main creator fields (100/110).
|
306
|
+
# @param [MARC::Field] field
|
307
|
+
# @param [Hash] relator_map
|
308
|
+
# @return [String]
|
309
|
+
def parse_show_value(field, relator_map: Mappers.relator)
|
310
|
+
creator = join_subfields(field, &subfield_not_in?(%w[0 1 4 6 8 e w]))
|
311
|
+
append_relator(field: field, joined_subfields: creator, relator_term_sf: 'e', relator_map: relator_map)
|
312
|
+
end
|
313
|
+
|
314
|
+
# Parse detailed conference show value from given conference field (111/711). If there is no $i, we join subfield
|
315
|
+
# values other than $0, $4, $5, $6, $8, $e, $j, and $w to create conference value. We join subfields $e and $w to
|
316
|
+
# determine the subunit value. We append any relators, preferring those defined in $4 and using $j as a fallback.
|
317
|
+
# @param [MARC::Field] field
|
318
|
+
# @return [String]
|
319
|
+
def parse_conference_detail_show_value(field, relator_map: Mappers.relator)
|
320
|
+
conf = if subfield_undefined? field, 'i'
|
321
|
+
join_subfields field, &subfield_not_in?(%w[0 4 5 6 8 e j w])
|
322
|
+
else
|
323
|
+
''
|
324
|
+
end
|
325
|
+
sub_unit = join_subfields(field, &subfield_in?(%w[e w]))
|
326
|
+
conf = [conf, sub_unit].compact_blank.join(' ')
|
327
|
+
|
328
|
+
append_relator(field: field, joined_subfields: conf, relator_term_sf: 'j', relator_map: relator_map)
|
329
|
+
end
|
267
330
|
end
|
268
331
|
end
|
269
332
|
end
|
@@ -8,14 +8,14 @@ module PennMARC
|
|
8
8
|
# Publication date is a four-digit year found in position 7-10 and may contain 'u' characters to represent
|
9
9
|
# partially known dates. We replace any occurrences of 'u' with '0' before converting to DateTime object.
|
10
10
|
# @param [MARC::Record] record
|
11
|
-
# @return [
|
11
|
+
# @return [Time, nil] The publication date, or nil if date found in record is invalid
|
12
12
|
def publication(record)
|
13
13
|
record.fields('008').filter_map { |field|
|
14
14
|
four_digit_year = sanitize_partially_known_date(field.value[7, 4], '0')
|
15
15
|
|
16
16
|
next if four_digit_year.blank?
|
17
17
|
|
18
|
-
|
18
|
+
Time.new(four_digit_year.to_i)
|
19
19
|
}.first
|
20
20
|
end
|
21
21
|
|
@@ -23,7 +23,7 @@ module PennMARC
|
|
23
23
|
# {PennMARC::Enriched} maps enriched marc fields and subfields created during Alma publishing. The enriched
|
24
24
|
# metadata provided by the Alma API does not include the date created value, so we can't work with that here.
|
25
25
|
# @param [MARC::Record] record
|
26
|
-
# @return [
|
26
|
+
# @return [Time, nil] The date added, or nil if date found in record is invalid
|
27
27
|
def added(record)
|
28
28
|
record.fields(Enriched::Pub::ITEM_TAG).flat_map { |field|
|
29
29
|
subfield_values(field, Enriched::Pub::ITEM_DATE_CREATED).filter_map do |date_added|
|
@@ -34,9 +34,10 @@ module PennMARC
|
|
34
34
|
|
35
35
|
format = date_added.size == 10 ? '%Y-%m-%d' : '%Y-%m-%d %H:%M:%S'
|
36
36
|
|
37
|
-
|
37
|
+
Time.strptime(date_added, format)
|
38
38
|
rescue StandardError => e
|
39
|
-
puts
|
39
|
+
puts 'Error parsing date in date added subfield. ' \
|
40
|
+
"mmsid: #{Identifier.mmsid(record)}, value: #{date_added}, error: #{e}"
|
40
41
|
nil
|
41
42
|
end
|
42
43
|
}.max
|
@@ -46,7 +47,7 @@ module PennMARC
|
|
46
47
|
# Date last updated is a sixteen character String recorded in
|
47
48
|
# {https://www.iso.org/iso-8601-date-and-time-format.html ISO 8601} format.
|
48
49
|
# @param [MARC::Record] record
|
49
|
-
# @return [
|
50
|
+
# @return [Time, nil] The date last updated, or nil if date found in record is invalid
|
50
51
|
def last_updated(record)
|
51
52
|
record.fields('005').filter_map { |field|
|
52
53
|
begin
|
@@ -56,9 +57,10 @@ module PennMARC
|
|
56
57
|
|
57
58
|
next if date_time_string.start_with?('0000')
|
58
59
|
|
59
|
-
|
60
|
-
rescue
|
61
|
-
puts
|
60
|
+
Time.strptime(date_time_string, '%Y%m%d%H%M%S.%N')
|
61
|
+
rescue StandardError => e
|
62
|
+
puts 'Error parsing last updated date. ' \
|
63
|
+
"mmsid: #{Identifier.mmsid(record)}, value: #{date_time_string}, error: #{e}"
|
62
64
|
nil
|
63
65
|
end
|
64
66
|
}.first
|
@@ -547,6 +547,12 @@ dent:
|
|
547
547
|
- Health Sciences Libraries
|
548
548
|
- Levy Dental Medicine Library
|
549
549
|
display: Levy Dental Medicine Library - Stacks
|
550
|
+
dentpcare:
|
551
|
+
specific_location: Levy Dental Medicine Library - PCare
|
552
|
+
library:
|
553
|
+
- Health Sciences Libraries
|
554
|
+
- Levy Dental Medicine Library
|
555
|
+
display: Levy Dental Medicine Library - PCare
|
550
556
|
dentrare:
|
551
557
|
specific_location: Levy Dental Medicine Library - Rare Books
|
552
558
|
library:
|
data/lib/pennmarc/version.rb
CHANGED
@@ -95,6 +95,23 @@ describe 'PennMARC::Creator' do
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
+
describe '.show_facet_map' do
|
99
|
+
let(:record) do
|
100
|
+
marc_record fields: [
|
101
|
+
marc_field(tag: '100', subfields: { a: 'Surname, Name', '0': 'http://cool.uri/12345', d: '1900-2000',
|
102
|
+
e: 'author.', '4': 'http://cool.uri/vocabulary/relators/aut' }),
|
103
|
+
marc_field(tag: '110', subfields: { a: 'Group of People', b: 'Annual Meeting', '4': 'aut' }),
|
104
|
+
marc_field(tag: '880', subfields: { a: 'Ignore', '6': '100' })
|
105
|
+
]
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'returns expected hash' do
|
109
|
+
values = helper.show_facet_map(record, relator_map: mapping)
|
110
|
+
expect(values).to eq({ 'Surname, Name 1900-2000, author.' => 'Surname, Name 1900-2000',
|
111
|
+
'Group of People Annual Meeting, Author.' => 'Group of People Annual Meeting' })
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
98
115
|
describe '.show_aux' do
|
99
116
|
let(:record) { marc_record fields: fields }
|
100
117
|
|
@@ -257,6 +274,22 @@ describe 'PennMARC::Creator' do
|
|
257
274
|
end
|
258
275
|
end
|
259
276
|
|
277
|
+
describe '.conference_detail_show_facet_map' do
|
278
|
+
let(:record) do
|
279
|
+
marc_record fields: [
|
280
|
+
marc_field(tag: '111', subfields: { a: 'Council of Trent', d: '(1545-1563 :', c: 'Trento, Italy)' }),
|
281
|
+
marc_field(tag: '711', subfields: { a: 'Code4Lib', n: '(18th :', d: '2024 :', c: 'Ann Arbor, MI)' }),
|
282
|
+
marc_field(tag: '880', subfields: { a: 'Alt Ignore', '6': '111' })
|
283
|
+
]
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'returns the expected hash' do
|
287
|
+
value = helper.conference_detail_show_facet_map(record)
|
288
|
+
expect(value).to eq({ 'Council of Trent (1545-1563 : Trento, Italy)' => 'Council of Trent Trento, Italy)',
|
289
|
+
'Code4Lib (18th : 2024 : Ann Arbor, MI)' => 'Code4Lib (18th : Ann Arbor, MI)' })
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
260
293
|
describe '.conference_search' do
|
261
294
|
let(:record) do
|
262
295
|
marc_record fields: [
|
@@ -10,7 +10,7 @@ describe 'PennMARC::Date' do
|
|
10
10
|
let(:fields) { [marc_control_field(tag: '008', value: '130827s2010 nyu o 000 1 eng d')] }
|
11
11
|
|
12
12
|
it 'returns publication date' do
|
13
|
-
expect(helper.publication(record)).to eq(
|
13
|
+
expect(helper.publication(record)).to eq(Time.new(2010))
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'returns a year value' do
|
@@ -33,7 +33,7 @@ describe 'PennMARC::Date' do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'returns only the expected date_added value' do
|
36
|
-
expect(helper.added(record)).to eq
|
36
|
+
expect(helper.added(record)).to eq Time.strptime('2023-10-19', '%Y-%m-%d')
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'does not output any warning to STDOUT' do
|
@@ -47,7 +47,7 @@ describe 'PennMARC::Date' do
|
|
47
47
|
let(:fields) { [marc_field(tag: 'itm', subfields: { q: '2023-06-28' })] }
|
48
48
|
|
49
49
|
it 'returns expected value' do
|
50
|
-
expect(helper.added(record)).to eq(
|
50
|
+
expect(helper.added(record)).to eq(Time.strptime('2023-06-28', '%Y-%m-%d'))
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'returns a year value' do
|
@@ -59,7 +59,7 @@ describe 'PennMARC::Date' do
|
|
59
59
|
let(:fields) { [marc_field(tag: 'itm', subfields: { q: '2023-06-29 11:04:30:10' })] }
|
60
60
|
|
61
61
|
it 'returns expected value' do
|
62
|
-
expect(helper.added(record)).to eq(
|
62
|
+
expect(helper.added(record)).to eq(Time.strptime('2023-06-29 11:04:30:10', '%Y-%m-%d %H:%M:%S'))
|
63
63
|
end
|
64
64
|
|
65
65
|
it 'returns a year value' do
|
@@ -74,12 +74,15 @@ describe 'PennMARC::Date' do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'returns most recent date' do
|
77
|
-
expect(helper.added(record)).to eq(
|
77
|
+
expect(helper.added(record)).to eq(Time.strptime('2023-06-29', '%Y-%m-%d'))
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
81
|
context 'with invalid date' do
|
82
|
-
let(:fields)
|
82
|
+
let(:fields) do
|
83
|
+
[marc_control_field(tag: '001', value: 'mmsid'),
|
84
|
+
marc_field(tag: 'itm', subfields: { q: 'invalid date' })]
|
85
|
+
end
|
83
86
|
|
84
87
|
it 'returns nil' do
|
85
88
|
expect(helper.added(record)).to be_nil
|
@@ -88,7 +91,8 @@ describe 'PennMARC::Date' do
|
|
88
91
|
it 'outputs error message' do
|
89
92
|
expect {
|
90
93
|
helper.added(record)
|
91
|
-
}.to output(
|
94
|
+
}.to output('Error parsing date in date added subfield. mmsid: mmsid, value: invalid date, ' \
|
95
|
+
"error: invalid date or strptime format - `invalid date' `%Y-%m-%d %H:%M:%S'\n").to_stdout
|
92
96
|
end
|
93
97
|
end
|
94
98
|
end
|
@@ -97,7 +101,7 @@ describe 'PennMARC::Date' do
|
|
97
101
|
let(:fields) { [marc_field(tag: '005', subfields: { q: '20230213163851.1' })] }
|
98
102
|
|
99
103
|
it 'returns date last updated' do
|
100
|
-
expect(helper.last_updated(record)).to eq(
|
104
|
+
expect(helper.last_updated(record)).to eq(Time.strptime('20230213163851.1', '%Y%m%d%H%M%S.%N'))
|
101
105
|
end
|
102
106
|
|
103
107
|
it 'returns year value' do
|
@@ -105,7 +109,10 @@ describe 'PennMARC::Date' do
|
|
105
109
|
end
|
106
110
|
|
107
111
|
context 'with invalid date' do
|
108
|
-
let(:fields)
|
112
|
+
let(:fields) do
|
113
|
+
[marc_control_field(tag: '001', value: 'mmsid'),
|
114
|
+
marc_field(tag: '005', subfields: { q: 'invalid date' })]
|
115
|
+
end
|
109
116
|
|
110
117
|
it 'returns nil' do
|
111
118
|
expect(helper.last_updated(record)).to be_nil
|
@@ -114,7 +121,8 @@ describe 'PennMARC::Date' do
|
|
114
121
|
it 'outputs error message' do
|
115
122
|
expect {
|
116
123
|
helper.last_updated(record)
|
117
|
-
}.to output(
|
124
|
+
}.to output('Error parsing last updated date. mmsid: mmsid, value: invalid date, ' \
|
125
|
+
"error: invalid date or strptime format - `invalid date' `%Y%m%d%H%M%S.%N'\n").to_stdout
|
118
126
|
end
|
119
127
|
end
|
120
128
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pennmarc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Kanning
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-
|
13
|
+
date: 2024-06-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|