pennmarc 1.0.0 → 1.0.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 +11 -19
- data/README.md +12 -2
- data/lib/pennmarc/helpers/creator.rb +24 -20
- data/lib/pennmarc/helpers/edition.rb +15 -13
- data/lib/pennmarc/helpers/format.rb +3 -3
- data/lib/pennmarc/helpers/genre.rb +5 -4
- data/lib/pennmarc/helpers/helper.rb +1 -0
- data/lib/pennmarc/helpers/language.rb +3 -3
- data/lib/pennmarc/helpers/location.rb +10 -10
- data/lib/pennmarc/helpers/relation.rb +7 -7
- data/lib/pennmarc/helpers/series.rb +18 -29
- data/lib/pennmarc/helpers/subject.rb +9 -10
- data/lib/pennmarc/mappers.rb +31 -0
- data/lib/pennmarc/parser.rb +36 -62
- data/lib/pennmarc/util.rb +10 -11
- data/pennmarc.gemspec +1 -1
- data/spec/lib/pennmarc/helpers/creator_spec.rb +9 -9
- data/spec/lib/pennmarc/helpers/edition_spec.rb +3 -2
- data/spec/lib/pennmarc/helpers/format_spec.rb +1 -1
- data/spec/lib/pennmarc/helpers/genre_spec.rb +1 -1
- data/spec/lib/pennmarc/helpers/language_spec.rb +1 -1
- data/spec/lib/pennmarc/helpers/location_spec.rb +8 -8
- data/spec/lib/pennmarc/helpers/relation_spec.rb +2 -2
- data/spec/lib/pennmarc/helpers/series_spec.rb +2 -2
- data/spec/lib/pennmarc/helpers/subject_spec.rb +1 -1
- data/spec/lib/pennmarc/parser_spec.rb +22 -1
- metadata +3 -5
- data/legacy/indexer.rb +0 -568
- data/legacy/marc.rb +0 -2964
- data/legacy/test_file_output.json +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e574f1fae4f59435df3bf467da310ae7e426d82c2fe54ae2321ad326c05e5e99
|
4
|
+
data.tar.gz: de545e5a150b26c73e814e36b167bb688d267a97205cf4cdbab15dfd5c3225a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c3fc981f5999eaca710a54fa3d247f2d01cc8183e13212151afab0cbb5b37f93531cbd264b22d1d4f30ef730b800efe38039b4bfc42a44cd28778c06f0cde3f
|
7
|
+
data.tar.gz: 729f0f80fd9d9ade7d1ae1085610cd85b8ab31beb1245efcaee246a18c01238abd5adc18dcf995f624448d518f4e36222a71c972d00c537c6367229f7d8d35c6
|
data/.rubocop_todo.yml
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 10000`
|
3
|
-
# on 2023-
|
3
|
+
# on 2023-08-14 17:52:48 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
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count:
|
9
|
+
# Offense count: 22
|
10
10
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
11
11
|
Metrics/AbcSize:
|
12
12
|
Exclude:
|
@@ -50,7 +50,7 @@ Metrics/CyclomaticComplexity:
|
|
50
50
|
- 'lib/pennmarc/helpers/title.rb'
|
51
51
|
- 'lib/pennmarc/util.rb'
|
52
52
|
|
53
|
-
# Offense count:
|
53
|
+
# Offense count: 24
|
54
54
|
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
|
55
55
|
Metrics/MethodLength:
|
56
56
|
Exclude:
|
@@ -86,6 +86,14 @@ Metrics/PerceivedComplexity:
|
|
86
86
|
- 'lib/pennmarc/helpers/title.rb'
|
87
87
|
- 'lib/pennmarc/util.rb'
|
88
88
|
|
89
|
+
# Offense count: 2
|
90
|
+
# This cop supports safe autocorrection (--autocorrect).
|
91
|
+
# Configuration parameters: EnforcedStyle, BlockForwardingName.
|
92
|
+
# SupportedStyles: anonymous, explicit
|
93
|
+
Naming/BlockForwarding:
|
94
|
+
Exclude:
|
95
|
+
- 'lib/pennmarc/util.rb'
|
96
|
+
|
89
97
|
# Offense count: 1
|
90
98
|
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
|
91
99
|
# NamePrefix: is_, has_, have_
|
@@ -104,14 +112,6 @@ Naming/VariableNumber:
|
|
104
112
|
Exclude:
|
105
113
|
- 'lib/pennmarc/util.rb'
|
106
114
|
|
107
|
-
# Offense count: 7
|
108
|
-
# Configuration parameters: MinSize.
|
109
|
-
Performance/CollectionLiteralInLoop:
|
110
|
-
Exclude:
|
111
|
-
- 'lib/pennmarc/helpers/creator.rb'
|
112
|
-
- 'lib/pennmarc/helpers/edition.rb'
|
113
|
-
- 'lib/pennmarc/helpers/series.rb'
|
114
|
-
|
115
115
|
# Offense count: 6
|
116
116
|
# Configuration parameters: Max, CountAsOne.
|
117
117
|
RSpec/ExampleLength:
|
@@ -141,11 +141,3 @@ RSpec/NestedGroups:
|
|
141
141
|
Rails/Output:
|
142
142
|
Exclude:
|
143
143
|
- 'lib/pennmarc/helpers/date.rb'
|
144
|
-
|
145
|
-
# Offense count: 1
|
146
|
-
# This cop supports safe autocorrection (--autocorrect).
|
147
|
-
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
|
148
|
-
# URISchemes: http, https
|
149
|
-
Layout/LineLength:
|
150
|
-
Exclude:
|
151
|
-
- 'lib/pennmarc/helpers/subject.rb'
|
data/README.md
CHANGED
@@ -53,6 +53,12 @@ To run rubocop with the configuration:
|
|
53
53
|
rubocop
|
54
54
|
```
|
55
55
|
|
56
|
+
#### To regenerate `.rubocop_todo.yml`:
|
57
|
+
```shell
|
58
|
+
bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 10000
|
59
|
+
```
|
60
|
+
|
61
|
+
|
56
62
|
### Testing
|
57
63
|
|
58
64
|
Testing is done with `rspec`. Test coverage should approach 100% given the relative simplicity of this gem.
|
@@ -63,6 +69,12 @@ To run the test suite:
|
|
63
69
|
rspec
|
64
70
|
```
|
65
71
|
|
72
|
+
## Publishing the Gem
|
73
|
+
|
74
|
+
1. Update the version in `pennmarc.gemspec`
|
75
|
+
2. Run `gem build pennmarc.gemspec` with the latest code
|
76
|
+
3. Run `gem push pennmarc-{version number here}`(e.g. `gem push pennmarc-1.0.0`) to push to RubyGems. You will need access and MFA setup with RubyGems.
|
77
|
+
|
66
78
|
## QA
|
67
79
|
|
68
80
|
### Checking output of an arbitrary MARC XML file
|
@@ -75,8 +87,6 @@ MARC_FILE=path/to/marc.xml bundle exec rake pennmarc:parse
|
|
75
87
|
|
76
88
|
## TODO
|
77
89
|
- rake task or some similar command to return a full set of values extracted from a specified marcxml file
|
78
|
-
- hosting of yard output files?
|
79
|
-
- mappings (locations, call number, languages)
|
80
90
|
- Pipeline to run tests and publish to Rubygems
|
81
91
|
- rubocop check
|
82
92
|
- rdoc/yard coverage checks?
|
@@ -24,17 +24,18 @@ module PennMARC
|
|
24
24
|
# indicator1 tell us the order of the name?
|
25
25
|
# @note ported from get_author_creator_1_search_values
|
26
26
|
# @param [MARC::Record] record
|
27
|
-
# @param [Hash]
|
27
|
+
# @param [Hash] relator_map
|
28
28
|
# @return [Array<String>] array of author/creator values for indexing
|
29
|
-
def search(record,
|
29
|
+
def search(record, relator_map: Mappers.relator)
|
30
|
+
creator_subfields = %w[a 1 4 6 8]
|
30
31
|
acc = record.fields(TAGS).map do |field|
|
31
32
|
pieces = field.filter_map do |sf|
|
32
33
|
if sf.code == 'a'
|
33
34
|
convert_name_order(sf.value)
|
34
|
-
elsif
|
35
|
+
elsif creator_subfields.exclude?(sf.code)
|
35
36
|
sf.value
|
36
37
|
elsif sf.code == '4'
|
37
|
-
relator = translate_relator(sf.value,
|
38
|
+
relator = translate_relator(sf.value, relator_map)
|
38
39
|
next if relator.blank?
|
39
40
|
|
40
41
|
relator
|
@@ -48,12 +49,13 @@ module PennMARC
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
# a second iteration over the same fields produces name entries with the names not reordered
|
52
|
+
secondary_subfields = %w[4 6 8]
|
51
53
|
acc += record.fields(TAGS).map do |field|
|
52
54
|
pieces = field.filter_map do |sf|
|
53
|
-
if
|
55
|
+
if secondary_subfields.exclude?(sf.code)
|
54
56
|
sf.value
|
55
57
|
elsif sf.code == '4'
|
56
|
-
relator = translate_relator(sf.value,
|
58
|
+
relator = translate_relator(sf.value, relator_map)
|
57
59
|
next if relator.blank?
|
58
60
|
|
59
61
|
relator
|
@@ -88,11 +90,11 @@ module PennMARC
|
|
88
90
|
# All author/creator values for display (like #show, but multivalued?) - no 880 linkage
|
89
91
|
# @note ported from get_author_creator_values (indexed as author_creator_a) - shown on results page
|
90
92
|
# @param [MARC::Record] record
|
91
|
-
# @param [Hash]
|
93
|
+
# @param [Hash] relator_map
|
92
94
|
# @return [Array<String>] array of author/creator values for display
|
93
|
-
def values(record,
|
95
|
+
def values(record, relator_map: Mappers.relator)
|
94
96
|
record.fields(TAGS).map do |field|
|
95
|
-
name_from_main_entry(field,
|
97
|
+
name_from_main_entry(field, relator_map)
|
96
98
|
end
|
97
99
|
end
|
98
100
|
|
@@ -109,8 +111,7 @@ module PennMARC
|
|
109
111
|
end
|
110
112
|
end
|
111
113
|
|
112
|
-
# Author/Creator sort. Does not map and include any relator
|
113
|
-
# codes.
|
114
|
+
# Author/Creator sort. Does not map and include any relator codes.
|
114
115
|
# @todo This includes any URI from ǂ0 which could help to disambiguate in sorts, but ǂ1 is excluded...
|
115
116
|
# @note ported from get_author_creator_sort_values
|
116
117
|
# @param [MARC::Record] record
|
@@ -143,11 +144,11 @@ module PennMARC
|
|
143
144
|
# Conference for display, intended for results display
|
144
145
|
# @note ported from get_conference_values
|
145
146
|
# @param [MARC::Record] record
|
146
|
-
# @param [Hash]
|
147
|
+
# @param [Hash] relator_map
|
147
148
|
# @return [Array<String>] array of conference values
|
148
|
-
def conference_show(record,
|
149
|
+
def conference_show(record, relator_map: Mappers.relator)
|
149
150
|
record.fields('111').filter_map do |field|
|
150
|
-
name_from_main_entry field,
|
151
|
+
name_from_main_entry field, relator_map
|
151
152
|
end
|
152
153
|
end
|
153
154
|
|
@@ -188,19 +189,21 @@ module PennMARC
|
|
188
189
|
# 'a', 'b', 'c', 'd', 'j', and 'q'. Then appends resulting string with joined subfields 'e', 'u', '3', and '4'.
|
189
190
|
# @note legacy version returns array of hash objects including data for display link
|
190
191
|
# @param [MARC::Record] record
|
191
|
-
# @ param [Hash]
|
192
|
+
# @ param [Hash] relator_map
|
192
193
|
# @return [Array<String>]
|
193
|
-
def contributor_show(record,
|
194
|
+
def contributor_show(record, relator_map: Mappers.relator)
|
195
|
+
indicator_2_options = ['', ' ', '0']
|
194
196
|
contributors = record.fields(%w[700 710]).filter_map do |field|
|
195
|
-
next unless
|
197
|
+
next unless indicator_2_options.member?(field.indicator2)
|
196
198
|
next if subfield_defined? field, 'i'
|
197
199
|
|
198
200
|
contributor = join_subfields(field, &subfield_in?(%w[a b c d j q]))
|
201
|
+
contributor_append_subfields = %w[e u 3 4]
|
199
202
|
contributor_append = field.filter_map { |subfield|
|
200
|
-
next unless
|
203
|
+
next unless contributor_append_subfields.member?(subfield.code)
|
201
204
|
|
202
205
|
if subfield.code == '4'
|
203
|
-
", #{translate_relator(subfield.value,
|
206
|
+
", #{translate_relator(subfield.value, relator_map)}"
|
204
207
|
else
|
205
208
|
" #{subfield.value}"
|
206
209
|
end
|
@@ -243,8 +246,9 @@ module PennMARC
|
|
243
246
|
# @param [MARC::Field] field
|
244
247
|
# @return [String] joined subfield values for value from field
|
245
248
|
def name_from_main_entry(field, mapping)
|
249
|
+
name_subfields = %w[0 1 4 6 8]
|
246
250
|
s = field.filter_map { |sf|
|
247
|
-
if
|
251
|
+
if name_subfields.exclude?(sf.code)
|
248
252
|
" #{sf.value}"
|
249
253
|
elsif sf.code == '4'
|
250
254
|
relator = translate_relator(sf.value, mapping)
|
@@ -34,47 +34,49 @@ module PennMARC
|
|
34
34
|
# display.
|
35
35
|
# https://www.loc.gov/marc/bibliographic/bd775.html
|
36
36
|
# @param [MARC::Record] record
|
37
|
-
# @param [Hash]
|
37
|
+
# @param [Hash] relator_map
|
38
38
|
# @return [Array<String>] array of other edition strings
|
39
|
-
def other_show(record,
|
39
|
+
def other_show(record, relator_map: Mappers.relator)
|
40
40
|
values = record.fields('775').filter_map do |field|
|
41
41
|
next unless subfield_defined?(field, :i)
|
42
42
|
|
43
|
-
other_edition_value(field,
|
43
|
+
other_edition_value(field, relator_map)
|
44
44
|
end
|
45
|
-
values
|
45
|
+
values + record.fields('880').filter_map do |field|
|
46
46
|
next unless field.indicator2.blank? && subfield_value_in?(field, '6', %w[775]) &&
|
47
47
|
subfield_defined?(field, 'i')
|
48
48
|
|
49
|
-
other_edition_value(field,
|
49
|
+
other_edition_value(field, relator_map)
|
50
50
|
end
|
51
|
-
values
|
52
51
|
end
|
53
52
|
|
54
53
|
private
|
55
54
|
|
56
55
|
# Assemble a string of relevant edition information.
|
57
56
|
# @param [MARC::DataField] field
|
58
|
-
# @param [Hash]
|
57
|
+
# @param [Hash] relator_map
|
59
58
|
# @return [String (frozen)] assembled other version string
|
60
|
-
def other_edition_value(field,
|
59
|
+
def other_edition_value(field, relator_map)
|
61
60
|
subi = remove_paren_value_from_subfield_i(field) || ''
|
61
|
+
excluded_subfields = %w[6 8]
|
62
|
+
other_edition_subfields = %w[s x z]
|
62
63
|
other_editions = field.filter_map { |sf|
|
63
|
-
next if
|
64
|
+
next if excluded_subfields.member?(sf.code)
|
64
65
|
|
65
|
-
if
|
66
|
+
if other_edition_subfields.member?(sf.code)
|
66
67
|
" #{sf.value}"
|
67
68
|
elsif sf.code == 't'
|
68
|
-
relator = translate_relator(sf.value,
|
69
|
+
relator = translate_relator(sf.value, relator_map)
|
69
70
|
next if relator.blank?
|
70
71
|
|
71
72
|
" #{relator}. "
|
72
73
|
end
|
73
74
|
}.join
|
75
|
+
other_editions_append_subfields = %w[i h s t x z e f o r w y 7]
|
74
76
|
other_editions_append = field.filter_map { |sf|
|
75
|
-
next if
|
77
|
+
next if excluded_subfields.member?(sf.code)
|
76
78
|
|
77
|
-
if
|
79
|
+
if other_editions_append_subfields.exclude?(sf.code)
|
78
80
|
" #{sf.value}"
|
79
81
|
elsif sf.code == 'h'
|
80
82
|
" (#{sf.value}) "
|
@@ -68,10 +68,10 @@ module PennMARC
|
|
68
68
|
# for this helper method
|
69
69
|
# @note ported from get_format
|
70
70
|
# @param [MARC::Record] record
|
71
|
-
# @param [Hash]
|
71
|
+
# @param [Hash] location_map
|
72
72
|
# @return [Array<String>] format values for faceting
|
73
73
|
|
74
|
-
def facet(record,
|
74
|
+
def facet(record, location_map: Mappers.location)
|
75
75
|
formats = []
|
76
76
|
format_code = leader_format(record.leader)
|
77
77
|
f007 = record.fields('007').map(&:value)
|
@@ -88,7 +88,7 @@ module PennMARC
|
|
88
88
|
end
|
89
89
|
|
90
90
|
# get all specific_location values from inventory info
|
91
|
-
locations = Location.location record: record,
|
91
|
+
locations = Location.location record: record, location_map: location_map,
|
92
92
|
display_value: :specific_location
|
93
93
|
|
94
94
|
if include_manuscripts?(locations)
|
@@ -34,8 +34,9 @@ module PennMARC
|
|
34
34
|
|
35
35
|
next if field.tag == '880' && subfield_values(field, '6').exclude?('655')
|
36
36
|
|
37
|
+
subfields = %w[a b]
|
37
38
|
sub_with_hyphens = field.find_all(&subfield_not_in?(%w[0 2 5 6 8 c e w])).map { |sf|
|
38
|
-
sep =
|
39
|
+
sep = subfields.exclude?(sf.code) ? ' -- ' : ' '
|
39
40
|
sep + sf.value
|
40
41
|
}.join.lstrip
|
41
42
|
"#{sub_with_hyphens} #{field.find_all(&subfield_in?(%w[e w])).join(' -- ')}".strip
|
@@ -46,10 +47,10 @@ module PennMARC
|
|
46
47
|
# @todo the Genre facet in Franklin is pretty ugly. It could be cleaned up by limiting the subfields included
|
47
48
|
# here and cleaning up punctuation.
|
48
49
|
# @param [MARC::Record] record
|
49
|
-
# @param [Hash]
|
50
|
+
# @param [Hash] location_map
|
50
51
|
# @return [Array<String>]
|
51
|
-
def facet(record,
|
52
|
-
locations = Location.location record: record,
|
52
|
+
def facet(record, location_map: Mappers.location)
|
53
|
+
locations = Location.location record: record, location_map: location_map,
|
53
54
|
display_value: :specific_location
|
54
55
|
manuscript = Format.include_manuscripts?(locations)
|
55
56
|
video = record.fields('007').any? { |field| field.value.starts_with? 'v' }
|
@@ -25,12 +25,12 @@ module PennMARC
|
|
25
25
|
# the 008 control field. Language facet and search values will typically be the same.
|
26
26
|
#
|
27
27
|
# @param [MARC::Record] record
|
28
|
-
# @param [Hash]
|
28
|
+
# @param [Hash] language_map hash for language code translation
|
29
29
|
# @return [String] nice value for language
|
30
|
-
def search(record,
|
30
|
+
def search(record, language_map: Mappers.language)
|
31
31
|
control_field = record['008']&.value
|
32
32
|
language_code = control_field[35..37]
|
33
|
-
|
33
|
+
language_map[language_code.to_sym || UNDETERMINED_CODE]
|
34
34
|
end
|
35
35
|
end
|
36
36
|
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_map 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,
|
16
|
-
location(record: record,
|
15
|
+
def library(record, location_map: Mappers.location)
|
16
|
+
location(record: record, location_map: location_map, 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_map 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,
|
29
|
-
location(record: record,
|
28
|
+
def specific_location(record, location_map: Mappers.location)
|
29
|
+
location(record: record, location_map: location_map, 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
|
@@ -36,9 +36,9 @@ module PennMARC
|
|
36
36
|
# Alma documentation for these added fields
|
37
37
|
# @param [MARC::Record] record
|
38
38
|
# @param [Symbol | String] display_value field in location hash to retrieve
|
39
|
-
# @param [Hash]
|
39
|
+
# @param [Hash] location_map hash with location_code as key and location hash as value
|
40
40
|
# @return [Array<String>]
|
41
|
-
def location(record:, display_value:,
|
41
|
+
def location(record:, display_value:, 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
|
|
@@ -56,9 +56,9 @@ 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_map.key?(subfield.value.to_sym)
|
60
60
|
|
61
|
-
|
61
|
+
location_map[subfield.value.to_sym][display_value.to_sym]
|
62
62
|
}.flatten.compact_blank
|
63
63
|
}.uniq
|
64
64
|
locations << 'Online library' if record.fields(PennMARC::EnrichedMarc::TAG_ELECTRONIC_INVENTORY).any?
|
@@ -46,15 +46,15 @@ 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_map
|
50
50
|
# @return [Array]
|
51
|
-
def related_work_show(record,
|
51
|
+
def related_work_show(record, relator_map: Mappers.relator)
|
52
52
|
values = record.fields(RELATED_WORK_FIELDS).filter_map do |field|
|
53
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_map)
|
58
58
|
end
|
59
59
|
values + record.fields('880').filter_map do |field|
|
60
60
|
next if field.indicator2.present?
|
@@ -63,7 +63,7 @@ module PennMARC
|
|
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_map)
|
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_map
|
75
75
|
# @return [Array]
|
76
|
-
def contains_show(record,
|
76
|
+
def contains_show(record, relator_map: Mappers.relator)
|
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_map)
|
81
81
|
end
|
82
82
|
acc + record.fields('880').filter_map do |field|
|
83
83
|
next unless field.indicator2 == '2'
|
@@ -20,13 +20,13 @@ module PennMARC
|
|
20
20
|
|
21
21
|
# Fields for display that pertain to series information.
|
22
22
|
# @param [MARC::Record] record
|
23
|
-
# @param [Hash]
|
23
|
+
# @param [Hash] relator_map
|
24
24
|
# @return [Array<String>] array of series information
|
25
|
-
def show(record,
|
25
|
+
def show(record, relator_map: Mappers.relator)
|
26
26
|
tags_present = DISPLAY_TAGS.select { |tag| record[tag].present? }
|
27
27
|
|
28
28
|
values = if %w[800 810 811 400 410 411].member?(tags_present.first)
|
29
|
-
author_show_entries(record, tags_present.first,
|
29
|
+
author_show_entries(record, tags_present.first, relator_map)
|
30
30
|
elsif %w[830 440 490].member?(tags_present.first)
|
31
31
|
title_show_entries(record, tags_present.first)
|
32
32
|
end || []
|
@@ -37,14 +37,14 @@ module PennMARC
|
|
37
37
|
|
38
38
|
# Values from series fields for display.
|
39
39
|
# @param [MARC::Record] record
|
40
|
-
# @param [Hash]
|
40
|
+
# @param [Hash] relator_map
|
41
41
|
# @return [Array<String>] array of series values
|
42
|
-
def values(record,
|
42
|
+
def values(record, relator_map: Mappers.relator)
|
43
43
|
series_8x = record.fields(%w[800 810 811 830]).first
|
44
|
-
return Array.wrap(
|
44
|
+
return Array.wrap(series_field(series_8x, relator_map)) if series_8x
|
45
45
|
|
46
46
|
series_4x = record.fields(%w[400 410 411 440 490]).first
|
47
|
-
|
47
|
+
Array.wrap(series_field(series_4x, relator_map)) if series_4x
|
48
48
|
end
|
49
49
|
|
50
50
|
# Series fields for search.
|
@@ -111,8 +111,9 @@ module PennMARC
|
|
111
111
|
def author_show_entries(record, first_tag, relator_mapping)
|
112
112
|
record.fields(first_tag).map do |field|
|
113
113
|
series = join_subfields(field, &subfield_not_in?(%w[0 5 6 8 e t w v n]))
|
114
|
+
author_show_subfields = %w[e w v n t]
|
114
115
|
pairs = field.map do |sf|
|
115
|
-
if
|
116
|
+
if author_show_subfields.member?(sf.code)
|
116
117
|
[' ', sf.value]
|
117
118
|
elsif sf.code == '4'
|
118
119
|
[', ', translate_relator(sf.value, relator_mapping)]
|
@@ -164,31 +165,19 @@ module PennMARC
|
|
164
165
|
end || []
|
165
166
|
end
|
166
167
|
|
167
|
-
# Assemble a formatted string of a given
|
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.
|
168
|
+
# Assemble a formatted string of a given field.
|
185
169
|
# @note added 2017/04/10: filter out 0 (authority record numbers) added by Alma
|
186
|
-
# @param [
|
170
|
+
# @param [MARC::Field] field
|
187
171
|
# @param [Hash] relator_mapping
|
188
172
|
# @return [String] series 4xx field
|
189
|
-
def
|
173
|
+
def series_field(field, relator_mapping)
|
174
|
+
subfields = if field.tag.start_with? '4'
|
175
|
+
%w[0 4 6 8]
|
176
|
+
else
|
177
|
+
%w[0 4 5 6 8]
|
178
|
+
end
|
190
179
|
s = field.filter_map { |sf|
|
191
|
-
if
|
180
|
+
if subfields.exclude?(sf.code)
|
192
181
|
" #{sf.value}"
|
193
182
|
elsif sf.code == '4'
|
194
183
|
", #{translate_relator(sf.value, relator_mapping)}"
|
@@ -26,14 +26,14 @@ module PennMARC
|
|
26
26
|
# Local subject heading tags
|
27
27
|
LOCAL_TAGS = %w[690 691 697].freeze
|
28
28
|
|
29
|
-
# All Subjects for searching. This includes most subfield content from any field contained in {SEARCH_TAGS} or
|
30
|
-
# including any linked 880 fields. Fields must have an indicator2 value in {SEARCH_SOURCE_INDICATORS}.
|
29
|
+
# All Subjects for searching. This includes most subfield content from any field contained in {SEARCH_TAGS} or
|
30
|
+
# 69X, including any linked 880 fields. Fields must have an indicator2 value in {SEARCH_SOURCE_INDICATORS}.
|
31
31
|
# @todo this includes subfields that may not be desired like 1 (uri) and 2 (source code) but this might be OK for
|
32
32
|
# a search (non-display) field?
|
33
|
-
# @param [Hash]
|
33
|
+
# @param [Hash] relator_map
|
34
34
|
# @param [MARC::Record] record
|
35
35
|
# @return [Array] array of all subject values for search
|
36
|
-
def search(record,
|
36
|
+
def search(record, relator_map: Mappers.relator)
|
37
37
|
subject_fields(record, type: :search).filter_map do |field|
|
38
38
|
subj_parts = field.filter_map do |subfield|
|
39
39
|
# TODO: use term hash here? pro/chr would be rejected...
|
@@ -45,10 +45,9 @@ module PennMARC
|
|
45
45
|
# remove any ? at the end
|
46
46
|
subfield.value.gsub(/^%?(PRO|CHR)/, '').gsub(/\?$/, '').strip
|
47
47
|
when '4'
|
48
|
-
# TODO: use relation mapping method from Title helper? for potential URI support?
|
49
48
|
# sf 4 should contain a 3-letter code or URI "that specifies the relationship from the entity described
|
50
49
|
# in the record to the entity referenced in the field"
|
51
|
-
"#{subfield.value} #{
|
50
|
+
"#{subfield.value} #{translate_relator(subfield.value.to_sym, relator_map)}".strip
|
52
51
|
else
|
53
52
|
subfield.value
|
54
53
|
end
|
@@ -183,7 +182,7 @@ module PennMARC
|
|
183
182
|
# @param [MARC::DataField] field
|
184
183
|
# @return [Boolean] whether a MARC field is intended for display under general "Subjects"
|
185
184
|
def subject_general_display_field?(field)
|
186
|
-
return false unless field.tag.in?
|
185
|
+
return false unless field.tag.in?(DISPLAY_TAGS + LOCAL_TAGS) && field.respond_to?(:indicator2)
|
187
186
|
|
188
187
|
return false if field.indicator2 == '7' && !valid_subject_genre_source_code?(field)
|
189
188
|
|
@@ -200,7 +199,7 @@ module PennMARC
|
|
200
199
|
# @param [Hash] options include :tags and :indicator2 values
|
201
200
|
# @return [Boolean] whether a MARC field should be considered for display
|
202
201
|
def subject_display_field?(field, options)
|
203
|
-
return false
|
202
|
+
return false unless field.respond_to?(:indicator2)
|
204
203
|
|
205
204
|
return true if field.tag.in?(options[:tags]) && field.indicator2.in?(options[:indicator2])
|
206
205
|
|
@@ -210,7 +209,7 @@ module PennMARC
|
|
210
209
|
# @param [MARC::DataField] field
|
211
210
|
# @return [Boolean]
|
212
211
|
def subject_facet_field?(field)
|
213
|
-
return false
|
212
|
+
return false unless field.respond_to?(:indicator2)
|
214
213
|
|
215
214
|
return true if field.tag.in?(DISPLAY_TAGS) && field.indicator2.in?(%w[0 2 4])
|
216
215
|
|
@@ -269,7 +268,7 @@ module PennMARC
|
|
269
268
|
# @param [MARC::DataField] field
|
270
269
|
# @return [Boolean]
|
271
270
|
def subject_search_field?(field)
|
272
|
-
return false
|
271
|
+
return false unless field.respond_to?(:indicator2) && SEARCH_SOURCE_INDICATORS.include?(field.indicator2)
|
273
272
|
|
274
273
|
tag = if field.tag == '880'
|
275
274
|
subfield_values(field, '6').first
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PennMARC
|
4
|
+
# reusable static mappers
|
5
|
+
class Mappers
|
6
|
+
class << self
|
7
|
+
# @return [Hash]
|
8
|
+
def language
|
9
|
+
@language ||= load_map('language.yml')
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Hash]
|
13
|
+
def location
|
14
|
+
@location ||= load_map('locations.yml')
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Hash]
|
18
|
+
def relator
|
19
|
+
@relator ||= load_map('relator.yml')
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [String] filename of mapping file in config directory, with file extension
|
23
|
+
# @return [Hash] mapping as hash
|
24
|
+
def load_map(filename)
|
25
|
+
puts { "Loading #{filename}" }
|
26
|
+
YAML.safe_load(File.read(File.join(File.expand_path(__dir__), 'mappings', filename)),
|
27
|
+
symbolize_names: true)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|