pennmarc 1.0.33 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +5 -4
- data/lib/pennmarc/helpers/classification.rb +18 -0
- data/lib/pennmarc/helpers/location.rb +48 -24
- data/lib/pennmarc/helpers/note.rb +1 -1
- data/lib/pennmarc/helpers/title.rb +83 -20
- data/lib/pennmarc/mappings/location_overrides.yml +1 -0
- data/lib/pennmarc/version.rb +1 -1
- data/spec/lib/pennmarc/helpers/classification_spec.rb +82 -17
- data/spec/lib/pennmarc/helpers/location_spec.rb +95 -63
- data/spec/lib/pennmarc/helpers/note_spec.rb +1 -1
- data/spec/lib/pennmarc/helpers/title_spec.rb +60 -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: 9003d5a58efd2cbef83a220bd0d609edfdc2bfb883378c003d0bafa2d85e520e
|
4
|
+
data.tar.gz: d8f841dbba9e412848b31a7a11284b14e2bbb772fbb98762b827ab9e2baf6355
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a45d1e909a7a9efad1aec8047d79f3358b1ee3b523958661459c27b397f3a0f33c00deffeae2bdd30fad14156b8f348171639375677e6f600086e1b592fe2c51
|
7
|
+
data.tar.gz: ba609fef49f12f9341328fc292cc510fab6ab298174791afc99ec802ecd1c62448c9ccc009a7f01c6aefef7be2c56d794cc5f2e0bddf01c72fc4e9db11ce6961
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 10000`
|
3
|
-
# on 2024-
|
3
|
+
# on 2024-08-20 20:46:53 UTC using RuboCop version 1.51.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -14,7 +14,7 @@ Gemspec/RequireMFA:
|
|
14
14
|
Exclude:
|
15
15
|
- 'pennmarc.gemspec'
|
16
16
|
|
17
|
-
# Offense count:
|
17
|
+
# Offense count: 26
|
18
18
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
19
19
|
Metrics/AbcSize:
|
20
20
|
Exclude:
|
@@ -31,7 +31,7 @@ Metrics/AbcSize:
|
|
31
31
|
- 'lib/pennmarc/helpers/title.rb'
|
32
32
|
- 'lib/pennmarc/util.rb'
|
33
33
|
|
34
|
-
# Offense count:
|
34
|
+
# Offense count: 9
|
35
35
|
# Configuration parameters: CountComments, Max, CountAsOne.
|
36
36
|
Metrics/ClassLength:
|
37
37
|
Exclude:
|
@@ -138,9 +138,10 @@ RSpec/FilePath:
|
|
138
138
|
Exclude:
|
139
139
|
- 'spec/lib/pennmarc/parser_spec.rb'
|
140
140
|
|
141
|
-
# Offense count:
|
141
|
+
# Offense count: 26
|
142
142
|
# Configuration parameters: Max, AllowedGroups.
|
143
143
|
RSpec/NestedGroups:
|
144
144
|
Exclude:
|
145
145
|
- 'spec/lib/pennmarc/helpers/access_spec.rb'
|
146
146
|
- 'spec/lib/pennmarc/helpers/format_spec.rb'
|
147
|
+
- 'spec/lib/pennmarc/helpers/location_spec.rb'
|
@@ -42,6 +42,24 @@ module PennMARC
|
|
42
42
|
}.uniq
|
43
43
|
end
|
44
44
|
|
45
|
+
# Parse call number values from inventory fields, including both hld and itm fields from publishing enrichment.
|
46
|
+
# Return only unique values.
|
47
|
+
# @param record [MARC::Record]
|
48
|
+
# @return [Array<String>] array of call numbers from inventory fields
|
49
|
+
def call_number_search(record)
|
50
|
+
call_nums = record.fields(TAGS).filter_map do |field|
|
51
|
+
subfield_values(field, call_number_sf(field))
|
52
|
+
end
|
53
|
+
|
54
|
+
# Ensure we get call numbers for records with no `itm` tags by also checking `hld` and de-duping
|
55
|
+
call_nums += record.fields([Enriched::Pub::PHYS_INVENTORY_TAG]).filter_map do |field|
|
56
|
+
first = subfield_values(field, Enriched::Pub::HOLDING_CLASSIFICATION_PART)&.first
|
57
|
+
last = subfield_values(field, Enriched::Pub::HOLDING_ITEM_PART)&.first
|
58
|
+
"#{first} #{last}".squish.presence
|
59
|
+
end
|
60
|
+
call_nums.flatten.uniq
|
61
|
+
end
|
62
|
+
|
45
63
|
private
|
46
64
|
|
47
65
|
# Retrieve subfield code that stores the call number on enriched marc field
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module PennMARC
|
4
4
|
# Methods that return Library and Location values from Alma enhanced MARC fields
|
5
5
|
class Location < Helper
|
6
|
-
ONLINE_LIBRARY = 'Online library'
|
7
6
|
WEB_LOCATION_CODE = 'web'
|
8
7
|
|
9
8
|
class << self
|
@@ -38,14 +37,14 @@ module PennMARC
|
|
38
37
|
# @see https://developers.exlibrisgroup.com/alma/apis/docs/bibs/R0VUIC9hbG1hd3MvdjEvYmlicy97bW1zX2lkfQ==/
|
39
38
|
# Alma documentation for these added fields
|
40
39
|
# @param record [MARC::Record]
|
41
|
-
# @param display_value [Symbol
|
40
|
+
# @param display_value [Symbol,String] field in location hash to retrieve
|
42
41
|
# @param location_map [Hash] hash with location_code as key and location hash as value
|
43
42
|
# @return [Array<String>]
|
44
43
|
def location(record:, display_value:, location_map:)
|
45
44
|
# get enriched marc location tag and relevant subfields
|
46
|
-
enriched_location_tag_and_subfields(record) => {tag:, location_code_sf:, call_num_sf:}
|
45
|
+
enriched_location_tag_and_subfields(record) => {tag:, location_code_sf:, call_num_sf:, call_num_type_sf:}
|
47
46
|
|
48
|
-
|
47
|
+
record.fields(tag).flat_map { |field|
|
49
48
|
field.filter_map { |subfield|
|
50
49
|
# skip unless subfield matches enriched marc tag subfield code
|
51
50
|
next unless subfield.code == location_code_sf
|
@@ -54,28 +53,27 @@ module PennMARC
|
|
54
53
|
|
55
54
|
next if location_code_to_ignore?(location_map, location_code)
|
56
55
|
|
57
|
-
override =
|
58
|
-
|
56
|
+
override = if display_value.to_sym == :specific_location
|
57
|
+
specific_location_override(location_code: location_code, field: field,
|
58
|
+
call_num_sf: call_num_sf, call_num_type_sf: call_num_type_sf)
|
59
|
+
end
|
59
60
|
|
60
61
|
override || location_map[location_code.to_sym][display_value.to_sym]
|
61
62
|
}.flatten.compact_blank
|
62
63
|
}.uniq
|
63
|
-
if record.tags.intersect?([Enriched::Pub::ELEC_INVENTORY_TAG, Enriched::Api::ELEC_INVENTORY_TAG])
|
64
|
-
locations << ONLINE_LIBRARY
|
65
|
-
end
|
66
|
-
|
67
|
-
locations
|
68
64
|
end
|
69
65
|
|
70
66
|
private
|
71
67
|
|
72
68
|
# Determine enriched marc location tag, location code subfield, and call number subfield,
|
73
|
-
# giving priority to using 'itm', 'AVA', or '
|
69
|
+
# giving priority to using 'itm', 'AVA', or 'hld' fields.
|
74
70
|
# @param record [MARC::Record]
|
75
71
|
# @return [Hash<String, String>] containing location tag and subfield code
|
76
72
|
# - `:tag` (String): The enriched marc location tag
|
77
73
|
# - `:location_code_sf` (String): The subfield code where location code is stored
|
78
74
|
# - `:call_num_sf` (String): The subfield code where call number is stored
|
75
|
+
# - `:call_num_type_sf` (String, nil): The subfield code where call number type is stored. nil if unavailable in a
|
76
|
+
# MARC field and we need to look for an indicator.
|
79
77
|
def enriched_location_tag_and_subfields(record)
|
80
78
|
# in holdings records, the shelving location is always the permanent location.
|
81
79
|
# in item records, the current location takes into account
|
@@ -90,19 +88,22 @@ module PennMARC
|
|
90
88
|
tag = Enriched::Pub::ITEM_TAG
|
91
89
|
location_code_sf = Enriched::Pub::ITEM_CURRENT_LOCATION
|
92
90
|
call_num_sf = Enriched::Pub::ITEM_CALL_NUMBER
|
91
|
+
call_num_type_sf = Enriched::Pub::ITEM_CALL_NUMBER_TYPE
|
93
92
|
# if the record has API inventory tags, use them
|
94
93
|
elsif field_defined?(record, Enriched::Api::PHYS_INVENTORY_TAG)
|
95
94
|
tag = Enriched::Api::PHYS_INVENTORY_TAG
|
96
95
|
location_code_sf = Enriched::Api::PHYS_LOCATION_CODE
|
97
96
|
call_num_sf = Enriched::Api::PHYS_CALL_NUMBER
|
97
|
+
call_num_type_sf = Enriched::Api::PHYS_CALL_NUMBER_TYPE
|
98
98
|
# otherwise use Pub holding tags
|
99
99
|
else
|
100
100
|
tag = Enriched::Pub::PHYS_INVENTORY_TAG
|
101
101
|
location_code_sf = Enriched::Pub::PHYS_LOCATION_CODE
|
102
102
|
call_num_sf = Enriched::Pub::HOLDING_CLASSIFICATION_PART
|
103
|
+
call_num_type_sf = nil # for hld tags, the call num type is indicator0
|
103
104
|
end
|
104
105
|
|
105
|
-
{ tag: tag, location_code_sf: location_code_sf, call_num_sf: call_num_sf }
|
106
|
+
{ tag: tag, location_code_sf: location_code_sf, call_num_sf: call_num_sf, call_num_type_sf: call_num_type_sf }
|
106
107
|
end
|
107
108
|
|
108
109
|
# Determines whether to ignore a location code.
|
@@ -111,32 +112,55 @@ module PennMARC
|
|
111
112
|
# map, we ignore it, for faceting purposes. We also ignore the location code 'web'. We don't facet for 'web'
|
112
113
|
# which is the 'Penn Library Web' location used in Voyager. This location should eventually go away completely
|
113
114
|
# with data cleanup in Alma.
|
114
|
-
# @param location_map [
|
115
|
-
# @param location_code [
|
115
|
+
# @param location_map [Hash] hash with location_code as key and location hash as value
|
116
|
+
# @param location_code [String] retrieved from record
|
116
117
|
# @return [Boolean]
|
117
118
|
def location_code_to_ignore?(location_map, location_code)
|
118
|
-
location_map.key?(location_code.to_sym)
|
119
|
+
!location_map.key?(location_code.to_sym) || location_code == WEB_LOCATION_CODE
|
119
120
|
end
|
120
121
|
|
121
122
|
# Retrieves a specific location override based on location code and call number. Specific location overrides are
|
122
123
|
# located in `location_overrides.yml`.
|
123
|
-
# @param display_value [String | Symbol]
|
124
124
|
# @param location_code [String]
|
125
125
|
# @param field [MARC::Field]
|
126
126
|
# @param call_num_sf [String]
|
127
|
+
# @param call_num_type_sf [String, nil]
|
127
128
|
# @return [String, Nil]
|
128
|
-
def specific_location_override(
|
129
|
-
|
129
|
+
def specific_location_override(location_code:, field:, call_num_sf:, call_num_type_sf:)
|
130
|
+
callnum_type = callnum_type(field: field, call_num_type_sf: call_num_type_sf)
|
131
|
+
return unless callnum_type
|
130
132
|
|
131
|
-
|
133
|
+
override = Mappers.location_overrides.find do |_key, override_data|
|
134
|
+
override_matching?(override_data: override_data, location_code: location_code, callnum_type: callnum_type,
|
135
|
+
call_numbers: subfield_values(field, call_num_sf))
|
136
|
+
end
|
132
137
|
|
133
|
-
|
138
|
+
override&.last&.dig(:specific_location)
|
139
|
+
end
|
134
140
|
|
135
|
-
|
136
|
-
|
141
|
+
# Check override_data hash for a matching location name override
|
142
|
+
# @param override_data [Hash]
|
143
|
+
# @param location_code [String]
|
144
|
+
# @param call_numbers [Array]
|
145
|
+
# @param callnum_type [String]
|
146
|
+
# @return [Boolean]
|
147
|
+
def override_matching?(override_data:, location_code:, call_numbers:, callnum_type:)
|
148
|
+
call_numbers.any? do |call_number|
|
149
|
+
override_data[:location_code] == location_code &&
|
150
|
+
override_data[:call_num_type] == callnum_type &&
|
151
|
+
call_number.match?(override_data[:call_num_pattern])
|
137
152
|
end
|
153
|
+
end
|
138
154
|
|
139
|
-
|
155
|
+
# Return call num type value for a given field. If no call number subfield is expected (publishing holding
|
156
|
+
# inventory case), the first indicator is checked.
|
157
|
+
# @param field [MARC::Field]
|
158
|
+
# @param call_num_type_sf [String, nil]
|
159
|
+
# @return [String, nil]
|
160
|
+
def callnum_type(field:, call_num_type_sf:)
|
161
|
+
return field.indicator1 if call_num_type_sf.nil?
|
162
|
+
|
163
|
+
subfield_values(field, call_num_type_sf).first
|
140
164
|
end
|
141
165
|
end
|
142
166
|
end
|
@@ -93,22 +93,46 @@ module PennMARC
|
|
93
93
|
# @param record [MARC::Record]
|
94
94
|
# @return [String] single title for display
|
95
95
|
def show(record)
|
96
|
+
field = record.fields('245')&.first
|
97
|
+
values = title_values(field)
|
98
|
+
[format_title(values[:title_or_form]), values[:punctuation], values[:other_info]].compact_blank.join(' ')
|
99
|
+
end
|
100
|
+
|
101
|
+
# Same as show, but with inclusive dates appended. For use on show page.
|
102
|
+
# @param record [MARC::Record]
|
103
|
+
# @return [String] detailed title for display
|
104
|
+
def detailed_show(record)
|
105
|
+
field = record.fields('245')&.first
|
106
|
+
values = title_values(field)
|
107
|
+
title = [format_title(values[:title_or_form]), values[:punctuation],
|
108
|
+
trim_trailing(:period, values[:other_info])].compact_blank.join(' ')
|
109
|
+
values[:inclusive_dates].present? ? [title, values[:inclusive_dates]].compact_blank.join(', ') : title
|
110
|
+
end
|
111
|
+
|
112
|
+
# Same structure as show, but linked alternate title.
|
113
|
+
# @param record [MARC::Record]
|
114
|
+
# @return [String, nil] alternate title for display
|
115
|
+
def alternate_show(record)
|
116
|
+
field = record.fields('880').filter_map { |alternate_field|
|
117
|
+
next unless subfield_value?(alternate_field, '6', /^245/)
|
118
|
+
|
119
|
+
alternate_field
|
120
|
+
}.first
|
121
|
+
return unless field
|
122
|
+
|
123
|
+
values = title_values(field)
|
124
|
+
[format_title(values[:title_or_form]), values[:punctuation], values[:other_info]].compact_blank.join(' ')
|
125
|
+
end
|
126
|
+
|
127
|
+
# Title statement of responsibility (field 245, subfield c) and linked alternate for display.
|
128
|
+
# See https://www.oclc.org/bibformats/en/2xx/245.html#subfieldc for examples
|
129
|
+
# @param [MARC::Record] record
|
130
|
+
# @return [Array<String>] statement of responsibility and linked alternate
|
131
|
+
def statement_of_responsibility_show(record)
|
96
132
|
field = record.fields('245').first
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
other_info = field.find_all(&subfield_in?(%w[b n p]))
|
101
|
-
.map { |sf| trim_trailing(:slash, sf.value) }
|
102
|
-
.join(' ')
|
103
|
-
hpunct = field.find_all { |sf| sf.code == 'h' }.map { |sf| sf.value.last }.first
|
104
|
-
punctuation = if [title_or_form.last, hpunct].include?('=')
|
105
|
-
'='
|
106
|
-
else
|
107
|
-
[title_or_form.last, hpunct].include?(':') ? ':' : nil
|
108
|
-
end
|
109
|
-
[trim_trailing(:colon, trim_trailing(:equal, title_or_form)).strip,
|
110
|
-
punctuation,
|
111
|
-
other_info].compact_blank.join(' ')
|
133
|
+
statement = field&.find { |sf| sf.code == 'c' }&.value
|
134
|
+
alternate_statement = linked_alternate(record, '245', &subfield_in?(%w[c]))&.first
|
135
|
+
[statement, alternate_statement].compact_blank
|
112
136
|
end
|
113
137
|
|
114
138
|
# Canonical title with non-filing characters relocated to the end.
|
@@ -212,12 +236,13 @@ module PennMARC
|
|
212
236
|
def former_show(record)
|
213
237
|
record.fields
|
214
238
|
.filter_map { |field|
|
215
|
-
|
239
|
+
next unless field.tag == '247' || (field.tag == '880' && subfield_value?(field, '6', /^247/))
|
216
240
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
241
|
+
# 6 and 8 are not meaningful for display
|
242
|
+
former_title = join_subfields field, &subfield_not_in?(%w[6 8 e w])
|
243
|
+
former_title_append = join_subfields field, &subfield_in?(%w[e w])
|
244
|
+
"#{former_title} #{former_title_append}".strip
|
245
|
+
}.uniq
|
221
246
|
end
|
222
247
|
|
223
248
|
# Determine if the record is a "Host" bibliographic record for other bib records ("bound-withs")
|
@@ -232,6 +257,44 @@ module PennMARC
|
|
232
257
|
|
233
258
|
private
|
234
259
|
|
260
|
+
# Extract title values from provided 245 subfields. Main title components are the following:
|
261
|
+
# - title_or_form: subfields a and k
|
262
|
+
# - inclusive_dates: subfield c
|
263
|
+
# - other_info: subfields b, n, and p
|
264
|
+
# https://www.oclc.org/bibformats/en/2xx/245.html
|
265
|
+
#
|
266
|
+
# @param field [MARC::Field]
|
267
|
+
# @return [Hash] title values
|
268
|
+
def title_values(field)
|
269
|
+
title_or_form = field.find_all(&subfield_in?(%w[a k]))
|
270
|
+
.map { |sf| trim_trailing(:comma, trim_trailing(:slash, sf.value).rstrip) }
|
271
|
+
.first || ''
|
272
|
+
inclusive_dates = field.find { |sf| sf.code == 'f' }&.value
|
273
|
+
other_info = field.find_all(&subfield_in?(%w[b n p]))
|
274
|
+
.map { |sf| trim_trailing(:slash, sf.value) }
|
275
|
+
.join(' ')
|
276
|
+
title_punctuation = title_or_form.last
|
277
|
+
medium_punctuation = field.find_all { |sf| sf.code == 'h' }
|
278
|
+
.map { |sf| sf.value.last }
|
279
|
+
.first
|
280
|
+
punctuation = if [title_punctuation, medium_punctuation].include?('=')
|
281
|
+
'='
|
282
|
+
else
|
283
|
+
[title_punctuation, medium_punctuation].include?(':') ? ':' : nil
|
284
|
+
end
|
285
|
+
{ title_or_form: title_or_form,
|
286
|
+
inclusive_dates: inclusive_dates,
|
287
|
+
other_info: other_info,
|
288
|
+
punctuation: punctuation }
|
289
|
+
end
|
290
|
+
|
291
|
+
# Remove trailing equal from title, then remove trailing colon.
|
292
|
+
# @param title [String]
|
293
|
+
# @return [String]
|
294
|
+
def format_title(title)
|
295
|
+
trim_trailing(:colon, trim_trailing(:equal, title)).strip
|
296
|
+
end
|
297
|
+
|
235
298
|
# Create prefix/filing hash for representing a title value with filing characters removed, with special
|
236
299
|
# consideration for bracketed titles
|
237
300
|
# @todo Is this still useful?
|
data/lib/pennmarc/version.rb
CHANGED
@@ -2,22 +2,26 @@
|
|
2
2
|
|
3
3
|
describe 'PennMARC::Classification' do
|
4
4
|
let(:helper) { PennMARC::Classification }
|
5
|
-
let(:record)
|
6
|
-
marc_record fields: [marc_field(tag: tag,
|
7
|
-
subfields: { call_number_type_sf => '0', call_number_sf => 'TA683 .B3 1909b' }),
|
8
|
-
marc_field(tag: tag,
|
9
|
-
subfields: { call_number_type_sf => '0', call_number_sf => 'QL756 .S643' }),
|
10
|
-
marc_field(tag: tag,
|
11
|
-
subfields: { call_number_type_sf => '1', call_number_sf => '691.3 B2141' }),
|
12
|
-
marc_field(tag: tag,
|
13
|
-
subfields: { call_number_type_sf => '1', call_number_sf => '378.748 POS1952.29' })]
|
14
|
-
end
|
5
|
+
let(:record) { marc_record fields: fields }
|
15
6
|
|
16
7
|
describe '.facet' do
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
8
|
+
let(:fields) do
|
9
|
+
[marc_field(tag: config[:tag],
|
10
|
+
subfields: { config[:call_number_type_sf] => '0', config[:call_number_sf] => 'TA683 .B3 1909b' }),
|
11
|
+
marc_field(tag: config[:tag],
|
12
|
+
subfields: { config[:call_number_type_sf] => '0', config[:call_number_sf] => 'QL756 .S643' }),
|
13
|
+
marc_field(tag: config[:tag],
|
14
|
+
subfields: { config[:call_number_type_sf] => '1', config[:call_number_sf] => '691.3 B2141' }),
|
15
|
+
marc_field(tag: config[:tag],
|
16
|
+
subfields: { config[:call_number_type_sf] => '1', config[:call_number_sf] => '378.748 POS1952.29' })]
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with enrichment via the Alma publishing process and itm fields' do
|
20
|
+
let(:config) do
|
21
|
+
{ tag: PennMARC::Enriched::Pub::ITEM_TAG,
|
22
|
+
call_number_type_sf: PennMARC::Enriched::Pub::ITEM_CALL_NUMBER_TYPE,
|
23
|
+
call_number_sf: PennMARC::Enriched::Pub::ITEM_CALL_NUMBER }
|
24
|
+
end
|
21
25
|
|
22
26
|
it 'returns expected values' do
|
23
27
|
expect(helper.facet(record)).to contain_exactly('T - Technology', '600 - Technology',
|
@@ -26,9 +30,11 @@ describe 'PennMARC::Classification' do
|
|
26
30
|
end
|
27
31
|
|
28
32
|
context 'with enrichment with availability info via Alma Api' do
|
29
|
-
let(:
|
30
|
-
|
31
|
-
|
33
|
+
let(:config) do
|
34
|
+
{ tag: PennMARC::Enriched::Api::PHYS_INVENTORY_TAG,
|
35
|
+
call_number_type_sf: PennMARC::Enriched::Api::PHYS_CALL_NUMBER_TYPE,
|
36
|
+
call_number_sf: PennMARC::Enriched::Api::PHYS_CALL_NUMBER }
|
37
|
+
end
|
32
38
|
|
33
39
|
it 'returns expected values' do
|
34
40
|
expect(helper.facet(record)).to contain_exactly('T - Technology', '600 - Technology',
|
@@ -36,4 +42,63 @@ describe 'PennMARC::Classification' do
|
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
45
|
+
|
46
|
+
describe '.call_number_search' do
|
47
|
+
let(:fields) do
|
48
|
+
[marc_field(tag: config[:tag],
|
49
|
+
subfields: { config[:call_number_type_sf] => '0', config[:call_number_sf] => 'QL756 .S643' }),
|
50
|
+
marc_field(tag: config[:tag],
|
51
|
+
subfields: { config[:call_number_type_sf] => '1', config[:call_number_sf] => '691.3 B2141' })]
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with enrichment via the Alma publishing process' do
|
55
|
+
let(:config) do
|
56
|
+
{ tag: PennMARC::Enriched::Pub::ITEM_TAG,
|
57
|
+
call_number_type_sf: PennMARC::Enriched::Pub::ITEM_CALL_NUMBER_TYPE,
|
58
|
+
call_number_sf: PennMARC::Enriched::Pub::ITEM_CALL_NUMBER }
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns expected values' do
|
62
|
+
expect(helper.call_number_search(record)).to contain_exactly '691.3 B2141', 'QL756 .S643'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with enrichment via the Alma publishing process and no itm fields' do
|
67
|
+
let(:fields) do
|
68
|
+
[marc_field(tag: PennMARC::Enriched::Pub::PHYS_INVENTORY_TAG,
|
69
|
+
subfields: { PennMARC::Enriched::Pub::HOLDING_CLASSIFICATION_PART => 'KF6450',
|
70
|
+
PennMARC::Enriched::Pub::HOLDING_ITEM_PART => '.C59 1989' })]
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'returns expected values from the hld tag' do
|
74
|
+
expect(helper.call_number_search(record)).to contain_exactly('KF6450 .C59 1989')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with enrichment via the Alma publishing process and values from both hld and itm fields' do
|
79
|
+
let(:fields) do
|
80
|
+
[marc_field(tag: PennMARC::Enriched::Pub::PHYS_INVENTORY_TAG,
|
81
|
+
subfields: { PennMARC::Enriched::Pub::HOLDING_CLASSIFICATION_PART => 'KF6450',
|
82
|
+
PennMARC::Enriched::Pub::HOLDING_ITEM_PART => '.C59 1989' }),
|
83
|
+
marc_field(tag: PennMARC::Enriched::Pub::ITEM_TAG,
|
84
|
+
subfields: { PennMARC::Enriched::Pub::ITEM_CALL_NUMBER => 'KF6450 .C59 1989' })]
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'returns a single call number' do
|
88
|
+
expect(helper.call_number_search(record)).to contain_exactly('KF6450 .C59 1989')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'with enrichment with availability info via Alma Api' do
|
93
|
+
let(:config) do
|
94
|
+
{ tag: PennMARC::Enriched::Api::PHYS_INVENTORY_TAG,
|
95
|
+
call_number_type_sf: PennMARC::Enriched::Api::PHYS_CALL_NUMBER_TYPE,
|
96
|
+
call_number_sf: PennMARC::Enriched::Api::PHYS_CALL_NUMBER }
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'returns expected values' do
|
100
|
+
expect(helper.call_number_search(record)).to contain_exactly '691.3 B2141', 'QL756 .S643'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
39
104
|
end
|
@@ -4,12 +4,13 @@ describe 'PennMARC::Location' do
|
|
4
4
|
let(:helper) { PennMARC::Location }
|
5
5
|
let(:enriched_marc) { PennMARC::Enriched }
|
6
6
|
let(:mapping) { location_map }
|
7
|
+
let(:record) { marc_record(fields: fields) }
|
7
8
|
|
8
9
|
describe 'location' do
|
9
10
|
context "with only 'itm' field present" do
|
10
|
-
let(:
|
11
|
-
|
12
|
-
|
11
|
+
let(:fields) do
|
12
|
+
[marc_field(tag: enriched_marc::Pub::ITEM_TAG,
|
13
|
+
subfields: { enriched_marc::Pub::ITEM_CURRENT_LOCATION => 'stor' })]
|
13
14
|
end
|
14
15
|
|
15
16
|
it 'returns expected value' do
|
@@ -21,9 +22,9 @@ describe 'PennMARC::Location' do
|
|
21
22
|
end
|
22
23
|
|
23
24
|
context "with only 'hld' field present" do
|
24
|
-
let(:
|
25
|
-
|
26
|
-
|
25
|
+
let(:fields) do
|
26
|
+
[marc_field(tag: enriched_marc::Pub::PHYS_INVENTORY_TAG,
|
27
|
+
subfields: { enriched_marc::Pub::PHYS_LOCATION_CODE => 'stor' })]
|
27
28
|
end
|
28
29
|
|
29
30
|
it 'returns expected value' do
|
@@ -35,11 +36,11 @@ describe 'PennMARC::Location' do
|
|
35
36
|
end
|
36
37
|
|
37
38
|
context 'with both holding and item tag fields present=' do
|
38
|
-
let(:
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
let(:fields) do
|
40
|
+
[marc_field(tag: enriched_marc::Pub::ITEM_TAG,
|
41
|
+
subfields: { enriched_marc::Pub::ITEM_CURRENT_LOCATION => 'stor' }),
|
42
|
+
marc_field(tag: enriched_marc::Pub::PHYS_INVENTORY_TAG,
|
43
|
+
subfields: { enriched_marc::Pub::PHYS_LOCATION_CODE => 'dent' })]
|
43
44
|
end
|
44
45
|
|
45
46
|
it 'returns item location' do
|
@@ -49,7 +50,7 @@ describe 'PennMARC::Location' do
|
|
49
50
|
end
|
50
51
|
|
51
52
|
context 'with multiple library locations' do
|
52
|
-
let(:
|
53
|
+
let(:fields) { [marc_field(tag: enriched_marc::Pub::ITEM_TAG, subfields: { g: %w[dent] })] }
|
53
54
|
|
54
55
|
it 'returns expected value' do
|
55
56
|
expect(helper.location(record: record, location_map: mapping,
|
@@ -59,34 +60,19 @@ describe 'PennMARC::Location' do
|
|
59
60
|
end
|
60
61
|
|
61
62
|
context 'without enriched marc location tag' do
|
62
|
-
let(:
|
63
|
+
let(:fields) { [marc_field(tag: '852', subfields: { g: 'stor' })] }
|
63
64
|
|
64
65
|
it 'returns expected value' do
|
65
66
|
expect(helper.location(record: record, location_map: mapping, display_value: :library)).to be_empty
|
66
67
|
end
|
67
68
|
end
|
68
69
|
|
69
|
-
context 'with electronic inventory tag' do
|
70
|
-
let(:record) do
|
71
|
-
marc_record(fields: [marc_field(tag: enriched_marc::Pub::ITEM_TAG,
|
72
|
-
subfields: { enriched_marc::Pub::ITEM_CURRENT_LOCATION => 'stor' }),
|
73
|
-
marc_field(tag: enriched_marc::Pub::ELEC_INVENTORY_TAG)])
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'returns expected value' do
|
77
|
-
expect(helper.location(record: record, location_map: mapping,
|
78
|
-
display_value: :library)).to contain_exactly('LIBRA', helper::ONLINE_LIBRARY)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
70
|
context 'with AVA fields' do
|
83
|
-
let(:
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
enriched_marc::Api::PHYS_LOCATION_CODE => 'stor'
|
89
|
-
})])
|
71
|
+
let(:fields) do
|
72
|
+
[marc_field(tag: enriched_marc::Api::PHYS_INVENTORY_TAG,
|
73
|
+
subfields: { enriched_marc::Api::PHYS_LIBRARY_CODE => 'Libra',
|
74
|
+
enriched_marc::Api::PHYS_LOCATION_NAME => 'LIBRA',
|
75
|
+
enriched_marc::Api::PHYS_LOCATION_CODE => 'stor' })]
|
90
76
|
end
|
91
77
|
|
92
78
|
it 'returns expected values' do
|
@@ -96,37 +82,83 @@ describe 'PennMARC::Location' do
|
|
96
82
|
end
|
97
83
|
end
|
98
84
|
|
99
|
-
context 'with AVE fields' do
|
100
|
-
let(:record) do
|
101
|
-
marc_record(fields: [marc_field(tag: enriched_marc::Api::ELEC_INVENTORY_TAG,
|
102
|
-
subfields: { enriched_marc::Api::ELEC_COLLECTION_NAME => 'Nature' })])
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'returns expected values' do
|
106
|
-
expect(helper.location(record: record, location_map: mapping, display_value: :library)).to(
|
107
|
-
contain_exactly(helper::ONLINE_LIBRARY)
|
108
|
-
)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
85
|
context 'with a specific location override' do
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
86
|
+
context 'with item fields and LC call nums' do
|
87
|
+
let(:fields) do
|
88
|
+
[marc_field(tag: enriched_marc::Pub::ITEM_TAG,
|
89
|
+
subfields: { enriched_marc::Pub::ITEM_CURRENT_LOCATION => 'vanp',
|
90
|
+
enriched_marc::Pub::ITEM_CALL_NUMBER_TYPE =>
|
91
|
+
PennMARC::Classification::LOC_CALL_NUMBER_TYPE,
|
92
|
+
enriched_marc::Pub::ITEM_CALL_NUMBER => 'ML3534 .D85 1984' }),
|
93
|
+
marc_field(tag: enriched_marc::Pub::ITEM_TAG,
|
94
|
+
subfields: { enriched_marc::Pub::ITEM_CURRENT_LOCATION => 'stor',
|
95
|
+
enriched_marc::Pub::ITEM_CALL_NUMBER_TYPE => '8',
|
96
|
+
enriched_marc::Pub::ITEM_CALL_NUMBER => 'L3534 .D85 1984' })]
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'returns expected values' do
|
100
|
+
expect(helper.location(record: record, display_value: :specific_location, location_map: mapping))
|
101
|
+
.to(contain_exactly(PennMARC::Mappers.location_overrides[:albrecht][:specific_location], 'LIBRA'))
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'returns expected values when receiving a string for display_value' do
|
105
|
+
expect(helper.location(record: record, display_value: 'specific_location', location_map: mapping))
|
106
|
+
.to(contain_exactly(PennMARC::Mappers.location_overrides[:albrecht][:specific_location], 'LIBRA'))
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'with item fields and microfilm call nums' do
|
111
|
+
let(:fields) do
|
112
|
+
[marc_field(tag: enriched_marc::Pub::ITEM_TAG, indicator1: ' ',
|
113
|
+
subfields: { enriched_marc::Pub::ITEM_CURRENT_LOCATION => 'vanp',
|
114
|
+
enriched_marc::Pub::ITEM_CALL_NUMBER_TYPE => '8',
|
115
|
+
enriched_marc::Pub::ITEM_CALL_NUMBER => 'Microfilm 3140 item 8' })]
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'returns expected values' do
|
119
|
+
expect(helper.location(record: record, display_value: :specific_location, location_map: mapping))
|
120
|
+
.to(contain_exactly(PennMARC::Mappers.location[:vanp][:specific_location]))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'with holding fields and both LC and non-LC call num type' do
|
125
|
+
let(:fields) do
|
126
|
+
[marc_field(indicator1: '8', tag: enriched_marc::Pub::PHYS_INVENTORY_TAG,
|
127
|
+
subfields: { enriched_marc::Pub::PHYS_LOCATION_CODE => 'vanp' }),
|
128
|
+
marc_field(indicator1: '0', tag: enriched_marc::Pub::PHYS_INVENTORY_TAG,
|
129
|
+
subfields: { enriched_marc::Pub::PHYS_LOCATION_CODE => 'vanp',
|
130
|
+
enriched_marc::Pub::HOLDING_CLASSIFICATION_PART => 'ML3534' })]
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'returns expected values' do
|
134
|
+
expect(helper.location(record: record, display_value: :specific_location, location_map: mapping))
|
135
|
+
.to(contain_exactly(PennMARC::Mappers.location[:vanp][:specific_location],
|
136
|
+
PennMARC::Mappers.location_overrides[:albrecht][:specific_location]))
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'with a variety of holding fields from the Alma API enrichment' do
|
141
|
+
let(:fields) do
|
142
|
+
[marc_field(tag: enriched_marc::Api::PHYS_INVENTORY_TAG,
|
143
|
+
subfields: { enriched_marc::Api::PHYS_CALL_NUMBER => 'Locked Closet Floor',
|
144
|
+
enriched_marc::Api::PHYS_CALL_NUMBER_TYPE => '8' }),
|
145
|
+
marc_field(tag: enriched_marc::Api::PHYS_INVENTORY_TAG,
|
146
|
+
subfields: { enriched_marc::Api::PHYS_LOCATION_CODE => 'vanp',
|
147
|
+
enriched_marc::Api::PHYS_CALL_NUMBER => ['ML123 .P567 1875', 'ML123'],
|
148
|
+
enriched_marc::Api::PHYS_CALL_NUMBER_TYPE =>
|
149
|
+
PennMARC::Classification::LOC_CALL_NUMBER_TYPE }),
|
150
|
+
marc_field(tag: enriched_marc::Api::PHYS_INVENTORY_TAG,
|
151
|
+
subfields: { enriched_marc::Api::PHYS_LOCATION_CODE => 'vanp',
|
152
|
+
enriched_marc::Api::PHYS_CALL_NUMBER => 'P789 .D123 2012',
|
153
|
+
enriched_marc::Api::PHYS_CALL_NUMBER_TYPE =>
|
154
|
+
PennMARC::Classification::LOC_CALL_NUMBER_TYPE })]
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'returns expected values' do
|
158
|
+
expect(helper.location(record: record, display_value: :specific_location, location_map: mapping))
|
159
|
+
.to(contain_exactly(PennMARC::Mappers.location[:vanp][:specific_location],
|
160
|
+
PennMARC::Mappers.location_overrides[:albrecht][:specific_location]))
|
161
|
+
end
|
130
162
|
end
|
131
163
|
end
|
132
164
|
end
|
@@ -136,7 +136,7 @@ describe 'PennMARC::Note' do
|
|
136
136
|
it 'returns expected values from 506' do
|
137
137
|
expect(values).to contain_exactly(
|
138
138
|
'Open to users with valid PennKey Donor Appointment Only estate executors Some Policy No online access
|
139
|
-
20300101 Van Pelt URI
|
139
|
+
20300101 Van Pelt URI'.squish
|
140
140
|
)
|
141
141
|
end
|
142
142
|
end
|
@@ -138,6 +138,66 @@ describe 'PennMARC::Title' do
|
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
|
+
describe '.detailed_show' do
|
142
|
+
let(:record) do
|
143
|
+
marc_record fields: [
|
144
|
+
marc_field(tag: '245', subfields: { k: 'Letters', f: '1972-1982', b: 'to Lewis Mumford.' })
|
145
|
+
]
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'with subfields ǂk, ǂf and ǂc' do
|
149
|
+
it 'returns detailed title values' do
|
150
|
+
expect(helper.detailed_show(record)).to eq 'Letters to Lewis Mumford, 1972-1982'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe '.alternate_show' do
|
156
|
+
let(:record) do
|
157
|
+
marc_record fields: [
|
158
|
+
marc_field(tag: '245', subfields: { k: 'Letters', b: 'to Lewis Mumford. ' }),
|
159
|
+
marc_field(tag: '880', subfields: { '6': '245', k: 'Lettres', b: 'à Lewis Mumford.' })
|
160
|
+
]
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'with subfields ǂk and ǂb' do
|
164
|
+
it 'returns alternate title values' do
|
165
|
+
expect(helper.alternate_show(record)).to eq 'Lettres à Lewis Mumford.'
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'when 880 field is not present' do
|
170
|
+
let(:record) do
|
171
|
+
marc_record fields: [
|
172
|
+
marc_field(tag: '245', subfields: { k: 'Letters', b: 'to Lewis Mumford. ' })
|
173
|
+
]
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'returns nil' do
|
177
|
+
expect(helper.alternate_show(record)).to be_nil
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe '.statement_of_responsibility_show' do
|
183
|
+
let(:record) do
|
184
|
+
marc_record fields: [marc_field(tag: '245', subfields: { c: 'statement of responsibility' }),
|
185
|
+
marc_field(tag: '880', subfields: { '6': '245', c: 'déclaration de responsabilité' })]
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'with ǂc defined' do
|
189
|
+
it 'returns statement of responsibility' do
|
190
|
+
expect(helper.statement_of_responsibility_show(record)).to include 'statement of responsibility'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'with linked alternate of 245 ǂc defined' do
|
195
|
+
it 'returns alternate statement of responsibility' do
|
196
|
+
expect(helper.statement_of_responsibility_show(record)).to include 'déclaration de responsabilité'
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
141
201
|
describe '.sort' do
|
142
202
|
context 'with a record with a valid indicator2 value' do
|
143
203
|
let(:record) do
|
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.
|
4
|
+
version: 1.1.1
|
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: 2024-08-
|
15
|
+
date: 2024-08-23 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activesupport
|