pennmarc 1.0.24 → 1.0.25
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pennmarc/enriched.rb +1 -0
- data/lib/pennmarc/helpers/access.rb +8 -6
- data/lib/pennmarc/helpers/identifier.rb +12 -0
- data/lib/pennmarc/helpers/subject.rb +10 -4
- data/lib/pennmarc/helpers/title.rb +39 -26
- data/lib/pennmarc/version.rb +1 -1
- data/spec/lib/pennmarc/helpers/access_spec.rb +11 -0
- data/spec/lib/pennmarc/helpers/identifer_spec.rb +14 -0
- data/spec/lib/pennmarc/helpers/subject_spec.rb +16 -0
- data/spec/lib/pennmarc/helpers/title_spec.rb +20 -0
- 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: 8b540ecd84333f097b50a3682732229854b188fcde76921eb0ec184622a690dd
|
4
|
+
data.tar.gz: 9203fadee45b9ad65ec20880a1acbc23356000b748d32d07428ec093590cd55a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6770815e8f5f828c15451fc71c04dbef6a131203e8c58d721c063b15f218d5814a71b37fd6c4f088a9c7164d5d989ff6933abc820094068921f218c937a87410
|
7
|
+
data.tar.gz: 94eee63c29ae06151816a532a5afb7db1f27490de798651c909dc07fd0f33de1b4a1ee26057b6e3a8abc5d15c54d09709df8942e6e21ad828c1296fe3191725e
|
data/lib/pennmarc/enriched.rb
CHANGED
@@ -12,6 +12,7 @@ module PennMARC
|
|
12
12
|
PHYS_INVENTORY_TAG = 'hld'
|
13
13
|
ELEC_INVENTORY_TAG = 'prt'
|
14
14
|
ITEM_TAG = 'itm'
|
15
|
+
RELATED_RECORD_TAG = 'rel'
|
15
16
|
|
16
17
|
# Subfields for HLD tags
|
17
18
|
# Follow MARC 852 spec: https://www.loc.gov/marc/holdings/hd852.html, but names are translated into Alma parlance
|
@@ -5,14 +5,13 @@ module PennMARC
|
|
5
5
|
class Access < Helper
|
6
6
|
ONLINE = 'Online'
|
7
7
|
AT_THE_LIBRARY = 'At the library'
|
8
|
+
RESOURCE_LINK_BASE_URL = 'hdl.library.upenn.edu'
|
8
9
|
|
9
10
|
class << self
|
10
11
|
# Based on enhanced metadata fields added by Alma publishing process or API, determine if the record has
|
11
12
|
# electronic access or has physical holdings, and is therefore "Online" or "At the library". If a record is "At
|
12
13
|
# the library", but has a link to a finding aid in the 856 field (matching certain criteria), also add 'Online' as
|
13
14
|
# an access method.
|
14
|
-
# @todo What if none of these criteria match? Should we include "At the library" by default? Records with no value
|
15
|
-
# in this field would be lost if the user selects a facet value.
|
16
15
|
# @param [MARC::Record] record
|
17
16
|
# @return [Array]
|
18
17
|
def facet(record)
|
@@ -24,7 +23,7 @@ module PennMARC
|
|
24
23
|
return values if values.size == 2 # return early if all values are already present
|
25
24
|
|
26
25
|
# only check if ONLINE isn't already there
|
27
|
-
values << ONLINE if values.exclude?(ONLINE) &&
|
26
|
+
values << ONLINE if values.exclude?(ONLINE) && resource_link?(record)
|
28
27
|
values.uniq
|
29
28
|
end
|
30
29
|
|
@@ -44,20 +43,23 @@ module PennMARC
|
|
44
43
|
field.tag.in? [Enriched::Pub::PHYS_INVENTORY_TAG, Enriched::Api::PHYS_INVENTORY_TAG]
|
45
44
|
end
|
46
45
|
|
47
|
-
# Check if a record contains an 856 entry
|
46
|
+
# Check if a record contains an 856 entry with a Penn Handle server link meeting these criteria:
|
48
47
|
# 1. Indicator 1 is 4 (HTTP resource)
|
49
48
|
# 2. Indicator 2 is NOT 2 (indicating the linkage is to a "related" thing)
|
50
49
|
# 3. The URL specified in subfield u (URI) is a Penn Handle link
|
50
|
+
# 4. The subfield z does NOT include the string 'Finding aid'
|
51
51
|
# See: https://www.loc.gov/marc/bibliographic/bd856.html
|
52
|
+
# @note Some electronic records do not have Portfolios in Alma, so we rely upon the Resource Link in the 856 to
|
53
|
+
# get these records included in the Online category.
|
52
54
|
# @param [MARC::Record] record
|
53
55
|
# @return [Boolean]
|
54
|
-
def
|
56
|
+
def resource_link?(record)
|
55
57
|
record.fields('856').filter_map do |field|
|
56
58
|
next if field.indicator2 == '2' || field.indicator1 != '4'
|
57
59
|
|
58
60
|
subz = subfield_values(field, 'z')
|
59
61
|
subfield_values(field, 'u').filter_map do |value|
|
60
|
-
return true if subz.
|
62
|
+
return true if subz.exclude?('Finding aid') && value.include?(RESOURCE_LINK_BASE_URL)
|
61
63
|
end
|
62
64
|
end
|
63
65
|
false
|
@@ -159,6 +159,18 @@ module PennMARC
|
|
159
159
|
}.uniq
|
160
160
|
end
|
161
161
|
|
162
|
+
# Gets any Host record MMS ID values from an Enriched::Pub::RELATED_RECORD_TAG field added during Alma enrichment.
|
163
|
+
# This aids in our handling of "bound with" records.
|
164
|
+
# @param [MARC::Record] record
|
165
|
+
# @return [Array<String>]
|
166
|
+
def host_record_id(record)
|
167
|
+
record.fields(Enriched::Pub::RELATED_RECORD_TAG).filter_map { |field|
|
168
|
+
next unless subfield_value?(field, 'c', /contains/i)
|
169
|
+
|
170
|
+
subfield_values field, :w
|
171
|
+
}.flatten.uniq
|
172
|
+
end
|
173
|
+
|
162
174
|
private
|
163
175
|
|
164
176
|
# Determine if subfield 'a' is an OCLC id.
|
@@ -18,7 +18,7 @@ module PennMARC
|
|
18
18
|
# - 2: MeSH
|
19
19
|
# - 4: Source not specified (local?)
|
20
20
|
# - 7: Source specified in ǂ2
|
21
|
-
|
21
|
+
VALID_SOURCE_INDICATORS = %w[0 1 2 4 7].freeze
|
22
22
|
|
23
23
|
# Tags that serve as sources for Subject facet values
|
24
24
|
DISPLAY_TAGS = %w[600 610 611 630 650 651].freeze
|
@@ -27,7 +27,7 @@ module PennMARC
|
|
27
27
|
LOCAL_TAGS = %w[690 691 697].freeze
|
28
28
|
|
29
29
|
# All Subjects for searching. This includes most subfield content from any field contained in {SEARCH_TAGS} or
|
30
|
-
# 69X, including any linked 880 fields. Fields must have an indicator2 value in {
|
30
|
+
# 69X, including any linked 880 fields. Fields must have an indicator2 value in {VALID_SOURCE_INDICATORS}.
|
31
31
|
# @todo this includes subfields that may not be desired like 1 (uri) and 2 (source code) but this might be OK for
|
32
32
|
# a search (non-display) field?
|
33
33
|
# @param [Hash] relator_map
|
@@ -179,12 +179,18 @@ module PennMARC
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
|
182
|
-
# Is a field intended for display in a general subject field
|
182
|
+
# Is a field intended for display in a general subject field? To be included, the field tag is in either
|
183
|
+
# {DISPLAY_TAGS} or {LOCAL_TAGS}, and has an indicator 2 value that is in {VALID_SOURCE_INDICATORS}. If
|
184
|
+
# indicator 2 is '7' - indicating "source specified", the specified source must be in our approved source code
|
185
|
+
# list.
|
186
|
+
# @see Util.valid_subject_genre_source_code?
|
183
187
|
# @param [MARC::DataField] field
|
184
188
|
# @return [Boolean] whether a MARC field is intended for display under general "Subjects"
|
185
189
|
def subject_general_display_field?(field)
|
186
190
|
return false unless field.tag.in?(DISPLAY_TAGS + LOCAL_TAGS) && field.respond_to?(:indicator2)
|
187
191
|
|
192
|
+
return false if field.indicator2.present? && !field.indicator2.in?(VALID_SOURCE_INDICATORS)
|
193
|
+
|
188
194
|
return false if field.indicator2 == '7' && !valid_subject_genre_source_code?(field)
|
189
195
|
|
190
196
|
true
|
@@ -278,7 +284,7 @@ module PennMARC
|
|
278
284
|
# @param [MARC::DataField] field
|
279
285
|
# @return [Boolean]
|
280
286
|
def subject_search_field?(field)
|
281
|
-
return false unless field.respond_to?(:indicator2) &&
|
287
|
+
return false unless field.respond_to?(:indicator2) && VALID_SOURCE_INDICATORS.include?(field.indicator2)
|
282
288
|
|
283
289
|
tag = if field.tag == '880'
|
284
290
|
subfield_values(field, '6').first
|
@@ -3,33 +3,36 @@
|
|
3
3
|
module PennMARC
|
4
4
|
# This helper contains logic for parsing out Title and Title-related fields.
|
5
5
|
class Title < Helper
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
6
|
+
# We use these fields when retrieving auxiliary titles in the *search_aux methods:
|
7
|
+
# {https://www.loc.gov/marc/bibliographic/bd130.html 130},
|
8
|
+
# {https://www.loc.gov/marc/bibliographic/bd210.html 210},
|
9
|
+
# {https://www.loc.gov/marc/bibliographic/bd245.html 245},
|
10
|
+
# {https://www.loc.gov/marc/bibliographic/bd246.html 246},
|
11
|
+
# {https://www.loc.gov/marc/bibliographic/bd247.html 247},
|
12
|
+
# {https://www.loc.gov/marc/bibliographic/bd440.html 440},
|
13
|
+
# {https://www.loc.gov/marc/bibliographic/bd490.html 490},
|
14
|
+
# {https://www.loc.gov/marc/bibliographic/bd730.html 730},
|
15
|
+
# {https://www.loc.gov/marc/bibliographic/bd740.html 740},
|
16
|
+
# {https://www.loc.gov/marc/bibliographic/bd830.html 830},
|
17
|
+
# {https://www.loc.gov/marc/bibliographic/bd773.html 773},
|
18
|
+
# {https://www.loc.gov/marc/bibliographic/bd774.html 774},
|
19
|
+
# {https://www.loc.gov/marc/bibliographic/bd780.html 780},
|
20
|
+
# {https://www.loc.gov/marc/bibliographic/bd785.html 785},
|
21
|
+
# {https://www.loc.gov/marc/bibliographic/bd700.html 700},
|
22
|
+
# {https://www.loc.gov/marc/bibliographic/bd710.html 710},
|
23
|
+
# {https://www.loc.gov/marc/bibliographic/bd711.html 711},
|
24
|
+
# {https://www.loc.gov/marc/bibliographic/bd505.html 505}
|
25
|
+
AUX_TITLE_TAGS = {
|
26
|
+
main: %w[130 210 240 245 246 247 440 490 730 740 830],
|
27
|
+
related: %w[773 774 780 785],
|
28
|
+
entity: %w[700 710 711],
|
29
|
+
note: %w[505]
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
# This text is used in Alma to indicate a Bib record is a "Host" record for other bibs (bound-withs)
|
33
|
+
HOST_BIB_TITLE = 'Host bibliographic record for boundwith'
|
32
34
|
|
35
|
+
class << self
|
33
36
|
# Main Title Search field. Takes from {https://www.loc.gov/marc/bibliographic/bd245.html 245} and linked 880.
|
34
37
|
# @note Ported from get_title_1_search_values.
|
35
38
|
# @param [MARC::Record] record
|
@@ -217,6 +220,16 @@ module PennMARC
|
|
217
220
|
}.uniq
|
218
221
|
end
|
219
222
|
|
223
|
+
# Determine if the record is a "Host" bibliographic record for other bib records ("bound-withs")
|
224
|
+
# @param [MARC::Record] record
|
225
|
+
# @return [Boolean]
|
226
|
+
def host_bib_record?(record)
|
227
|
+
record.fields('245').any? do |f|
|
228
|
+
title = join_subfields(f, &subfield_in?(%w[a]))
|
229
|
+
title.include?(HOST_BIB_TITLE)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
220
233
|
private
|
221
234
|
|
222
235
|
# Create prefix/filing hash for representing a title value with filing characters removed, with special
|
data/lib/pennmarc/version.rb
CHANGED
@@ -69,6 +69,17 @@ describe 'PennMARC::Access' do
|
|
69
69
|
{ z: 'Finding aid', u: 'http://hdl.library.upenn.edu/1017/d/pacscl/UPENN_RBML_MsColl200' }
|
70
70
|
end
|
71
71
|
|
72
|
+
it 'does not include online access' do
|
73
|
+
expect(helper.facet(record)).to contain_exactly(PennMARC::Access::AT_THE_LIBRARY)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with an 856 describing a resource link' do
|
78
|
+
let(:indicators) { { indicator1: '4', indicator2: '1' } }
|
79
|
+
let(:location_and_access_subfields) do
|
80
|
+
{ z: 'Connect to resource', u: 'http://hdl.library.upenn.edu/1234' }
|
81
|
+
end
|
82
|
+
|
72
83
|
it 'includes online access' do
|
73
84
|
expect(helper.facet(record)).to contain_exactly(PennMARC::Access::ONLINE, PennMARC::Access::AT_THE_LIBRARY)
|
74
85
|
end
|
@@ -161,4 +161,18 @@ describe 'PennMARC::Identifier' do
|
|
161
161
|
'10.1038/sdata.2016.18', '10.18574/9781479842865')
|
162
162
|
end
|
163
163
|
end
|
164
|
+
|
165
|
+
describe '.host_record_id' do
|
166
|
+
let(:record) do
|
167
|
+
marc_record fields: [
|
168
|
+
marc_field(tag: PennMARC::Enriched::Pub::RELATED_RECORD_TAG, subfields: { w: '123456789', c: 'Contains',
|
169
|
+
a: 'Title' }),
|
170
|
+
marc_field(tag: PennMARC::Enriched::Pub::RELATED_RECORD_TAG, subfields: { w: '666666666', c: 'Contained In' })
|
171
|
+
]
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'returns only the desired host record MMS ID values' do
|
175
|
+
expect(helper.host_record_id(record)).to contain_exactly '123456789'
|
176
|
+
end
|
177
|
+
end
|
164
178
|
end
|
@@ -288,6 +288,22 @@ describe 'PennMARC::Subject' do
|
|
288
288
|
'Early works to 1950.')
|
289
289
|
end
|
290
290
|
end
|
291
|
+
|
292
|
+
context 'with a mix of allowed and disallowed heading sources' do
|
293
|
+
let(:fields) do
|
294
|
+
[marc_field(tag: '650', indicator2: '7', subfields: {
|
295
|
+
'2': 'fast',
|
296
|
+
a: 'Philosophy in motion pictures.',
|
297
|
+
'0': 'http://id.loc.gov/authorities/subjects/sh92003501'
|
298
|
+
}),
|
299
|
+
marc_field(tag: '650', indicator2: '7', subfields: { '2': 'gnd', a: 'Filmästhetik.' }),
|
300
|
+
marc_field(tag: '650', indicator2: '6', subfields: { a: 'Cinéma et arts.' })]
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'includes only permitted headings from approved ontologies' do
|
304
|
+
expect(values).to contain_exactly 'Philosophy in motion pictures.'
|
305
|
+
end
|
306
|
+
end
|
291
307
|
end
|
292
308
|
|
293
309
|
describe '.childrens_show' do
|
@@ -249,4 +249,24 @@ describe 'PennMARC::Title' do
|
|
249
249
|
expect(values).not_to include 'Linkage', '247'
|
250
250
|
end
|
251
251
|
end
|
252
|
+
|
253
|
+
describe '.host_bib_record?' do
|
254
|
+
let(:record) { marc_record fields: [marc_field(tag: '245', subfields: subfields)] }
|
255
|
+
|
256
|
+
context 'with a host record' do
|
257
|
+
let(:subfields) { { a: "#{PennMARC::Title::HOST_BIB_TITLE} for 123456789" } }
|
258
|
+
|
259
|
+
it 'returns true' do
|
260
|
+
expect(helper.host_bib_record?(record)).to be true
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'with a non-host record' do
|
265
|
+
let(:subfields) { { a: 'Regular record' } }
|
266
|
+
|
267
|
+
it 'returns false' do
|
268
|
+
expect(helper.host_bib_record?(record)).to be false
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
252
272
|
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.25
|
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-06-
|
13
|
+
date: 2024-06-26 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|