pennmarc 1.0.33 → 1.1.1
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 +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
|