pennmarc 1.0.24 → 1.0.26
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 +8 -9
- data/lib/pennmarc/enriched.rb +1 -0
- data/lib/pennmarc/helpers/access.rb +8 -6
- data/lib/pennmarc/helpers/creator.rb +139 -65
- data/lib/pennmarc/helpers/edition.rb +5 -3
- data/lib/pennmarc/helpers/identifier.rb +12 -0
- data/lib/pennmarc/helpers/note.rb +24 -19
- data/lib/pennmarc/helpers/production.rb +113 -20
- data/lib/pennmarc/helpers/subject.rb +10 -4
- data/lib/pennmarc/helpers/title.rb +39 -26
- data/lib/pennmarc/test/marc_helpers.rb +83 -0
- data/lib/pennmarc/util.rb +98 -69
- data/lib/pennmarc/version.rb +1 -1
- data/lib/pennmarc.rb +7 -0
- data/spec/lib/pennmarc/helpers/access_spec.rb +11 -2
- data/spec/lib/pennmarc/helpers/citation_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/classification_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/creator_spec.rb +103 -2
- data/spec/lib/pennmarc/helpers/database_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/date_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/edition_spec.rb +4 -2
- data/spec/lib/pennmarc/helpers/format_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/genre_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/identifer_spec.rb +14 -2
- data/spec/lib/pennmarc/helpers/inventory_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/language_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/link_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/location_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/note_spec.rb +22 -29
- data/spec/lib/pennmarc/helpers/production_spec.rb +121 -22
- data/spec/lib/pennmarc/helpers/relation_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/series_spec.rb +0 -2
- data/spec/lib/pennmarc/helpers/subject_spec.rb +16 -2
- data/spec/lib/pennmarc/helpers/title_spec.rb +20 -2
- data/spec/lib/pennmarc/marc_util_spec.rb +0 -2
- data/spec/lib/pennmarc/parser_spec.rb +1 -1
- data/spec/spec_helper.rb +7 -0
- data/spec/support/fixture_helpers.rb +10 -0
- metadata +4 -3
- data/spec/support/marc_spec_helpers.rb +0 -85
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b4d6a53347f4532faa566debcc59bde1fb7043cfbd4530d0a06489a36db8599
|
4
|
+
data.tar.gz: 8a92c36c80406541ac454025e6c2adc53af80dab20af5af16b8995dc5bacfe9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b1f0be0caba6a00adc8ccc5516556b2de250d93861157c49a60e17f52810b6eed7942efe8b51843d7428bb329c6dcad58a0887c17e9132004fe3d7d29729682
|
7
|
+
data.tar.gz: b06dad73899b13254391b74832d3b99745d82bc9f871801d7a617e2416f9d70039d45a9122a292377628b638c4044e692432688dbce48497cb6394fa48ba0d6e
|
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-07-02 15:41:46 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: 25
|
18
18
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
19
19
|
Metrics/AbcSize:
|
20
20
|
Exclude:
|
@@ -26,18 +26,18 @@ Metrics/AbcSize:
|
|
26
26
|
- 'lib/pennmarc/helpers/location.rb'
|
27
27
|
- 'lib/pennmarc/helpers/note.rb'
|
28
28
|
- 'lib/pennmarc/helpers/production.rb'
|
29
|
-
- 'lib/pennmarc/helpers/relation.rb'
|
30
29
|
- 'lib/pennmarc/helpers/series.rb'
|
31
30
|
- 'lib/pennmarc/helpers/subject.rb'
|
32
31
|
- 'lib/pennmarc/helpers/title.rb'
|
33
32
|
- 'lib/pennmarc/util.rb'
|
34
33
|
|
35
|
-
# Offense count:
|
34
|
+
# Offense count: 8
|
36
35
|
# Configuration parameters: CountComments, Max, CountAsOne.
|
37
36
|
Metrics/ClassLength:
|
38
37
|
Exclude:
|
39
38
|
- 'lib/pennmarc/helpers/creator.rb'
|
40
39
|
- 'lib/pennmarc/helpers/format.rb'
|
40
|
+
- 'lib/pennmarc/helpers/production.rb'
|
41
41
|
- 'lib/pennmarc/helpers/series.rb'
|
42
42
|
- 'lib/pennmarc/helpers/subject.rb'
|
43
43
|
- 'lib/pennmarc/helpers/title.rb'
|
@@ -54,13 +54,12 @@ Metrics/CyclomaticComplexity:
|
|
54
54
|
- 'lib/pennmarc/helpers/language.rb'
|
55
55
|
- 'lib/pennmarc/helpers/note.rb'
|
56
56
|
- 'lib/pennmarc/helpers/production.rb'
|
57
|
-
- 'lib/pennmarc/helpers/relation.rb'
|
58
57
|
- 'lib/pennmarc/helpers/series.rb'
|
59
58
|
- 'lib/pennmarc/helpers/subject.rb'
|
60
59
|
- 'lib/pennmarc/helpers/title.rb'
|
61
60
|
- 'lib/pennmarc/util.rb'
|
62
61
|
|
63
|
-
# Offense count:
|
62
|
+
# Offense count: 28
|
64
63
|
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
|
65
64
|
Metrics/MethodLength:
|
66
65
|
Exclude:
|
@@ -82,7 +81,7 @@ Metrics/ModuleLength:
|
|
82
81
|
Exclude:
|
83
82
|
- 'lib/pennmarc/util.rb'
|
84
83
|
|
85
|
-
# Offense count:
|
84
|
+
# Offense count: 14
|
86
85
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
87
86
|
Metrics/PerceivedComplexity:
|
88
87
|
Exclude:
|
@@ -123,7 +122,7 @@ Naming/VariableNumber:
|
|
123
122
|
Exclude:
|
124
123
|
- 'lib/pennmarc/util.rb'
|
125
124
|
|
126
|
-
# Offense count:
|
125
|
+
# Offense count: 8
|
127
126
|
# Configuration parameters: Max, CountAsOne.
|
128
127
|
RSpec/ExampleLength:
|
129
128
|
Exclude:
|
@@ -139,7 +138,7 @@ RSpec/FilePath:
|
|
139
138
|
Exclude:
|
140
139
|
- 'spec/lib/pennmarc/parser_spec.rb'
|
141
140
|
|
142
|
-
# Offense count:
|
141
|
+
# Offense count: 23
|
143
142
|
# Configuration parameters: Max, AllowedGroups.
|
144
143
|
RSpec/NestedGroups:
|
145
144
|
Exclude:
|
data/lib/pennmarc/enriched.rb
CHANGED
@@ -12,6 +12,7 @@ module PennMARC
|
|
12
12
|
PHYS_INVENTORY_TAG = 'hld'
|
13
13
|
ELEC_INVENTORY_TAG = 'prt'
|
14
14
|
ITEM_TAG = 'itm'
|
15
|
+
RELATED_RECORD_TAG = 'rel'
|
15
16
|
|
16
17
|
# Subfields for HLD tags
|
17
18
|
# Follow MARC 852 spec: https://www.loc.gov/marc/holdings/hd852.html, but names are translated into Alma parlance
|
@@ -5,14 +5,13 @@ module PennMARC
|
|
5
5
|
class Access < Helper
|
6
6
|
ONLINE = 'Online'
|
7
7
|
AT_THE_LIBRARY = 'At the library'
|
8
|
+
RESOURCE_LINK_BASE_URL = 'hdl.library.upenn.edu'
|
8
9
|
|
9
10
|
class << self
|
10
11
|
# Based on enhanced metadata fields added by Alma publishing process or API, determine if the record has
|
11
12
|
# electronic access or has physical holdings, and is therefore "Online" or "At the library". If a record is "At
|
12
13
|
# the library", but has a link to a finding aid in the 856 field (matching certain criteria), also add 'Online' as
|
13
14
|
# an access method.
|
14
|
-
# @todo What if none of these criteria match? Should we include "At the library" by default? Records with no value
|
15
|
-
# in this field would be lost if the user selects a facet value.
|
16
15
|
# @param [MARC::Record] record
|
17
16
|
# @return [Array]
|
18
17
|
def facet(record)
|
@@ -24,7 +23,7 @@ module PennMARC
|
|
24
23
|
return values if values.size == 2 # return early if all values are already present
|
25
24
|
|
26
25
|
# only check if ONLINE isn't already there
|
27
|
-
values << ONLINE if values.exclude?(ONLINE) &&
|
26
|
+
values << ONLINE if values.exclude?(ONLINE) && resource_link?(record)
|
28
27
|
values.uniq
|
29
28
|
end
|
30
29
|
|
@@ -44,20 +43,23 @@ module PennMARC
|
|
44
43
|
field.tag.in? [Enriched::Pub::PHYS_INVENTORY_TAG, Enriched::Api::PHYS_INVENTORY_TAG]
|
45
44
|
end
|
46
45
|
|
47
|
-
# Check if a record contains an 856 entry
|
46
|
+
# Check if a record contains an 856 entry with a Penn Handle server link meeting these criteria:
|
48
47
|
# 1. Indicator 1 is 4 (HTTP resource)
|
49
48
|
# 2. Indicator 2 is NOT 2 (indicating the linkage is to a "related" thing)
|
50
49
|
# 3. The URL specified in subfield u (URI) is a Penn Handle link
|
50
|
+
# 4. The subfield z does NOT include the string 'Finding aid'
|
51
51
|
# See: https://www.loc.gov/marc/bibliographic/bd856.html
|
52
|
+
# @note Some electronic records do not have Portfolios in Alma, so we rely upon the Resource Link in the 856 to
|
53
|
+
# get these records included in the Online category.
|
52
54
|
# @param [MARC::Record] record
|
53
55
|
# @return [Boolean]
|
54
|
-
def
|
56
|
+
def resource_link?(record)
|
55
57
|
record.fields('856').filter_map do |field|
|
56
58
|
next if field.indicator2 == '2' || field.indicator1 != '4'
|
57
59
|
|
58
60
|
subz = subfield_values(field, 'z')
|
59
61
|
subfield_values(field, 'u').filter_map do |value|
|
60
|
-
return true if subz.
|
62
|
+
return true if subz.exclude?('Finding aid') && value.include?(RESOURCE_LINK_BASE_URL)
|
61
63
|
end
|
62
64
|
end
|
63
65
|
false
|
@@ -7,26 +7,27 @@ module PennMARC
|
|
7
7
|
# @todo can there ever be multiple 100 fields?
|
8
8
|
# can ǂe and ǂ4 both be used at the same time? seems to result in duplicate values
|
9
9
|
class Creator < Helper
|
10
|
-
|
11
|
-
|
12
|
-
TAGS = %w[100 110].freeze
|
10
|
+
# Main tags for Author/Creator information
|
11
|
+
TAGS = %w[100 110].freeze
|
13
12
|
|
14
|
-
|
15
|
-
|
13
|
+
# Aux tags for Author/Creator information, for use in search_aux method
|
14
|
+
AUX_TAGS = %w[100 110 111 400 410 411 700 710 711 800 810 811].freeze
|
16
15
|
|
17
|
-
|
16
|
+
CONFERENCE_SEARCH_TAGS = %w[111 711 811].freeze
|
17
|
+
CORPORATE_SEARCH_TAGS = %w[110 710 810].freeze
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
# subfields NOT to join when combining raw subfield values
|
20
|
+
NAME_EXCLUDED_SUBFIELDS = %w[a 1 4 5 6 8 t].freeze
|
21
21
|
|
22
|
-
|
22
|
+
CONTRIBUTOR_TAGS = %w[700 710].freeze
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
29
|
|
30
|
+
class << self
|
30
31
|
# Author/Creator search field. Includes all subfield values (even ǂ0 URIs) from
|
31
32
|
# {https://www.oclc.org/bibformats/en/1xx/100.html 100 Main Entry--Personal Name} and
|
32
33
|
# {https://www.oclc.org/bibformats/en/1xx/110.html 110 Main Entry--Corporate Name}. Maps any relator codes found
|
@@ -35,8 +36,8 @@ module PennMARC
|
|
35
36
|
# @todo are we including too many details here and gumming up our index? consider UIRs, relator labels, dates...
|
36
37
|
# @todo shouldn't indicator1 tell us the order of the name? do we not trust the indicator?
|
37
38
|
# @note ported from get_author_creator_1_search_values
|
38
|
-
# @param [MARC::Record]
|
39
|
-
# @param [Hash]
|
39
|
+
# @param record [MARC::Record]
|
40
|
+
# @param relator_map [Hash]
|
40
41
|
# @return [Array<String>] array of author/creator values for indexing
|
41
42
|
def search(record, relator_map: Mappers.relator)
|
42
43
|
name_search_values record: record, tags: TAGS, relator_map: relator_map
|
@@ -50,7 +51,7 @@ module PennMARC
|
|
50
51
|
# and {https://www.loc.gov/marc/bibliographic/bd711.html MARC 711}. The 800, 810 and 8111 tags are similar in
|
51
52
|
# theme to the 7xx fields but apply to serial records.
|
52
53
|
# @note ported from get_author_creator_2_search_values
|
53
|
-
# @param [MARC::Record]
|
54
|
+
# @param record [MARC::Record]
|
54
55
|
# @return [Array<String>] array of extended author/creator values for indexing
|
55
56
|
def search_aux(record, relator_map: Mappers.relator)
|
56
57
|
name_search_values record: record, tags: AUX_TAGS, relator_map: relator_map
|
@@ -60,7 +61,7 @@ module PennMARC
|
|
60
61
|
# and {https://www.loc.gov/marc/bibliographic/bd110.html 110} and their linked alternates. First, joins subfields
|
61
62
|
# other than $0, $1, $4, $6, $8, $e, and w. Then, appends any encoded relators found in $4.
|
62
63
|
# If there are no valid encoded relators, uses the value found in $e.
|
63
|
-
# @param [MARC::Record]
|
64
|
+
# @param record [MARC::Record]
|
64
65
|
# @return [Array<String>] array of author/creator values for display
|
65
66
|
def show(record, relator_map: Mappers.relator)
|
66
67
|
fields = record.fields(TAGS)
|
@@ -72,8 +73,8 @@ module PennMARC
|
|
72
73
|
|
73
74
|
# Hash with main creator show values as the fields and the corresponding facet as the values.
|
74
75
|
# Does not include linked 880s.
|
75
|
-
# @param [MARC::Record]
|
76
|
-
# @param [Hash]
|
76
|
+
# @param record [MARC::Record]
|
77
|
+
# @param relator_map [Hash]
|
77
78
|
# @return [Hash]
|
78
79
|
def show_facet_map(record, relator_map: Mappers.relator)
|
79
80
|
creators = record.fields(TAGS).filter_map do |field|
|
@@ -84,11 +85,82 @@ module PennMARC
|
|
84
85
|
creators.to_h { |h| [h[:show], h[:facet]] }
|
85
86
|
end
|
86
87
|
|
88
|
+
# Returns the list of authors with name (subfield $a) only
|
89
|
+
# @param [MARC::Record] record
|
90
|
+
# @param [Boolean] main_tags_only, if true, only use TAGS; otherwise use both TAGS and CONTRIBUTOR_TAGS
|
91
|
+
# @param [Boolean] first_initial_only: true to only use the first initial instead of first name
|
92
|
+
# @return [Array<String>] names of the authors
|
93
|
+
def authors_list(record, main_tags_only: false, first_initial_only: false)
|
94
|
+
tags = if main_tags_only
|
95
|
+
TAGS
|
96
|
+
else
|
97
|
+
TAGS + CONTRIBUTOR_TAGS
|
98
|
+
end
|
99
|
+
|
100
|
+
fields = record.fields(tags)
|
101
|
+
fields.filter_map { |field|
|
102
|
+
if first_initial_only
|
103
|
+
abbreviate_name(field['a']) if field['a']
|
104
|
+
else
|
105
|
+
field['a']
|
106
|
+
end
|
107
|
+
}.uniq
|
108
|
+
end
|
109
|
+
|
110
|
+
# Show the authors and contributors grouped together by relators with only names
|
111
|
+
# @param [MARC::Record] record
|
112
|
+
# @param [Hash] relator_map
|
113
|
+
# @param [Boolean] include_authors: true to include author fields TAGS
|
114
|
+
# @param [Boolean] name_only: true to include only the name subfield $a
|
115
|
+
# @param [Boolean] vernacular: true to include field 880 with subfield $6
|
116
|
+
# @return [Hash]
|
117
|
+
def contributors_list(record, relator_map: Mappers.relator, include_authors: true, name_only: true,
|
118
|
+
vernacular: false)
|
119
|
+
indicator_2_options = ['', ' ', '0']
|
120
|
+
tags = CONTRIBUTOR_TAGS
|
121
|
+
|
122
|
+
fields = record.fields(tags)
|
123
|
+
fields += record.fields('880').select { |field| subfield_value_in?(field, '6', CONTRIBUTOR_TAGS) } if vernacular
|
124
|
+
|
125
|
+
contributors = {}
|
126
|
+
fields.each do |field|
|
127
|
+
next if indicator_2_options.exclude?(field.indicator2) && field.tag.in?(CONTRIBUTOR_TAGS)
|
128
|
+
next if subfield_defined? field, 'i'
|
129
|
+
|
130
|
+
relator = relator(field: field, relator_term_sf: 'e', relator_map: relator_map)
|
131
|
+
relator = 'Contributor' if relator.blank?
|
132
|
+
relator = trim_punctuation(relator).capitalize
|
133
|
+
|
134
|
+
name = if name_only
|
135
|
+
field['a']
|
136
|
+
else
|
137
|
+
join_subfields(field, &subfield_in?(%w[a b c d j q u 3])) + ", #{relator}"
|
138
|
+
end
|
139
|
+
|
140
|
+
if contributors.key?(relator)
|
141
|
+
contributors[relator].push(name)
|
142
|
+
else
|
143
|
+
contributors[relator] = [name]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# add the authors
|
148
|
+
if include_authors
|
149
|
+
authors = authors_list(record, main_tags_only: true)
|
150
|
+
if contributors.key?('Author')
|
151
|
+
contributors['Author'] += authors
|
152
|
+
else
|
153
|
+
contributors['Author'] = authors
|
154
|
+
end
|
155
|
+
end
|
156
|
+
contributors
|
157
|
+
end
|
158
|
+
|
87
159
|
# All author/creator values for display (like #show, but multivalued?) - no 880 linkage
|
88
160
|
# Performs additional normalization of author names
|
89
161
|
# @note ported from get_author_creator_values (indexed as author_creator_a) - shown on results page
|
90
|
-
# @param [MARC::Record]
|
91
|
-
# @param [Hash]
|
162
|
+
# @param record [MARC::Record]
|
163
|
+
# @param relator_map [Hash]
|
92
164
|
# @return [Array<String>] array of author/creator values for display
|
93
165
|
def show_aux(record, relator_map: Mappers.relator)
|
94
166
|
record.fields(TAGS).map { |field|
|
@@ -99,7 +171,7 @@ module PennMARC
|
|
99
171
|
# Author/Creator sort. Does not map and include any relator codes.
|
100
172
|
# @todo This includes any URI from ǂ0 which could help to disambiguate in sorts, but ǂ1 is excluded...
|
101
173
|
# @note ported from get_author_creator_sort_values
|
102
|
-
# @param [MARC::Record]
|
174
|
+
# @param record [MARC::Record]
|
103
175
|
# @return [String] string with author/creator value for sorting
|
104
176
|
def sort(record)
|
105
177
|
field = record.fields(TAGS).first
|
@@ -107,11 +179,11 @@ module PennMARC
|
|
107
179
|
end
|
108
180
|
|
109
181
|
# Author/Creator for faceting. Grabs values from a plethora of fields, joins defined subfields, then trims some
|
110
|
-
# punctuation (@see trim_punctuation)
|
182
|
+
# punctuation (@see Util.trim_punctuation)
|
111
183
|
# @todo should trim_punctuation apply to each subfield value, or the joined values? i think the joined values
|
112
184
|
# @note ported from author_creator_xfacet2_input - is this the best choice? check the copyField declarations -
|
113
185
|
# franklin uses author_creator_f
|
114
|
-
# @param [MARC::Record]
|
186
|
+
# @param record [MARC::Record]
|
115
187
|
# @return [Array<String>] array of author/creator values for faceting
|
116
188
|
def facet(record)
|
117
189
|
FACET_SOURCE_MAP.flat_map { |field_num, subfields|
|
@@ -123,8 +195,8 @@ module PennMARC
|
|
123
195
|
|
124
196
|
# Conference for display, intended for results display
|
125
197
|
# @note ported from get_conference_values
|
126
|
-
# @param [MARC::Record]
|
127
|
-
# @param [Hash]
|
198
|
+
# @param record [MARC::Record]
|
199
|
+
# @param relator_map [Hash]
|
128
200
|
# @return [Array<String>] array of conference values
|
129
201
|
def conference_show(record, relator_map: Mappers.relator)
|
130
202
|
record.fields('111').filter_map { |field|
|
@@ -139,7 +211,7 @@ module PennMARC
|
|
139
211
|
# using subfields $e and $w. We append any relators, preferring those defined in $4 and using $j as a fallback.
|
140
212
|
# @note ported from get_conference_values
|
141
213
|
# @todo what is ǂi for?
|
142
|
-
# @param [MARC::Record]
|
214
|
+
# @param record [MARC::Record]
|
143
215
|
# @return [Array<String>] array of conference values
|
144
216
|
def conference_detail_show(record, relator_map: Mappers.relator)
|
145
217
|
conferences = record.fields(%w[111 711]).filter_map do |field|
|
@@ -164,8 +236,8 @@ module PennMARC
|
|
164
236
|
# Return hash of detailed conference values mapped to their corresponding facets from fields
|
165
237
|
# {https://www.loc.gov/marc/bibliographic/bd111.html 111} and
|
166
238
|
# {https://www.loc.gov/marc/bibliographic/bd711.html 711}. Does not include linked 880s.
|
167
|
-
# @param [MARC::Record]
|
168
|
-
# @param [Hash]
|
239
|
+
# @param record [MARC::Record]
|
240
|
+
# @param relator_map [Hash]
|
169
241
|
# @return [Hash]
|
170
242
|
def conference_detail_show_facet_map(record, relator_map: Mappers.relator)
|
171
243
|
conferences = record.fields(%w[111 711]).filter_map do |field|
|
@@ -180,7 +252,7 @@ module PennMARC
|
|
180
252
|
end
|
181
253
|
|
182
254
|
# Conference name values for searching
|
183
|
-
# @param [MARC::Record]
|
255
|
+
# @param record [MARC::Record]
|
184
256
|
# @return [Array<String>]
|
185
257
|
def conference_search(record)
|
186
258
|
record.fields(CONFERENCE_SEARCH_TAGS).filter_map { |field|
|
@@ -188,14 +260,23 @@ module PennMARC
|
|
188
260
|
}.uniq
|
189
261
|
end
|
190
262
|
|
263
|
+
# Corporate author search values for searching
|
264
|
+
# @param record [MARC::Record]
|
265
|
+
# @return [Array<String>]
|
266
|
+
def corporate_search(record)
|
267
|
+
record.fields(CORPORATE_SEARCH_TAGS).filter_map do |field|
|
268
|
+
join_subfields(field, &subfield_in?(%w[a b c d]))
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
191
272
|
# Retrieve contributor values for display from fields {https://www.oclc.org/bibformats/en/7xx/700.html 700}
|
192
273
|
# and {https://www.oclc.org/bibformats/en/7xx/710.html 710} and their linked alternates. Joins subfields
|
193
274
|
# 'a', 'b', 'c', 'd', 'j', and 'q', 'u', and '3'. Then appends resulting string with any encoded relationships
|
194
275
|
# found in $4. If there are no valid encoded relationships, uses the value found in $e.
|
195
276
|
# @note legacy version returns array of hash objects including data for display link
|
196
277
|
# @todo is it okay to include 880 $4 here? Legacy includes $4 in main author display 880 but not here.
|
197
|
-
# @param [MARC::Record]
|
198
|
-
# @
|
278
|
+
# @param record [MARC::Record]
|
279
|
+
# @param relator_map [Hash]
|
199
280
|
# @return [Array<String>]
|
200
281
|
def contributor_show(record, relator_map: Mappers.relator)
|
201
282
|
indicator_2_options = ['', ' ', '0']
|
@@ -212,9 +293,9 @@ module PennMARC
|
|
212
293
|
|
213
294
|
private
|
214
295
|
|
215
|
-
# @param [MARC::Record]
|
216
|
-
# @param [Array]
|
217
|
-
# @param [Hash]
|
296
|
+
# @param record [MARC::Record]
|
297
|
+
# @param tags [Array] to consider
|
298
|
+
# @param relator_map [Hash]
|
218
299
|
# @return [Array<String>] name values from given tags
|
219
300
|
def name_search_values(record:, tags:, relator_map:)
|
220
301
|
acc = record.fields(tags).filter_map do |field|
|
@@ -238,30 +319,10 @@ module PennMARC
|
|
238
319
|
acc.uniq
|
239
320
|
end
|
240
321
|
|
241
|
-
# Trim punctuation method extracted from Traject macro, to ensure consistent output
|
242
|
-
# @todo move to Util?
|
243
|
-
# @param [String] string
|
244
|
-
# @return [String] string with relevant punctuation removed
|
245
|
-
def trim_punctuation(string)
|
246
|
-
return string unless string
|
247
|
-
|
248
|
-
string = string.sub(%r{ *[ ,/;:] *\Z}, '')
|
249
|
-
|
250
|
-
# trailing period if it is preceded by at least three letters (possibly preceded and followed by whitespace)
|
251
|
-
string = string.sub(/( *[[:word:]]{3,})\. *\Z/, '\1')
|
252
|
-
|
253
|
-
# single square bracket characters if they are the start and/or end chars and there are no internal square
|
254
|
-
# brackets.
|
255
|
-
string = string.sub(/\A\[?([^\[\]]+)\]?\Z/, '\1')
|
256
|
-
|
257
|
-
# trim any leading or trailing whitespace
|
258
|
-
string.strip
|
259
|
-
end
|
260
|
-
|
261
322
|
# Extract the information we care about from 1xx fields, map relator codes, and use appropriate punctuation
|
262
|
-
# @param [MARC::Field]
|
263
|
-
# @param [Hash]
|
264
|
-
# @param [Boolean]
|
323
|
+
# @param field [MARC::Field]
|
324
|
+
# @param mapping [Hash]
|
325
|
+
# @param should_convert_name_order [Boolean]
|
265
326
|
# @return [String] joined subfield values for value from field
|
266
327
|
def name_from_main_entry(field, mapping, should_convert_name_order: false)
|
267
328
|
relator_term_sf = relator_term_subfield(field)
|
@@ -284,7 +345,7 @@ module PennMARC
|
|
284
345
|
end
|
285
346
|
|
286
347
|
# Convert "Lastname, First" to "First Lastname"
|
287
|
-
# @param [String]
|
348
|
+
# @param name [String] value for processing
|
288
349
|
# @return [String]
|
289
350
|
def convert_name_order(name)
|
290
351
|
return name unless name.include? ','
|
@@ -294,17 +355,30 @@ module PennMARC
|
|
294
355
|
"#{after_comma} #{before_comma}".squish
|
295
356
|
end
|
296
357
|
|
358
|
+
# Convert "Lastname, First" to "Lastname, F"
|
359
|
+
# @param [String] name
|
360
|
+
def abbreviate_name(name)
|
361
|
+
name_parts = name.split(', ')
|
362
|
+
return '' if name_parts.empty?
|
363
|
+
|
364
|
+
first_name_parts = name_parts.last.split
|
365
|
+
temp_name = "#{name_parts.first}, #{first_name_parts.first[0, 1]}."
|
366
|
+
first_name_parts.shift
|
367
|
+
temp_name += " #{first_name_parts.join(' ')}" unless first_name_parts.empty?
|
368
|
+
temp_name
|
369
|
+
end
|
370
|
+
|
297
371
|
# Parse creator facet value from given creator field and desired subfields
|
298
|
-
# @param [MARC::Field]
|
299
|
-
# @param [Array<String>]
|
372
|
+
# @param field [MARC::Field]
|
373
|
+
# @param subfields [Array<String>]
|
300
374
|
# @return [String]
|
301
375
|
def parse_facet_value(field, subfields)
|
302
376
|
trim_punctuation(join_subfields(field, &subfield_in?(subfields)))
|
303
377
|
end
|
304
378
|
|
305
379
|
# Parse creator show value from given main creator fields (100/110).
|
306
|
-
# @param [MARC::Field]
|
307
|
-
# @param [Hash]
|
380
|
+
# @param field [MARC::Field]
|
381
|
+
# @param relator_map [Hash]
|
308
382
|
# @return [String]
|
309
383
|
def parse_show_value(field, relator_map: Mappers.relator)
|
310
384
|
creator = join_subfields(field, &subfield_not_in?(%w[0 1 4 6 8 e w]))
|
@@ -314,7 +388,7 @@ module PennMARC
|
|
314
388
|
# Parse detailed conference show value from given conference field (111/711). If there is no $i, we join subfield
|
315
389
|
# values other than $0, $4, $5, $6, $8, $e, $j, and $w to create conference value. We join subfields $e and $w to
|
316
390
|
# determine the subunit value. We append any relators, preferring those defined in $4 and using $j as a fallback.
|
317
|
-
# @param [MARC::Field]
|
391
|
+
# @param field [MARC::Field]
|
318
392
|
# @return [String]
|
319
393
|
def parse_conference_detail_show_value(field, relator_map: Mappers.relator)
|
320
394
|
conf = if subfield_undefined? field, 'i'
|
@@ -13,10 +13,12 @@ module PennMARC
|
|
13
13
|
# https://www.loc.gov/marc/bibliographic/bd250.html
|
14
14
|
# @param [MARC::Record] record
|
15
15
|
# @return [Array<String>] array of editions and their alternates
|
16
|
-
def show(record)
|
17
|
-
editions = record.fields('250').map
|
16
|
+
def show(record, with_alternate: true)
|
17
|
+
editions = record.fields('250').map do |field|
|
18
18
|
join_subfields(field, &subfield_not_in?(%w[6 8]))
|
19
|
-
|
19
|
+
end
|
20
|
+
editions += linked_alternate_not_6_or_8(record, '250') if with_alternate
|
21
|
+
|
20
22
|
editions.uniq
|
21
23
|
end
|
22
24
|
|
@@ -159,6 +159,18 @@ module PennMARC
|
|
159
159
|
}.uniq
|
160
160
|
end
|
161
161
|
|
162
|
+
# Gets any Host record MMS ID values from an Enriched::Pub::RELATED_RECORD_TAG field added during Alma enrichment.
|
163
|
+
# This aids in our handling of "bound with" records.
|
164
|
+
# @param [MARC::Record] record
|
165
|
+
# @return [Array<String>]
|
166
|
+
def host_record_id(record)
|
167
|
+
record.fields(Enriched::Pub::RELATED_RECORD_TAG).filter_map { |field|
|
168
|
+
next unless subfield_value?(field, 'c', /contains/i)
|
169
|
+
|
170
|
+
subfield_values field, :w
|
171
|
+
}.flatten.uniq
|
172
|
+
end
|
173
|
+
|
162
174
|
private
|
163
175
|
|
164
176
|
# Determine if subfield 'a' is an OCLC id.
|