pennmarc 1.3.3 → 1.3.4
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 +4 -4
- data/lib/pennmarc/helpers/access.rb +74 -1
- data/lib/pennmarc/helpers/creator.rb +11 -3
- data/lib/pennmarc/mappings/locations.yml +2 -66
- data/lib/pennmarc/version.rb +1 -1
- data/spec/lib/pennmarc/helpers/access_spec.rb +59 -0
- data/spec/lib/pennmarc/helpers/creator_spec.rb +3 -3
- 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: 3409e098b2447b1f3eb3295e8df39d2b3e5133a9594f93f0b017132700b3fdd6
|
4
|
+
data.tar.gz: 02a38f6ffff4ce8032b4f60e9bcc2de3945c14b8d249bf83e2ffff26cb8c1a60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e3c34f9063ca03595f9e45adf23c4f8c4f27a369b874eaf9944ce11b60f16cf8298bfb7a169094c5fe9b6b1fc726eb68272b996085c5092a65d03bce9bde893
|
7
|
+
data.tar.gz: c304b6f45e769ecc13cb0b17230448a87d1f52b5fe496587663ed88383cc4a7288a4422dbca685c6229fee69fae8d6964ee9d332bb95c6aa0dd5e04ced5909b7
|
@@ -7,12 +7,15 @@ module PennMARC
|
|
7
7
|
AT_THE_LIBRARY = 'At the library'
|
8
8
|
HANDLE_BASE_URL = 'hdl.library.upenn.edu'
|
9
9
|
COLENDA_BASE_URL = 'colenda.library.upenn.edu'
|
10
|
+
REQUIRED_ONLINE_MARC_INDICATOR_COUNT = 2
|
10
11
|
|
11
12
|
class << self
|
12
13
|
# Based on enhanced metadata fields added by Alma publishing process or API, determine if the record has
|
13
14
|
# electronic access or has physical holdings, and is therefore "Online" or "At the library". If a record is "At
|
14
15
|
# the library", but has a link to a finding aid in the 856 field (matching certain criteria), also add 'Online' as
|
15
16
|
# an access method.
|
17
|
+
# Because Alma E-Collections don't return electronic inventory, check some MARC control fields and other fields
|
18
|
+
# for indicators of an online resource, but only if no other Online indicators are present.
|
16
19
|
# @param record [MARC::Record]
|
17
20
|
# @return [Array]
|
18
21
|
def facet(record)
|
@@ -24,7 +27,7 @@ module PennMARC
|
|
24
27
|
return values if values.size == 2 # return early if all values are already present
|
25
28
|
|
26
29
|
# only check if ONLINE isn't already there
|
27
|
-
values << ONLINE if values.exclude?(ONLINE) &&
|
30
|
+
values << ONLINE if values.exclude?(ONLINE) && marc_indicators?(record)
|
28
31
|
values.uniq
|
29
32
|
end
|
30
33
|
|
@@ -44,6 +47,24 @@ module PennMARC
|
|
44
47
|
field.tag.in? [Enriched::Pub::PHYS_INVENTORY_TAG, Enriched::Api::PHYS_INVENTORY_TAG]
|
45
48
|
end
|
46
49
|
|
50
|
+
# In order to determine if a record has Online access, we should also check some MARC fields. This is because the
|
51
|
+
# Alma inventory publishing process does not include tags for E-Collections associated with a record. Here we
|
52
|
+
# check for obvious indicators:
|
53
|
+
# - a "Resource Link" matching certain criteria
|
54
|
+
# - a field indicating that the record is part of our curated "Databases" collection
|
55
|
+
# If there's still no online access, check for at least two other positive indicators in other MARC control fields
|
56
|
+
# and other tags.
|
57
|
+
# @param record [MARC::Record]
|
58
|
+
# @return [Boolean]
|
59
|
+
def marc_indicators?(record)
|
60
|
+
return true if resource_link?(record) || electronic_database?(record)
|
61
|
+
|
62
|
+
[eresource_form?(record),
|
63
|
+
eresource_material_designation?(record),
|
64
|
+
online_computer_file_form?(record),
|
65
|
+
online_carrier_type?(record)].count(true) >= REQUIRED_ONLINE_MARC_INDICATOR_COUNT
|
66
|
+
end
|
67
|
+
|
47
68
|
# Check if a record contains an 856 entry with a Penn Handle server link meeting these criteria:
|
48
69
|
# 1. Indicator 1 is 4 (HTTP resource)
|
49
70
|
# 2. Indicator 2 is NOT 2 (indicating the linkage is to a "related" thing)
|
@@ -58,6 +79,58 @@ module PennMARC
|
|
58
79
|
record.fields('856').any? { |field| valid_resource_field?(field) }
|
59
80
|
end
|
60
81
|
|
82
|
+
# Does the record have an 006 suggesting an electronic resource?
|
83
|
+
# Check position 6 "Form of item" for an `o` indicating "Online"
|
84
|
+
# @see https://www.loc.gov/marc/bibliographic/bd006.html
|
85
|
+
# @see https://www.loc.gov/marc/bibliographic/bd008c.html
|
86
|
+
# @param record [MARC::Record]
|
87
|
+
# @return [Boolean]
|
88
|
+
def eresource_form?(record)
|
89
|
+
return false unless field_defined?(record, '006')
|
90
|
+
|
91
|
+
record.fields('006').first.value[6] == 'o'
|
92
|
+
end
|
93
|
+
|
94
|
+
# Does the record have an 007 indicating an electronic resource?
|
95
|
+
# Check pos 0 for a `c` ("Electronic resource") and position 1 for an `r` ("Remote")
|
96
|
+
# @see https://www.loc.gov/marc/bibliographic/bd007c.html
|
97
|
+
# @param record [MARC::Record]
|
98
|
+
# @return [Boolean]
|
99
|
+
def eresource_material_designation?(record)
|
100
|
+
return false unless field_defined?(record, '007')
|
101
|
+
|
102
|
+
record.fields('007').first.value[0..1] == 'cr'
|
103
|
+
end
|
104
|
+
|
105
|
+
# Does the record have an 008 indicating an electronic resource?
|
106
|
+
# https://www.loc.gov/marc/bibliographic/bd008c.html
|
107
|
+
# @param record [MARC::Record]
|
108
|
+
# @return [Boolean]
|
109
|
+
def online_computer_file_form?(record)
|
110
|
+
return false unless field_defined?(record, '008')
|
111
|
+
|
112
|
+
record.fields('008').first.value[23] == 'o'
|
113
|
+
end
|
114
|
+
|
115
|
+
# Does the record have an 338 indicating an electronic resource?
|
116
|
+
# @see https://www.loc.gov/marc/bibliographic/bd338.html, https://www.loc.gov/standards/valuelist/rdacarrier.html
|
117
|
+
# @param record [MARC::Record]
|
118
|
+
# @return [Boolean]
|
119
|
+
def online_carrier_type?(record)
|
120
|
+
return false unless field_defined?(record, '338')
|
121
|
+
|
122
|
+
return false unless subfield_values_for(tag: '338', subfield: 'a', record: record).include?('online resource')
|
123
|
+
|
124
|
+
subfield_values_for(tag: '338', subfield: 'b', record: record).include?('cr')
|
125
|
+
end
|
126
|
+
|
127
|
+
# Databases are always electronic resources
|
128
|
+
# @param record [MARC::Record]
|
129
|
+
# @return [Boolean]
|
130
|
+
def electronic_database?(record)
|
131
|
+
Database.type_facet(record).any?
|
132
|
+
end
|
133
|
+
|
61
134
|
# Check if a field contains valid resource
|
62
135
|
# @param field [MARC::Field]
|
63
136
|
# @return [Boolean]
|
@@ -90,9 +90,10 @@ module PennMARC
|
|
90
90
|
# @return [Array<String>] array of author/creator values for display
|
91
91
|
def extended_show(record, relator_map: Mappers.relator)
|
92
92
|
fields = record.fields(%w[100 700])
|
93
|
+
fields += record.fields('880').select { |field| subfield_value?(field, '6', /^(#{TAGS.join('|')})/) }
|
93
94
|
fields.filter_map { |field|
|
94
|
-
# for 700 entries, only include ones with relator code ('4') = aut, or code 'e' = 'author'
|
95
|
-
next if field.tag
|
95
|
+
# for 700 and 880 entries, only include ones with relator code ('4') = aut, or code 'e' = 'author'
|
96
|
+
next if field.tag.in?(%w[700 880]) && !describes_author?(field)
|
96
97
|
|
97
98
|
parse_show_value(field, relator_map: relator_map)
|
98
99
|
}.uniq
|
@@ -106,7 +107,7 @@ module PennMARC
|
|
106
107
|
def extended_show_facet_map(record, relator_map: Mappers.relator)
|
107
108
|
creators = record.fields(%w[100 700]).filter_map do |field|
|
108
109
|
# for 700 entries, only include ones with relator code ('4') = aut, or code 'e' = 'author'
|
109
|
-
next if field.tag == '700' && !(field
|
110
|
+
next if field.tag == '700' && !describes_author?(field)
|
110
111
|
|
111
112
|
show = parse_show_value(field, relator_map: relator_map)
|
112
113
|
facet = parse_facet_value(field, FACET_SOURCE_MAP[field.tag.to_i].chars)
|
@@ -465,6 +466,13 @@ module PennMARC
|
|
465
466
|
|
466
467
|
append_relator(field: field, joined_subfields: conf, relator_term_sf: 'j', relator_map: relator_map)
|
467
468
|
end
|
469
|
+
|
470
|
+
# Does the given field describe an author record, as indicated by the relator fields of sf 4 or sf e ?
|
471
|
+
# @param [MARC::Field] field
|
472
|
+
# @return [Boolean]
|
473
|
+
def describes_author?(field)
|
474
|
+
field['4']&.downcase == 'aut' || field['e']&.downcase&.start_with?('author')
|
475
|
+
end
|
468
476
|
end
|
469
477
|
end
|
470
478
|
end
|
@@ -66,10 +66,6 @@ carpco:
|
|
66
66
|
library: Special Collections
|
67
67
|
display: Carpenters' Company of the City and County of Philadelphia
|
68
68
|
aeon: true
|
69
|
-
catoffice:
|
70
|
-
specific_location: Athenaeum of Philadelphia - Cataloging Office
|
71
|
-
library: Athenaeum of Philadelphia
|
72
|
-
display: Athenaeum of Philadelphia - Cataloging Office
|
73
69
|
circcoll:
|
74
70
|
specific_location: Athenaeum of Philadelphia - Circulating Collection
|
75
71
|
library: Athenaeum of Philadelphia
|
@@ -83,10 +79,6 @@ cidirbusrm:
|
|
83
79
|
library: Athenaeum of Philadelphia
|
84
80
|
display: Athenaeum of Philadelphia - City Directories Busch Room
|
85
81
|
aeon: true
|
86
|
-
collcare:
|
87
|
-
specific_location: Athenaeum of Philadelphia - Collections Care Manager
|
88
|
-
library: Athenaeum of Philadelphia
|
89
|
-
display: Athenaeum of Philadelphia - Collections Care Manager
|
90
82
|
fic:
|
91
83
|
specific_location: Athenaeum of Philadelphia - Fiction
|
92
84
|
library: Athenaeum of Philadelphia
|
@@ -128,11 +120,6 @@ rarecoll:
|
|
128
120
|
library: Athenaeum of Philadelphia
|
129
121
|
display: Athenaeum of Philadelphia - Rare Books Collection
|
130
122
|
aeon: true
|
131
|
-
reevecoll:
|
132
|
-
specific_location: Athenaeum of Philadelphia - Reeve Collection
|
133
|
-
library: Athenaeum of Philadelphia
|
134
|
-
display: Athenaeum of Philadelphia - Reeve Collection
|
135
|
-
aeon: true
|
136
123
|
ref:
|
137
124
|
specific_location: Athenaeum of Philadelphia - Reference
|
138
125
|
library: Athenaeum of Philadelphia
|
@@ -293,13 +280,6 @@ cjsarcths:
|
|
293
280
|
- Library at the Katz Center for Advanced Judaic Studies
|
294
281
|
display: Library at the Katz Center - Archives Thesis
|
295
282
|
aeon: true
|
296
|
-
cjsartif:
|
297
|
-
specific_location: Library at the Katz Center - Reading Room
|
298
|
-
library:
|
299
|
-
- Special Collections
|
300
|
-
- Library at the Katz Center for Advanced Judaic Studies
|
301
|
-
display: Library at the Katz Center - Artifacts
|
302
|
-
aeon: true
|
303
283
|
cjsbox1:
|
304
284
|
specific_location: Library at the Katz Center - Stacks
|
305
285
|
library: Library at the Katz Center for Advanced Judaic Studies
|
@@ -312,22 +292,10 @@ cjsbox3:
|
|
312
292
|
specific_location: Library at the Katz Center - Stacks
|
313
293
|
library: Library at the Katz Center for Advanced Judaic Studies
|
314
294
|
display: Library at the Katz Center - Stacks Box 3
|
315
|
-
cjsbox4:
|
316
|
-
specific_location: Library at the Katz Center - Stacks
|
317
|
-
library: Library at the Katz Center for Advanced Judaic Studies
|
318
|
-
display: Library at the Katz Center - Stacks Box 4
|
319
295
|
cjscdrom:
|
320
296
|
specific_location: Library at the Katz Center - Reading Room
|
321
297
|
library: Library at the Katz Center for Advanced Judaic Studies
|
322
298
|
display: Library at the Katz Center - CD-ROM
|
323
|
-
cjscirc:
|
324
|
-
specific_location: Library at the Katz Center - Reading Room
|
325
|
-
library: Library at the Katz Center for Advanced Judaic Studies
|
326
|
-
display: Library at the Katz Center - Circulation
|
327
|
-
cjscomp:
|
328
|
-
specific_location: Library at the Katz Center - Reading Room
|
329
|
-
library: Library at the Katz Center for Advanced Judaic Studies
|
330
|
-
display: Library at the Katz Center - Computer Room
|
331
299
|
cjsdir:
|
332
300
|
specific_location: Library at the Katz Center - Stacks
|
333
301
|
library: Library at the Katz Center for Advanced Judaic Studies
|
@@ -438,10 +406,6 @@ cjspergal:
|
|
438
406
|
specific_location: Library at the Katz Center - Reading Room
|
439
407
|
library: Library at the Katz Center for Advanced Judaic Studies
|
440
408
|
display: Library at the Katz Center - Periodicals Gallery
|
441
|
-
cjsperover:
|
442
|
-
specific_location: Library at the Katz Center - Stacks
|
443
|
-
library: Library at the Katz Center for Advanced Judaic Studies
|
444
|
-
display: Library at the Katz Center - Periodicals Oversize
|
445
409
|
cjsrar:
|
446
410
|
specific_location: Library at the Katz Center - Rare Book Room
|
447
411
|
library:
|
@@ -531,12 +495,6 @@ cjsreffol+:
|
|
531
495
|
specific_location: Library at the Katz Center - Reading Room
|
532
496
|
library: Library at the Katz Center for Advanced Judaic Studies
|
533
497
|
display: Library at the Katz Center - Reference Oversize
|
534
|
-
cjsres:
|
535
|
-
specific_location: Library at the Katz Center - Reading Room
|
536
|
-
library:
|
537
|
-
- Library at the Katz Center for Advanced Judaic Studies
|
538
|
-
- Reserve
|
539
|
-
display: Library at the Katz Center - Reserves
|
540
498
|
cjsspec:
|
541
499
|
specific_location: Library at the Katz Center - Stacks
|
542
500
|
library:
|
@@ -842,12 +800,7 @@ mideast:
|
|
842
800
|
specific_location: Van Pelt - Stapleton Seminar Room
|
843
801
|
library: Van Pelt-Dietrich Library Center
|
844
802
|
display: Van Pelt - Stapleton Seminar Room (523)
|
845
|
-
|
846
|
-
specific_location: Van Pelt - Middle East Seminar Reserve
|
847
|
-
library:
|
848
|
-
- Van Pelt-Dietrich Library Center
|
849
|
-
- Reserve
|
850
|
-
display: Van Pelt - Middle East Seminar Reserve
|
803
|
+
|
851
804
|
mscirc:
|
852
805
|
specific_location: Penn Museum Library - Circulation
|
853
806
|
library: Penn Museum Library
|
@@ -1073,12 +1026,6 @@ sasiarefe:
|
|
1073
1026
|
specific_location: Van Pelt - Govindaraju/Chandrasekhara South Asia Studies Seminar Room
|
1074
1027
|
library: Van Pelt-Dietrich Library Center
|
1075
1028
|
display: Van Pelt - Govindaraju/Chandrasekhara South Asia Studies Seminar Room (551)
|
1076
|
-
sasiarese:
|
1077
|
-
specific_location: Van Pelt - South Asian Reserve
|
1078
|
-
library:
|
1079
|
-
- Van Pelt-Dietrich Library Center
|
1080
|
-
- Reserve
|
1081
|
-
display: Van Pelt - South Asia Reserve (551)
|
1082
1029
|
scg123:
|
1083
1030
|
specific_location: Kislak Center for Special Collections - Rare Book Collection
|
1084
1031
|
library:
|
@@ -1479,10 +1426,6 @@ stor:
|
|
1479
1426
|
specific_location: LIBRA
|
1480
1427
|
library: LIBRA
|
1481
1428
|
display: LIBRA
|
1482
|
-
storcirc:
|
1483
|
-
specific_location: LIBRA - Circulation
|
1484
|
-
library: LIBRA
|
1485
|
-
display: LIBRA - Circulation
|
1486
1429
|
storcrstxt:
|
1487
1430
|
specific_location: GIC Collection at Penn Libraries
|
1488
1431
|
library:
|
@@ -1526,13 +1469,6 @@ scrunning:
|
|
1526
1469
|
- LIBRA
|
1527
1470
|
display: LIBRA Running Press Collection
|
1528
1471
|
aeon: true
|
1529
|
-
storvilain:
|
1530
|
-
specific_location: LIBRA Vilain-Wieck Collection
|
1531
|
-
library:
|
1532
|
-
- Special Collections
|
1533
|
-
- LIBRA
|
1534
|
-
display: LIBRA Vilain-Wieck Collection
|
1535
|
-
aeon: true
|
1536
1472
|
univarch:
|
1537
1473
|
specific_location: University Archives
|
1538
1474
|
library: University Archives
|
@@ -1649,7 +1585,7 @@ vetewellrm:
|
|
1649
1585
|
- Veterinary
|
1650
1586
|
- 'Veterinary: Atwood Library (Campus)'
|
1651
1587
|
display: 'Veterinary: Atwood Library (Campus)- Wellness Room'
|
1652
|
-
|
1588
|
+
vpexhibits:
|
1653
1589
|
specific location: Van Pelt - Exhibits and Events
|
1654
1590
|
library: Van Pelt-Dietrich Library Center
|
1655
1591
|
display: Van Pelt - Exhibits and Events -- First Floor, Circulation Desk
|
data/lib/pennmarc/version.rb
CHANGED
@@ -105,5 +105,64 @@ describe 'PennMARC::Access' do
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
end
|
108
|
+
|
109
|
+
context 'with an electronic record but no electronic inventory provided' do
|
110
|
+
let(:record) { marc_record fields: fields }
|
111
|
+
|
112
|
+
context 'with physical inventory' do
|
113
|
+
let(:fields) do
|
114
|
+
[marc_field(tag: PennMARC::Enriched::Pub::PHYS_INVENTORY_TAG),
|
115
|
+
marc_field(tag: '944', subfields: { a: 'Database & Article Index',
|
116
|
+
b: 'Dictionaries and Thesauri (language based)' })]
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'adds in additional Online access value' do
|
120
|
+
expect(helper.facet(record)).to contain_exactly PennMARC::Access::AT_THE_LIBRARY, PennMARC::Access::ONLINE
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'with a 944 indicating an online database' do
|
125
|
+
let(:fields) do
|
126
|
+
[marc_field(tag: '944', subfields: { a: 'Database & Article Index',
|
127
|
+
b: 'Dictionaries and Thesauri (language based)' })]
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'returns expected Online access value' do
|
131
|
+
expect(helper.facet(record)).to contain_exactly(PennMARC::Access::ONLINE)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'with a single MARC indicator check suggesting an online database' do
|
136
|
+
let(:fields) do
|
137
|
+
[marc_control_field(tag: '006', value: ' o ')]
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'does not return Online access value' do
|
141
|
+
expect(helper.facet(record)).not_to include PennMARC::Access::ONLINE
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'with two MARC indicators suggesting an online database' do
|
146
|
+
let(:fields) do
|
147
|
+
[marc_control_field(tag: '006', value: ' o '),
|
148
|
+
marc_control_field(tag: '007', value: 'cr')]
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'returns expected Online access value' do
|
152
|
+
expect(helper.facet(record)).to contain_exactly(PennMARC::Access::ONLINE)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'with other two MARC indicators suggesting an online database' do
|
157
|
+
let(:fields) do
|
158
|
+
[marc_control_field(tag: '008', value: '970325c19959999nyuwr d o 0 2eng '),
|
159
|
+
marc_field(tag: '338', subfields: { a: 'online resource', b: 'cr' })]
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'returns expected Online access value' do
|
163
|
+
expect(helper.facet(record)).to contain_exactly(PennMARC::Access::ONLINE)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
108
167
|
end
|
109
168
|
end
|
@@ -100,12 +100,12 @@ describe 'PennMARC::Creator' do
|
|
100
100
|
let(:fields) do
|
101
101
|
[marc_field(tag: '100', subfields: { a: 'Surname, Name', '0': 'http://cool.uri/12345', d: '1900-2000',
|
102
102
|
e: 'author.', '4': 'http://cool.uri/vocabulary/relators/aut' }),
|
103
|
-
marc_field(tag: '880', subfields: { a: 'Surname, Alternative', '6': '100' })]
|
103
|
+
marc_field(tag: '880', subfields: { a: 'Surname, Alternative', e: 'author', '6': '100' })]
|
104
104
|
end
|
105
105
|
|
106
|
-
it 'returns single author values with no URIs anywhere (the same as show)' do
|
106
|
+
it 'returns single author values and linked alternate with no URIs anywhere (the same as show)' do
|
107
107
|
values = helper.extended_show(record)
|
108
|
-
expect(values).to contain_exactly 'Surname, Name 1900-2000, author.'
|
108
|
+
expect(values).to contain_exactly 'Surname, Name 1900-2000, author.', 'Surname, Alternative, author.'
|
109
109
|
expect(values.join.downcase).not_to include 'http'
|
110
110
|
end
|
111
111
|
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.3.
|
4
|
+
version: 1.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Kanning
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2025-
|
15
|
+
date: 2025-10-02 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activesupport
|