pennmarc 0.0.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/.rubocop_todo.yml +151 -0
- data/Gemfile +1 -1
- data/lib/pennmarc/helpers/creator.rb +47 -13
- data/lib/pennmarc/helpers/database.rb +8 -8
- data/lib/pennmarc/helpers/date.rb +16 -15
- data/lib/pennmarc/helpers/edition.rb +14 -11
- data/lib/pennmarc/helpers/format.rb +16 -5
- data/lib/pennmarc/helpers/genre.rb +12 -11
- data/lib/pennmarc/helpers/identifier.rb +16 -7
- data/lib/pennmarc/helpers/language.rb +1 -1
- data/lib/pennmarc/helpers/link.rb +6 -0
- data/lib/pennmarc/helpers/location.rb +14 -14
- data/lib/pennmarc/helpers/note.rb +52 -2
- data/lib/pennmarc/helpers/relation.rb +9 -9
- data/lib/pennmarc/helpers/series.rb +182 -85
- data/lib/pennmarc/helpers/subject.rb +11 -11
- data/lib/pennmarc/helpers/title.rb +1 -1
- data/lib/pennmarc/parser.rb +2 -99
- data/lib/pennmarc/util.rb +11 -11
- data/pennmarc.gemspec +2 -2
- data/spec/lib/pennmarc/helpers/citation_spec.rb +1 -2
- data/spec/lib/pennmarc/helpers/creator_spec.rb +46 -11
- data/spec/lib/pennmarc/helpers/date_spec.rb +5 -5
- data/spec/lib/pennmarc/helpers/edition_spec.rb +1 -4
- data/spec/lib/pennmarc/helpers/format_spec.rb +29 -9
- data/spec/lib/pennmarc/helpers/genre_spec.rb +3 -3
- data/spec/lib/pennmarc/helpers/identifer_spec.rb +15 -0
- data/spec/lib/pennmarc/helpers/location_spec.rb +9 -8
- data/spec/lib/pennmarc/helpers/note_spec.rb +67 -2
- data/spec/lib/pennmarc/helpers/series_spec.rb +54 -0
- data/spec/lib/pennmarc/helpers/subject_spec.rb +8 -8
- data/spec/lib/pennmarc/helpers/title_spec.rb +3 -1
- data/spec/lib/pennmarc/marc_util_spec.rb +9 -8
- data/spec/lib/pennmarc/parser_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -1
- metadata +7 -17
@@ -19,13 +19,13 @@ module PennMARC
|
|
19
19
|
# @param [MARC::Record] record
|
20
20
|
# @return [Array<String>]
|
21
21
|
def isxn_search(record)
|
22
|
-
record.fields(%w[020 022]).filter_map
|
22
|
+
record.fields(%w[020 022]).filter_map { |field|
|
23
23
|
if field.tag == '020'
|
24
24
|
field.filter_map { |subfield| normalize_isbn(subfield.value) if subfield_in?(%w[a z]).call(subfield) }
|
25
25
|
else
|
26
26
|
field.filter_map { |subfield| subfield.value if subfield_in?(%w[a l z]).call(subfield) }
|
27
27
|
end
|
28
|
-
|
28
|
+
}.flatten.uniq
|
29
29
|
end
|
30
30
|
|
31
31
|
# Get ISBN values for display from the {https://www.oclc.org/bibformats/en/0xx/020.html 020 field}
|
@@ -37,7 +37,7 @@ module PennMARC
|
|
37
37
|
def isbn_show(record)
|
38
38
|
isbn_values = record.fields('020').filter_map do |field|
|
39
39
|
joined_isbn = join_subfields(field, &subfield_in?(%w[a z]))
|
40
|
-
joined_isbn
|
40
|
+
joined_isbn.presence
|
41
41
|
end
|
42
42
|
isbn_values += linked_alternate(record, '020', &subfield_in?(%w[a z]))
|
43
43
|
isbn_values
|
@@ -51,7 +51,7 @@ module PennMARC
|
|
51
51
|
def issn_show(record)
|
52
52
|
issn_values = record.fields('022').filter_map do |field|
|
53
53
|
joined_issn = join_subfields(field, &subfield_in?(%w[a z]))
|
54
|
-
joined_issn
|
54
|
+
joined_issn.presence
|
55
55
|
end
|
56
56
|
issn_values += linked_alternate(record, '022', &subfield_in?(%w[a z]))
|
57
57
|
issn_values
|
@@ -92,21 +92,30 @@ module PennMARC
|
|
92
92
|
def publisher_number_show(record)
|
93
93
|
publisher_numbers = record.fields(%w[024 028]).filter_map do |field|
|
94
94
|
joined_identifiers = join_subfields(field, &subfield_not_in?(%w[5 6]))
|
95
|
-
joined_identifiers
|
95
|
+
joined_identifiers.presence
|
96
96
|
end
|
97
97
|
publisher_numbers += linked_alternate(record, %w[024 028], &subfield_not_in?(%w[5 6]))
|
98
98
|
publisher_numbers
|
99
99
|
end
|
100
100
|
|
101
101
|
# Get publisher issued identifiers for searching of a record. Values extracted from fields
|
102
|
-
# {https://www.oclc.org/bibformats/en/0xx/024.html 024} and {https://www.oclc.org/bibformats/en/0xx/
|
102
|
+
# {https://www.oclc.org/bibformats/en/0xx/024.html 024} and {https://www.oclc.org/bibformats/en/0xx/028.html 028}.
|
103
103
|
#
|
104
104
|
# @param [MARC::Record] record
|
105
105
|
# @return [Array<String>]
|
106
106
|
def publisher_number_search(record)
|
107
107
|
record.fields(%w[024 028]).filter_map do |field|
|
108
108
|
joined_identifiers = join_subfields(field, &subfield_in?(%w[a]))
|
109
|
-
joined_identifiers
|
109
|
+
joined_identifiers.presence
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Retrieve fingerprint for display from the {https://www.oclc.org/bibformats/en/0xx/026.html 026} field
|
114
|
+
# @param [MARC::Record] record
|
115
|
+
# @return [Array<String>]
|
116
|
+
def fingerprint_show(record)
|
117
|
+
record.fields('026').map do |field|
|
118
|
+
join_subfields(field, &subfield_not_in?(%w[2 5 6 8]))
|
110
119
|
end
|
111
120
|
end
|
112
121
|
|
@@ -27,7 +27,7 @@ module PennMARC
|
|
27
27
|
# @param [MARC::Record] record
|
28
28
|
# @param [Hash] mapping hash for language code translation
|
29
29
|
# @return [String] nice value for language
|
30
|
-
def search(record, mapping)
|
30
|
+
def search(record, mapping = language_map)
|
31
31
|
control_field = record['008']&.value
|
32
32
|
language_code = control_field[35..37]
|
33
33
|
mapping[language_code.to_sym || UNDETERMINED_CODE]
|
@@ -4,6 +4,12 @@ module PennMARC
|
|
4
4
|
# Do Link-y stuff
|
5
5
|
class Link < Helper
|
6
6
|
class << self
|
7
|
+
# @todo the legacy code here is a hot mess for a number of reasons, what do we need this field to do?
|
8
|
+
# @note port the needed parts from get_offsite_display, don't return HTML
|
9
|
+
# @param [MARC::Record] record
|
10
|
+
# @return [Object]
|
11
|
+
def offsite(record); end
|
12
|
+
|
7
13
|
def full_text(record:); end
|
8
14
|
|
9
15
|
def web(record:); end
|
@@ -10,10 +10,10 @@ module PennMARC
|
|
10
10
|
# @see https://developers.exlibrisgroup.com/alma/apis/docs/bibs/R0VUIC9hbG1hd3MvdjEvYmlicy97bW1zX2lkfQ==/
|
11
11
|
# Alma documentation for these added fields
|
12
12
|
# @param [MARC::Record] record
|
13
|
-
# @param [Hash]
|
13
|
+
# @param [Hash] location_mapping hash with location_code as key and location hash as value
|
14
14
|
# @return [Array<String>] Array of library locations retrieved from location_map
|
15
|
-
def library(record, location_map)
|
16
|
-
location(record: record,
|
15
|
+
def library(record, location_mapping = location_map)
|
16
|
+
location(record: record, location_mapping: location_mapping, display_value: 'library')
|
17
17
|
end
|
18
18
|
|
19
19
|
# Retrieves the specific location from enriched marc 'itm' or 'hld' fields, giving priority to the item location
|
@@ -23,10 +23,10 @@ module PennMARC
|
|
23
23
|
# @see https://developers.exlibrisgroup.com/alma/apis/docs/bibs/R0VUIC9hbG1hd3MvdjEvYmlicy97bW1zX2lkfQ==/
|
24
24
|
# Alma documentation for these added fields
|
25
25
|
# @param [MARC::Record] record
|
26
|
-
# @param [Hash]
|
26
|
+
# @param [Hash] location_mapping hash with location_code as key and location hash as value
|
27
27
|
# @return [Array<String>] Array of specific locations retrieved from location_map
|
28
|
-
def specific_location(record, location_map)
|
29
|
-
location(record: record,
|
28
|
+
def specific_location(record, location_mapping = location_map)
|
29
|
+
location(record: record, location_mapping: location_mapping, display_value: 'specific_location')
|
30
30
|
end
|
31
31
|
|
32
32
|
# Base method to retrieve location data from enriched marc 'itm' or 'hld' fields, giving priority to the item
|
@@ -35,15 +35,15 @@ module PennMARC
|
|
35
35
|
# @see https://developers.exlibrisgroup.com/alma/apis/docs/bibs/R0VUIC9hbG1hd3MvdjEvYmlicy97bW1zX2lkfQ==/
|
36
36
|
# Alma documentation for these added fields
|
37
37
|
# @param [MARC::Record] record
|
38
|
-
# @param [Hash] location_map hash with location_code as key and location hash as value
|
39
38
|
# @param [Symbol | String] display_value field in location hash to retrieve
|
39
|
+
# @param [Hash] location_mapping hash with location_code as key and location hash as value
|
40
40
|
# @return [Array<String>]
|
41
|
-
def location(record:,
|
41
|
+
def location(record:, display_value:, location_mapping: location_map)
|
42
42
|
# get enriched marc location tag and subfield code
|
43
43
|
location_tag_and_subfield_code(record) => {tag:, subfield_code:}
|
44
44
|
|
45
|
-
locations = record.fields(tag).flat_map
|
46
|
-
field.filter_map
|
45
|
+
locations = record.fields(tag).flat_map { |field|
|
46
|
+
field.filter_map { |subfield|
|
47
47
|
# skip unless subfield code does not match enriched marc tag subfield code
|
48
48
|
next unless subfield.code == subfield_code
|
49
49
|
|
@@ -56,11 +56,11 @@ module PennMARC
|
|
56
56
|
# sometimes "happening locations" are mistakenly used in holdings records.
|
57
57
|
# that's a data problem that should be fixed.
|
58
58
|
# here, if we encounter a code we can't map, we ignore it, for faceting purposes
|
59
|
-
next unless
|
59
|
+
next unless location_mapping.key?(subfield.value.to_sym)
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
location_mapping[subfield.value.to_sym][display_value.to_sym]
|
62
|
+
}.flatten.compact_blank
|
63
|
+
}.uniq
|
64
64
|
locations << 'Online library' if record.fields(PennMARC::EnrichedMarc::TAG_ELECTRONIC_INVENTORY).any?
|
65
65
|
locations
|
66
66
|
end
|
@@ -72,11 +72,11 @@ module PennMARC
|
|
72
72
|
# @param [MARC::Record] record
|
73
73
|
# @return [Array<String>]
|
74
74
|
def contents_show(record)
|
75
|
-
record.fields(%w[505 880]).filter_map
|
75
|
+
record.fields(%w[505 880]).filter_map { |field|
|
76
76
|
next if field.tag == '880' && subfield_value_not_in?(field, '6', %w[505])
|
77
77
|
|
78
78
|
join_subfields(field, &subfield_not_in?(%w[6 8])).split('--')
|
79
|
-
|
79
|
+
}.flatten
|
80
80
|
end
|
81
81
|
|
82
82
|
# Retrieve access restricted notes for display from field {https://www.oclc.org/bibformats/en/5xx/506.html 506}.
|
@@ -127,6 +127,56 @@ module PennMARC
|
|
127
127
|
def summary_show(record)
|
128
128
|
datafield_and_linked_alternate(record, '520')
|
129
129
|
end
|
130
|
+
|
131
|
+
# Retrieve arrangement values for display from field field {https://www.oclc.org/bibformats/en/3xx/351.html 351}.
|
132
|
+
# @param [MARC::Record] record
|
133
|
+
# @return [Array<String>]
|
134
|
+
def arrangement_show(record)
|
135
|
+
datafield_and_linked_alternate(record, '351')
|
136
|
+
end
|
137
|
+
|
138
|
+
# Retrieve system details notes for display from fields {https://www.oclc.org/bibformats/en/5xx/538.html 538},
|
139
|
+
# {https://www.oclc.org/bibformats/en/3xx/344.html 344}, {https://www.oclc.org/bibformats/en/3xx/345.html 345},
|
140
|
+
# {https://www.oclc.org/bibformats/en/3xx/346.html 346}, {https://www.oclc.org/bibformats/en/3xx/347.html 347},
|
141
|
+
# and their linked alternates.
|
142
|
+
# @param [MARC::Record] record
|
143
|
+
# @return [Array<String>]
|
144
|
+
def system_details_show(record)
|
145
|
+
system_details_notes = record.fields(%w[538 880]).filter_map do |field|
|
146
|
+
next if field.tag == '880' && subfield_value_not_in?(field, '6', ['538'])
|
147
|
+
|
148
|
+
sub3_and_other_subs(field, &subfield_in?(%w[a i u]))
|
149
|
+
end
|
150
|
+
system_details_notes += record.fields(%w[344 880]).filter_map do |field|
|
151
|
+
next if field.tag == '880' && subfield_value_not_in?(field, '6', ['344'])
|
152
|
+
|
153
|
+
sub3_and_other_subs(field, &subfield_in?(%w[a b c d e f g h]))
|
154
|
+
end
|
155
|
+
system_details_notes += record.fields(%w[345 346 880]).filter_map do |field|
|
156
|
+
next if field.tag == '880' && subfield_value_not_in?(field, '6', %w[345 346])
|
157
|
+
|
158
|
+
sub3_and_other_subs(field, &subfield_in?(%w[a b]))
|
159
|
+
end
|
160
|
+
system_details_notes += record.fields(%w[347 880]).filter_map do |field|
|
161
|
+
next if field.tag == '880' && subfield_value_not_in?(field, '6', ['347'])
|
162
|
+
|
163
|
+
sub3_and_other_subs(field, &subfield_in?(%w[a b c d e f]))
|
164
|
+
end
|
165
|
+
system_details_notes
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
# For system details: extract subfield ǂ3 plus other subfields as specified by passed-in block. Pays special
|
171
|
+
# attention to punctuation, joining subfield ǂ3 values with a colon-space (': ').
|
172
|
+
# @param [MARC::DataField] field
|
173
|
+
# @param [Proc] selector
|
174
|
+
# @return [String]
|
175
|
+
def sub3_and_other_subs(field, &)
|
176
|
+
sub3 = field.filter_map { |sf| trim_trailing('period', sf.value) if sf.code == '3' }.join(': ')
|
177
|
+
oth_subs = join_subfields(field, &)
|
178
|
+
[sub3, trim_trailing('semicolon', oth_subs)].join(' ')
|
179
|
+
end
|
130
180
|
end
|
131
181
|
end
|
132
182
|
end
|
@@ -46,24 +46,24 @@ module PennMARC
|
|
46
46
|
# Get related work from {RELATED_WORK_FIELDS} in the 7XX range. Require presence of sf t (title) and absence of
|
47
47
|
# an indicator2 value. Prefix returned values with sf i value. Also map relator codes found in sf 4. Ignore sf 0.
|
48
48
|
# @param [MARC::Record] record
|
49
|
-
# @param [Hash]
|
49
|
+
# @param [Hash] relator_mapping
|
50
50
|
# @return [Array]
|
51
|
-
def related_work_show(record, relator_map)
|
51
|
+
def related_work_show(record, relator_mapping = relator_map)
|
52
52
|
values = record.fields(RELATED_WORK_FIELDS).filter_map do |field|
|
53
|
-
next
|
53
|
+
next if field.indicator2.present?
|
54
54
|
|
55
55
|
next unless subfield_defined?(field, 't')
|
56
56
|
|
57
|
-
values_with_title_prefix(field, sf_exclude: %w[0 4 6 8 i], relator_map:
|
57
|
+
values_with_title_prefix(field, sf_exclude: %w[0 4 6 8 i], relator_map: relator_mapping)
|
58
58
|
end
|
59
59
|
values + record.fields('880').filter_map do |field|
|
60
|
-
next
|
60
|
+
next if field.indicator2.present?
|
61
61
|
|
62
62
|
next unless subfield_value?(field, '6', /^(#{RELATED_WORK_FIELDS.join('|')})/)
|
63
63
|
|
64
64
|
next unless subfield_defined?(field, 't')
|
65
65
|
|
66
|
-
values_with_title_prefix(field, sf_exclude: %w[0 4 6 8 i], relator_map:
|
66
|
+
values_with_title_prefix(field, sf_exclude: %w[0 4 6 8 i], relator_map: relator_mapping)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -71,13 +71,13 @@ module PennMARC
|
|
71
71
|
# "Analytical Entry" meaning that the record is contained by the matching field. Map relator codes in sf 4. Ignore
|
72
72
|
# values in sf 0, 5, 6, and 8.
|
73
73
|
# @param [MARC::Record] record
|
74
|
-
# @param [Hash]
|
74
|
+
# @param [Hash] relator_mapping
|
75
75
|
# @return [Array]
|
76
|
-
def contains_show(record, relator_map)
|
76
|
+
def contains_show(record, relator_mapping = relator_map)
|
77
77
|
acc = record.fields(CONTAINS_FIELDS).filter_map do |field|
|
78
78
|
next unless field.indicator2 == '2'
|
79
79
|
|
80
|
-
values_with_title_prefix(field, sf_exclude: %w[0 4 5 6 8 i], relator_map:
|
80
|
+
values_with_title_prefix(field, sf_exclude: %w[0 4 5 6 8 i], relator_map: relator_mapping)
|
81
81
|
end
|
82
82
|
acc + record.fields('880').filter_map do |field|
|
83
83
|
next unless field.indicator2 == '2'
|
@@ -1,116 +1,213 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module PennMARC
|
4
|
-
# Do Series-
|
4
|
+
# Do Series and series-related field processing. Many of these fields are added entries that are justified by
|
5
|
+
# corresponding series statements (usually 490). These fields provide information about the published series in which
|
6
|
+
# a book, encoded finding aid, or other published work has appeared
|
7
|
+
# @todo We may want to include 410 in the display tags, since it is included in references below.
|
5
8
|
class Series < Helper
|
6
9
|
class << self
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
if %w[e w v n t].member?(sf.code)
|
18
|
-
[' ', sf.value]
|
19
|
-
elsif sf.code == '4'
|
20
|
-
[', ', relator_codes[sf.value]]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
series_append = pairs.flatten.join.strip
|
24
|
-
acc << { value: series, value_append: series_append, link_type: 'author_search' }
|
25
|
-
end
|
26
|
-
elsif %w[830 440 490].member?(tags_present.first)
|
27
|
-
record.fields(tags_present.first).each do |field|
|
28
|
-
# added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
29
|
-
series = join_subfields(field, &subfield_not_in(%w[0 5 6 8 c e w v n]))
|
30
|
-
series_append = join_subfields(field, &subfield_in(%w[c e w v n]))
|
31
|
-
acc << { value: series, value_append: series_append, link_type: 'title_search' }
|
32
|
-
end
|
33
|
-
end
|
10
|
+
# 800 - Series Added Entry-Personal Name - https://www.loc.gov/marc/bibliographic/bd800.html
|
11
|
+
# 810 - Series Added Entry-Corporate Name - https://www.loc.gov/marc/bibliographic/bd810.html
|
12
|
+
# 410 - Series Statement/Added Entry-Corporate Name - https://www.loc.gov/marc/bibliographic/bd410.html
|
13
|
+
# 811 - Series Added Entry-Meeting Name - https://www.loc.gov/marc/bibliographic/bd811.html
|
14
|
+
# 830 - Series Added Entry-Uniform Title - https://www.loc.gov/marc/bibliographic/bd830.html
|
15
|
+
# 400 - Series Statement/Added Entry-Personal Name - https://www.loc.gov/marc/bibliographic/bd400.html
|
16
|
+
# 411 - Series Statement/Added Entry Meeting Name - https://www.loc.gov/marc/bibliographic/bd411.html
|
17
|
+
# 440 - Series Statement/Added Entry-Title - https://www.loc.gov/marc/bibliographic/bd440.html
|
18
|
+
# 490 - Series Statement - https://www.loc.gov/marc/bibliographic/bd490.html
|
19
|
+
DISPLAY_TAGS = %w[800 810 811 830 400 411 440 490].freeze
|
34
20
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
21
|
+
# Fields for display that pertain to series information.
|
22
|
+
# @param [MARC::Record] record
|
23
|
+
# @param [Hash] relator_mapping
|
24
|
+
# @return [Array<String>] array of series information
|
25
|
+
def show(record, relator_mapping = relator_map)
|
26
|
+
tags_present = DISPLAY_TAGS.select { |tag| record[tag].present? }
|
40
27
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
28
|
+
values = if %w[800 810 811 400 410 411].member?(tags_present.first)
|
29
|
+
author_show_entries(record, tags_present.first, relator_mapping)
|
30
|
+
elsif %w[830 440 490].member?(tags_present.first)
|
31
|
+
title_show_entries(record, tags_present.first)
|
32
|
+
end || []
|
47
33
|
|
48
|
-
|
34
|
+
values += remaining_show_entries(record, tags_present)
|
35
|
+
values + series_880_fields(record)
|
49
36
|
end
|
50
37
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|
63
|
-
acc
|
38
|
+
# Values from series fields for display.
|
39
|
+
# @param [MARC::Record] record
|
40
|
+
# @param [Hash] relator_mapping
|
41
|
+
# @return [Array<String>] array of series values
|
42
|
+
def values(record, relator_mapping = relator_map)
|
43
|
+
series_8x = record.fields(%w[800 810 811 830]).first
|
44
|
+
return Array.wrap(series_8xx_field(series_8x, relator_mapping)) if series_8x
|
45
|
+
|
46
|
+
series_4x = record.fields(%w[400 410 411 440 490]).first
|
47
|
+
return Array.wrap(series_4xx_field(series_4x, relator_mapping)) if series_4x
|
64
48
|
end
|
65
49
|
|
50
|
+
# Series fields for search.
|
51
|
+
# @param [MARC::Record] record
|
52
|
+
# @return [Array<String>] array of series values
|
66
53
|
def search(record)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
54
|
+
values = record.fields(%w[400 410 411]).filter_map do |field|
|
55
|
+
subfields = if field.indicator2 != '0'
|
56
|
+
%w[4 6 8]
|
57
|
+
elsif field.indicator2 != '1'
|
58
|
+
%w[4 6 8 a]
|
59
|
+
else
|
60
|
+
next
|
61
|
+
end
|
62
|
+
join_subfields(field, &subfield_not_in?(subfields))
|
71
63
|
end
|
72
|
-
|
73
|
-
|
74
|
-
.map do |field|
|
75
|
-
join_subfields(field, &subfield_not_in(%w[4 6 8 a]))
|
64
|
+
values += record.fields(%w[440]).filter_map do |field|
|
65
|
+
join_subfields(field, &subfield_not_in?(%w[0 5 6 8 w]))
|
76
66
|
end
|
77
|
-
|
78
|
-
|
79
|
-
join_subfields(field, &subfield_not_in(%w[0 5 6 8 w]))
|
67
|
+
values += record.fields(%w[800 810 811]).filter_map do |field|
|
68
|
+
join_subfields(field, &subfield_not_in?(%w[0 4 5 6 7 8 w]))
|
80
69
|
end
|
81
|
-
|
82
|
-
|
83
|
-
join_subfields(field, &subfield_not_in(%w[0 4 5 6 7 8 w]))
|
70
|
+
values += record.fields(%w[830]).filter_map do |field|
|
71
|
+
join_subfields(field, &subfield_not_in?(%w[0 5 6 7 8 w]))
|
84
72
|
end
|
85
|
-
|
86
|
-
|
73
|
+
values += record.fields(%w[533]).filter_map do |field|
|
74
|
+
filtered_values = field.filter_map { |sf| sf.value if sf.code == 'f' }
|
75
|
+
next if filtered_values.empty?
|
76
|
+
|
77
|
+
filtered_values.map { |v| v.gsub(/\(|\)/, '') }.join(' ')
|
87
78
|
end
|
88
|
-
|
89
|
-
.map do |field|
|
90
|
-
field.find_all { |sf| sf.code == 'f' }
|
91
|
-
.map(&:value)
|
92
|
-
.map { |v| v.gsub(/\(|\)/, '') }
|
93
|
-
.join(' ')
|
94
|
-
end
|
79
|
+
values
|
95
80
|
end
|
96
81
|
|
82
|
+
# Information concerning the immediate predecessor of the target item (chronological relationship). When a note
|
83
|
+
# is generated from this field, the introductory term or phrase may be generated based on the value in the second
|
84
|
+
# indicator position for display.
|
85
|
+
# https://www.loc.gov/marc/bibliographic/bd780.html
|
86
|
+
# @param [MARC::Record] record
|
87
|
+
# @return [String] continues fields string
|
97
88
|
def get_continues_display(record)
|
98
|
-
|
89
|
+
continues(record, '780')
|
99
90
|
end
|
100
91
|
|
92
|
+
# Information concerning the immediate successor to the target item (chronological relationship). When a note is
|
93
|
+
# generated from this field, the introductory phrase may be generated based on the value in the second indicator
|
94
|
+
# position for display.
|
95
|
+
# https://www.loc.gov/marc/bibliographic/bd785.html
|
96
|
+
# @param [MARC::Record] record
|
97
|
+
# @return [String] continued by fields string
|
101
98
|
def get_continued_by_display(record)
|
102
|
-
|
99
|
+
continues(record, '785')
|
103
100
|
end
|
104
101
|
|
105
102
|
private
|
106
103
|
|
107
|
-
#
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
104
|
+
# If any of these values: 800 810 811 400 410 411 are present, return a string with series information and
|
105
|
+
# appended values.
|
106
|
+
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
107
|
+
# @param [MARC::Record] record
|
108
|
+
# @param [String] first_tag
|
109
|
+
# @param [Hash] relator_mapping
|
110
|
+
# @return [Array<Hash>] array of author show entry hashes
|
111
|
+
def author_show_entries(record, first_tag, relator_mapping)
|
112
|
+
record.fields(first_tag).map do |field|
|
113
|
+
series = join_subfields(field, &subfield_not_in?(%w[0 5 6 8 e t w v n]))
|
114
|
+
pairs = field.map do |sf|
|
115
|
+
if %w[e w v n t].member?(sf.code)
|
116
|
+
[' ', sf.value]
|
117
|
+
elsif sf.code == '4'
|
118
|
+
[', ', translate_relator(sf.value, relator_mapping)]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
series_append = pairs.flatten.join.strip
|
122
|
+
"#{series} #{series_append}".squish
|
123
|
+
end || []
|
124
|
+
end
|
125
|
+
|
126
|
+
# If any of these values: 830 440 490 are present, return a string with series information and appended values.
|
127
|
+
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
128
|
+
# @param [MARC::Record] record
|
129
|
+
# @param [String] first_tag
|
130
|
+
# @return [Array<Hash>] array of author show entry hashes
|
131
|
+
def title_show_entries(record, first_tag)
|
132
|
+
record.fields(first_tag).map do |field|
|
133
|
+
series = join_subfields(field, &subfield_not_in?(%w[0 5 6 8 c e w v n]))
|
134
|
+
series_append = join_subfields(field, &subfield_in?(%w[c e w v n]))
|
135
|
+
"#{series} #{series_append}".squish
|
136
|
+
end || []
|
137
|
+
end
|
138
|
+
|
139
|
+
# Assemble an array of hashes that includes the remaining show entries.
|
140
|
+
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
141
|
+
# @param [MARC::Record] record
|
142
|
+
# @param [Array<String>] tags_present
|
143
|
+
# @return [Array<Hash>] array of remaining show entry hashes
|
144
|
+
def remaining_show_entries(record, tags_present)
|
145
|
+
record.fields(tags_present.drop(1)).map do |field|
|
146
|
+
join_subfields(field, &subfield_not_in?(%w[0 5 6 8]))
|
147
|
+
end || []
|
148
|
+
end
|
149
|
+
|
150
|
+
# TODO: use linked alternate in place of this function
|
151
|
+
# @note There are multiple locations in these helpers where we should be able to use the linked_alternate util.
|
152
|
+
# @note This requires a more comprehensive evaluation and refactor of the linked_alternate utility.
|
153
|
+
#
|
154
|
+
# Fully content-designated representation, in a different script, of another field in the same record. Field 880
|
155
|
+
# is linked to the associated regular field by subfield $6 (Linkage). A subfield $6 in the associated field also
|
156
|
+
# links that field to the 880 field. The data in field 880 may be in more than one script. This function exists
|
157
|
+
# because it differs than the tradition use of linked_alternate.
|
158
|
+
# @param [MARC::Record] record
|
159
|
+
def series_880_fields(record)
|
160
|
+
record.fields('880').filter_map do |field|
|
161
|
+
next unless subfield_value?(field, '6', /^(800|810|811|830|400|410|411|440|490)/)
|
162
|
+
|
163
|
+
join_subfields(field, &subfield_not_in?(%w[5 6 8]))
|
164
|
+
end || []
|
165
|
+
end
|
166
|
+
|
167
|
+
# Assemble a formatted string of a given 8xx field.
|
168
|
+
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
169
|
+
# @param [String] field
|
170
|
+
# @param [Hash] relator_mapping
|
171
|
+
# @return [String] series 8xx field
|
172
|
+
def series_8xx_field(field, relator_mapping)
|
173
|
+
s = field.filter_map { |sf|
|
174
|
+
if %w[0 4 5 6 8].exclude?(sf.code)
|
175
|
+
" #{sf.value}"
|
176
|
+
elsif sf.code == '4'
|
177
|
+
", #{translate_relator(sf.value, relator_mapping)}"
|
178
|
+
end
|
179
|
+
}.join
|
180
|
+
s2 = s + (%w[. -].exclude?(s[-1]) ? '.' : '')
|
181
|
+
s2.squish
|
182
|
+
end
|
183
|
+
|
184
|
+
# Assemble a formatted string of a given 4xx field.
|
185
|
+
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
186
|
+
# @param [String] field
|
187
|
+
# @param [Hash] relator_mapping
|
188
|
+
# @return [String] series 4xx field
|
189
|
+
def series_4xx_field(field, relator_mapping)
|
190
|
+
s = field.filter_map { |sf|
|
191
|
+
if %w[0 4 6 8].exclude?(sf.code)
|
192
|
+
" #{sf.value}"
|
193
|
+
elsif sf.code == '4'
|
194
|
+
", #{translate_relator(sf.value, relator_mapping)}"
|
195
|
+
end
|
196
|
+
}.join
|
197
|
+
s2 = s + (%w[. -].exclude?(s[-1]) ? '.' : '')
|
198
|
+
s2.squish
|
199
|
+
end
|
200
|
+
|
201
|
+
# Get subfields from a given field (continues or continued_by).
|
202
|
+
# @param [MARC::Record] record
|
203
|
+
# @param [String] tag
|
204
|
+
# @return [String] joined subfields
|
205
|
+
def continues(record, tag)
|
206
|
+
record.fields.filter_map do |field|
|
207
|
+
next unless field.tag == tag || (field.tag == '880' && subfield_value?(field, '6', /^#{tag}/))
|
208
|
+
next unless field.any?(&subfield_in?(%w[i a s t n d]))
|
209
|
+
|
210
|
+
join_subfields(field, &subfield_in?(%w[i a s t n d]))
|
114
211
|
end
|
115
212
|
end
|
116
213
|
end
|