pennmarc 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +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
|