pennmarc 1.0.24 → 1.0.25

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59881d630f244bc6d8b76665df84f4b22297de2d51c44f5272df4226f4e27e75
4
- data.tar.gz: 8d4e78c359dea40f482adc5b4deaa3fbb75bbe15a4fce5955ad48de054ce82c4
3
+ metadata.gz: 8b540ecd84333f097b50a3682732229854b188fcde76921eb0ec184622a690dd
4
+ data.tar.gz: 9203fadee45b9ad65ec20880a1acbc23356000b748d32d07428ec093590cd55a
5
5
  SHA512:
6
- metadata.gz: 4a3a43ff1cecadf978a8c50d59b382c2592925116cacd757f368ea0a698e9b370a94e74fd98e1a6a06a3b837ab0dbdce2efece991aaf3da4b53c74396a73ee2e
7
- data.tar.gz: 7f5468f9891c9fe15003160fb4d5a6c04cd8291ead5e803f0652368376e1fd67381195a7bdffd7ea9a7aa996c071b75240405dd956c46d879753f6811eca1b0a
6
+ metadata.gz: 6770815e8f5f828c15451fc71c04dbef6a131203e8c58d721c063b15f218d5814a71b37fd6c4f088a9c7164d5d989ff6933abc820094068921f218c937a87410
7
+ data.tar.gz: 94eee63c29ae06151816a532a5afb7db1f27490de798651c909dc07fd0f33de1b4a1ee26057b6e3a8abc5d15c54d09709df8942e6e21ad828c1296fe3191725e
@@ -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) && finding_aid_linkage?(record)
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 for an online finding aid, meeting these criteria:
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 finding_aid_linkage?(record)
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.include?('Finding aid') && value.include?('hdl.library.upenn.edu')
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
- SEARCH_SOURCE_INDICATORS = %w[0 1 2 4 7].freeze
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 {SEARCH_SOURCE_INDICATORS}.
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) && SEARCH_SOURCE_INDICATORS.include?(field.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
- class << self
7
- # We use these fields when retrieving auxiliary titles in the *search_aux methods:
8
- # {https://www.loc.gov/marc/bibliographic/bd130.html 130},
9
- # {https://www.loc.gov/marc/bibliographic/bd210.html 210},
10
- # {https://www.loc.gov/marc/bibliographic/bd245.html 245},
11
- # {https://www.loc.gov/marc/bibliographic/bd246.html 246},
12
- # {https://www.loc.gov/marc/bibliographic/bd247.html 247},
13
- # {https://www.loc.gov/marc/bibliographic/bd440.html 440},
14
- # {https://www.loc.gov/marc/bibliographic/bd490.html 490},
15
- # {https://www.loc.gov/marc/bibliographic/bd730.html 730},
16
- # {https://www.loc.gov/marc/bibliographic/bd740.html 740},
17
- # {https://www.loc.gov/marc/bibliographic/bd830.html 830},
18
- # {https://www.loc.gov/marc/bibliographic/bd773.html 773},
19
- # {https://www.loc.gov/marc/bibliographic/bd774.html 774},
20
- # {https://www.loc.gov/marc/bibliographic/bd780.html 780},
21
- # {https://www.loc.gov/marc/bibliographic/bd785.html 785},
22
- # {https://www.loc.gov/marc/bibliographic/bd700.html 700},
23
- # {https://www.loc.gov/marc/bibliographic/bd710.html 710},
24
- # {https://www.loc.gov/marc/bibliographic/bd711.html 711},
25
- # {https://www.loc.gov/marc/bibliographic/bd505.html 505}
26
- AUX_TITLE_TAGS = {
27
- main: %w[130 210 240 245 246 247 440 490 730 740 830],
28
- related: %w[773 774 780 785],
29
- entity: %w[700 710 711],
30
- note: %w[505]
31
- }.freeze
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PennMARC
4
- VERSION = '1.0.24'
4
+ VERSION = '1.0.25'
5
5
  end
@@ -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.24
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-18 00:00:00.000000000 Z
13
+ date: 2024-06-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport