pennmarc 1.0.22 → 1.0.24

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: d9222d0bfd9ca8704ec91ef01d1e27ce90711506b648f2d0006fc2270dd6d82d
4
- data.tar.gz: c250833003d00f8d2b12a6c8e4043d9eadcdaaa33bba8ae70468e3210cdb1780
3
+ metadata.gz: 59881d630f244bc6d8b76665df84f4b22297de2d51c44f5272df4226f4e27e75
4
+ data.tar.gz: 8d4e78c359dea40f482adc5b4deaa3fbb75bbe15a4fce5955ad48de054ce82c4
5
5
  SHA512:
6
- metadata.gz: b9a1c42746b7d1448df78aad4528c1bf20731feeadc073e4937d0722bcfbed6ec42c104ae2d1241cf31830e6c7e50b0b6ab125140cf9d232511530a7b82861ef
7
- data.tar.gz: c143ab4e9056f6a62a06a90d01938d70a6b7088704930e0dcf402c392954c08164a9821f39f35d03d07023393ca1d64844fa56d16522155ec55ca4a9a35fcf9b
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. Appends any encoded
55
- # relationships found in $4. If there are no valid encoded relationships, uses the value found in $e.
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
- creator = join_subfields(field, &subfield_not_in?(%w[0 1 4 6 8 e w]))
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
- source_map = {
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
- trim_punctuation(join_subfields(field, &subfield_in?(subfields.chars)))
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
- conf = if subfield_undefined? field, 'i'
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 [DateTime, nil] The publication date, or nil if date found in record is invalid
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
- DateTime.new(four_digit_year.to_i)
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 [DateTime, nil] The date added, or nil if date found in record is invalid
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
- DateTime.strptime(date_added, format)
37
+ Time.strptime(date_added, format)
38
38
  rescue StandardError => e
39
- puts "Error parsing date in date added subfield: #{date_added} - #{e}"
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 [DateTime, nil] The date last updated, or nil if date found in record is invalid
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
- DateTime.iso8601(date_time_string).to_datetime
60
- rescue ArgumentError => e
61
- puts "Error parsing last updated date: #{date_time_string} - #{e}"
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:
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PennMARC
4
- VERSION = '1.0.22'
4
+ VERSION = '1.0.24'
5
5
  end
@@ -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(DateTime.new(2010))
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 DateTime.strptime('2023-10-19', '%Y-%m-%d')
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(DateTime.strptime('2023-06-28', '%Y-%m-%d'))
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(DateTime.strptime('2023-06-29 11:04:30:10', '%Y-%m-%d %H:%M:%S'))
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(DateTime.strptime('2023-06-29', '%Y-%m-%d'))
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) { [marc_field(tag: 'itm', subfields: { q: 'invalid date' })] }
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("Error parsing date in date added subfield: invalid date - invalid date\n").to_stdout
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(DateTime.iso8601('20230213163851.1').to_datetime)
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) { [marc_field(tag: '005', subfields: { q: 'invalid date' })] }
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("Error parsing last updated date: invalid date - invalid date\n").to_stdout
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.22
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-05-24 00:00:00.000000000 Z
13
+ date: 2024-06-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport