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 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