pennmarc 0.0.2 → 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.yml +4 -0
- data/.rubocop_todo.yml +143 -0
- data/Gemfile +1 -1
- data/README.md +12 -2
- data/lib/pennmarc/helpers/creator.rb +59 -21
- data/lib/pennmarc/helpers/database.rb +8 -8
- data/lib/pennmarc/helpers/date.rb +16 -15
- data/lib/pennmarc/helpers/edition.rb +25 -20
- data/lib/pennmarc/helpers/format.rb +15 -4
- data/lib/pennmarc/helpers/genre.rb +13 -11
- data/lib/pennmarc/helpers/helper.rb +1 -0
- data/lib/pennmarc/helpers/identifier.rb +16 -7
- data/lib/pennmarc/helpers/language.rb +3 -3
- data/lib/pennmarc/helpers/link.rb +6 -0
- data/lib/pennmarc/helpers/location.rb +8 -8
- data/lib/pennmarc/helpers/note.rb +52 -2
- data/lib/pennmarc/helpers/relation.rb +4 -4
- data/lib/pennmarc/helpers/series.rb +171 -85
- data/lib/pennmarc/helpers/subject.rb +16 -17
- data/lib/pennmarc/helpers/title.rb +1 -1
- data/lib/pennmarc/mappers.rb +31 -0
- data/lib/pennmarc/parser.rb +34 -157
- data/lib/pennmarc/util.rb +15 -16
- data/pennmarc.gemspec +2 -2
- data/spec/lib/pennmarc/helpers/citation_spec.rb +1 -2
- data/spec/lib/pennmarc/helpers/creator_spec.rb +54 -19
- data/spec/lib/pennmarc/helpers/date_spec.rb +5 -5
- data/spec/lib/pennmarc/helpers/edition_spec.rb +4 -6
- data/spec/lib/pennmarc/helpers/format_spec.rb +30 -10
- data/spec/lib/pennmarc/helpers/genre_spec.rb +4 -4
- data/spec/lib/pennmarc/helpers/identifer_spec.rb +15 -0
- data/spec/lib/pennmarc/helpers/language_spec.rb +1 -1
- data/spec/lib/pennmarc/helpers/location_spec.rb +2 -1
- data/spec/lib/pennmarc/helpers/note_spec.rb +67 -2
- data/spec/lib/pennmarc/helpers/relation_spec.rb +2 -2
- data/spec/lib/pennmarc/helpers/series_spec.rb +54 -0
- data/spec/lib/pennmarc/helpers/subject_spec.rb +9 -9
- 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 +24 -3
- data/spec/spec_helper.rb +1 -1
- metadata +8 -20
- 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.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 10000`
|
3
|
+
# on 2023-08-14 17:52:48 UTC using RuboCop version 1.51.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 22
|
10
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
11
|
+
Metrics/AbcSize:
|
12
|
+
Exclude:
|
13
|
+
- 'lib/pennmarc/helpers/creator.rb'
|
14
|
+
- 'lib/pennmarc/helpers/edition.rb'
|
15
|
+
- 'lib/pennmarc/helpers/format.rb'
|
16
|
+
- 'lib/pennmarc/helpers/genre.rb'
|
17
|
+
- 'lib/pennmarc/helpers/location.rb'
|
18
|
+
- 'lib/pennmarc/helpers/note.rb'
|
19
|
+
- 'lib/pennmarc/helpers/production.rb'
|
20
|
+
- 'lib/pennmarc/helpers/relation.rb'
|
21
|
+
- 'lib/pennmarc/helpers/series.rb'
|
22
|
+
- 'lib/pennmarc/helpers/subject.rb'
|
23
|
+
- 'lib/pennmarc/helpers/title.rb'
|
24
|
+
- 'lib/pennmarc/util.rb'
|
25
|
+
|
26
|
+
# Offense count: 5
|
27
|
+
# Configuration parameters: CountComments, Max, CountAsOne.
|
28
|
+
Metrics/ClassLength:
|
29
|
+
Exclude:
|
30
|
+
- 'lib/pennmarc/helpers/creator.rb'
|
31
|
+
- 'lib/pennmarc/helpers/format.rb'
|
32
|
+
- 'lib/pennmarc/helpers/series.rb'
|
33
|
+
- 'lib/pennmarc/helpers/subject.rb'
|
34
|
+
- 'lib/pennmarc/helpers/title.rb'
|
35
|
+
|
36
|
+
# Offense count: 18
|
37
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
38
|
+
Metrics/CyclomaticComplexity:
|
39
|
+
Exclude:
|
40
|
+
- 'lib/pennmarc/helpers/creator.rb'
|
41
|
+
- 'lib/pennmarc/helpers/database.rb'
|
42
|
+
- 'lib/pennmarc/helpers/edition.rb'
|
43
|
+
- 'lib/pennmarc/helpers/format.rb'
|
44
|
+
- 'lib/pennmarc/helpers/genre.rb'
|
45
|
+
- 'lib/pennmarc/helpers/note.rb'
|
46
|
+
- 'lib/pennmarc/helpers/production.rb'
|
47
|
+
- 'lib/pennmarc/helpers/relation.rb'
|
48
|
+
- 'lib/pennmarc/helpers/series.rb'
|
49
|
+
- 'lib/pennmarc/helpers/subject.rb'
|
50
|
+
- 'lib/pennmarc/helpers/title.rb'
|
51
|
+
- 'lib/pennmarc/util.rb'
|
52
|
+
|
53
|
+
# Offense count: 24
|
54
|
+
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
|
55
|
+
Metrics/MethodLength:
|
56
|
+
Exclude:
|
57
|
+
- 'lib/pennmarc/helpers/creator.rb'
|
58
|
+
- 'lib/pennmarc/helpers/date.rb'
|
59
|
+
- 'lib/pennmarc/helpers/edition.rb'
|
60
|
+
- 'lib/pennmarc/helpers/format.rb'
|
61
|
+
- 'lib/pennmarc/helpers/location.rb'
|
62
|
+
- 'lib/pennmarc/helpers/note.rb'
|
63
|
+
- 'lib/pennmarc/helpers/production.rb'
|
64
|
+
- 'lib/pennmarc/helpers/relation.rb'
|
65
|
+
- 'lib/pennmarc/helpers/series.rb'
|
66
|
+
- 'lib/pennmarc/helpers/subject.rb'
|
67
|
+
- 'lib/pennmarc/helpers/title.rb'
|
68
|
+
|
69
|
+
# Offense count: 1
|
70
|
+
# Configuration parameters: CountComments, Max, CountAsOne.
|
71
|
+
Metrics/ModuleLength:
|
72
|
+
Exclude:
|
73
|
+
- 'lib/pennmarc/util.rb'
|
74
|
+
|
75
|
+
# Offense count: 12
|
76
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
77
|
+
Metrics/PerceivedComplexity:
|
78
|
+
Exclude:
|
79
|
+
- 'lib/pennmarc/helpers/creator.rb'
|
80
|
+
- 'lib/pennmarc/helpers/edition.rb'
|
81
|
+
- 'lib/pennmarc/helpers/format.rb'
|
82
|
+
- 'lib/pennmarc/helpers/genre.rb'
|
83
|
+
- 'lib/pennmarc/helpers/note.rb'
|
84
|
+
- 'lib/pennmarc/helpers/production.rb'
|
85
|
+
- 'lib/pennmarc/helpers/series.rb'
|
86
|
+
- 'lib/pennmarc/helpers/title.rb'
|
87
|
+
- 'lib/pennmarc/util.rb'
|
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
|
+
|
97
|
+
# Offense count: 1
|
98
|
+
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
|
99
|
+
# NamePrefix: is_, has_, have_
|
100
|
+
# ForbiddenPrefixes: is_, has_, have_
|
101
|
+
# AllowedMethods: is_a?
|
102
|
+
# MethodDefinitionMacros: define_method, define_singleton_method
|
103
|
+
Naming/PredicateName:
|
104
|
+
Exclude:
|
105
|
+
- 'lib/pennmarc/helpers/relation.rb'
|
106
|
+
|
107
|
+
# Offense count: 2
|
108
|
+
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
109
|
+
# SupportedStyles: snake_case, normalcase, non_integer
|
110
|
+
# AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
|
111
|
+
Naming/VariableNumber:
|
112
|
+
Exclude:
|
113
|
+
- 'lib/pennmarc/util.rb'
|
114
|
+
|
115
|
+
# Offense count: 6
|
116
|
+
# Configuration parameters: Max, CountAsOne.
|
117
|
+
RSpec/ExampleLength:
|
118
|
+
Exclude:
|
119
|
+
- 'spec/lib/pennmarc/helpers/creator_spec.rb'
|
120
|
+
- 'spec/lib/pennmarc/helpers/note_spec.rb'
|
121
|
+
- 'spec/lib/pennmarc/helpers/production_spec.rb'
|
122
|
+
- 'spec/lib/pennmarc/marc_util_spec.rb'
|
123
|
+
|
124
|
+
# Offense count: 1
|
125
|
+
# Configuration parameters: Include, CustomTransform, IgnoreMethods, SpecSuffixOnly.
|
126
|
+
# Include: **/*_spec*rb*, **/spec/**/*
|
127
|
+
RSpec/FilePath:
|
128
|
+
Exclude:
|
129
|
+
- 'spec/lib/pennmarc/parser_spec.rb'
|
130
|
+
|
131
|
+
# Offense count: 4
|
132
|
+
# Configuration parameters: Max, AllowedGroups.
|
133
|
+
RSpec/NestedGroups:
|
134
|
+
Exclude:
|
135
|
+
- 'spec/lib/pennmarc/helpers/format_spec.rb'
|
136
|
+
|
137
|
+
# Offense count: 2
|
138
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
139
|
+
# Configuration parameters: Include.
|
140
|
+
# Include: app/**/*.rb, config/**/*.rb, db/**/*.rb, lib/**/*.rb
|
141
|
+
Rails/Output:
|
142
|
+
Exclude:
|
143
|
+
- 'lib/pennmarc/helpers/date.rb'
|
data/Gemfile
CHANGED
@@ -7,6 +7,7 @@ gem 'library_stdnums', '~> 1.6'
|
|
7
7
|
gem 'marc', '~> 1.2'
|
8
8
|
gem 'nokogiri', '~> 1.15'
|
9
9
|
gem 'rake', '~> 13.0'
|
10
|
+
gem 'upennlib-rubocop', require: false
|
10
11
|
|
11
12
|
group :test, :development do
|
12
13
|
gem 'rspec', '~> 3.12'
|
@@ -17,7 +18,6 @@ group :test do
|
|
17
18
|
end
|
18
19
|
|
19
20
|
group :development do
|
20
|
-
gem 'upennlib-rubocop', require: false
|
21
21
|
gem 'webrick', '~> 1.8'
|
22
22
|
gem 'yard', '~> 0.9'
|
23
23
|
end
|
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,43 +24,45 @@ 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
|
41
42
|
end
|
42
43
|
end
|
43
44
|
value = join_and_squish(pieces)
|
44
|
-
if value.end_with?('.'
|
45
|
+
if value.end_with?('.', '-')
|
45
46
|
value
|
46
47
|
else
|
47
48
|
"#{value}."
|
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
|
60
62
|
end
|
61
63
|
end
|
62
64
|
value = join_and_squish(pieces)
|
63
|
-
if value.end_with?('.'
|
65
|
+
if value.end_with?('.', '-')
|
64
66
|
value
|
65
67
|
else
|
66
68
|
"#{value}."
|
@@ -69,9 +71,9 @@ module PennMARC
|
|
69
71
|
acc += record.fields(%w[880]).filter_map do |field|
|
70
72
|
next unless field.any? { |sf| sf.code == '6' && sf.value.in?(%w[100 110]) }
|
71
73
|
|
72
|
-
suba = field.find_all(&subfield_in?(%w[a])).map
|
74
|
+
suba = field.find_all(&subfield_in?(%w[a])).map { |sf|
|
73
75
|
convert_name_order(sf.value)
|
74
|
-
|
76
|
+
}.first
|
75
77
|
oth = join_and_squish(field.find_all(&subfield_not_in?(%w[6 8 a t])).map(&:value))
|
76
78
|
join_and_squish [suba, oth]
|
77
79
|
end
|
@@ -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
|
@@ -135,7 +136,7 @@ module PennMARC
|
|
135
136
|
}
|
136
137
|
source_map.flat_map do |field_num, subfields|
|
137
138
|
record.fields(field_num.to_s).map do |field|
|
138
|
-
trim_punctuation(join_subfields(field, &subfield_in?(subfields.
|
139
|
+
trim_punctuation(join_subfields(field, &subfield_in?(subfields.chars)))
|
139
140
|
end
|
140
141
|
end
|
141
142
|
end
|
@@ -145,7 +146,7 @@ module PennMARC
|
|
145
146
|
# @param [MARC::Record] record
|
146
147
|
# @param [Hash] relator_map
|
147
148
|
# @return [Array<String>] array of conference values
|
148
|
-
def conference_show(record, relator_map)
|
149
|
+
def conference_show(record, relator_map: Mappers.relator)
|
149
150
|
record.fields('111').filter_map do |field|
|
150
151
|
name_from_main_entry field, relator_map
|
151
152
|
end
|
@@ -183,6 +184,42 @@ module PennMARC
|
|
183
184
|
# @note see get_conference_search_values
|
184
185
|
def conference_search(record); end
|
185
186
|
|
187
|
+
# Retrieve contributor values for display from fields {https://www.oclc.org/bibformats/en/7xx/700.html 700}
|
188
|
+
# and {https://www.oclc.org/bibformats/en/7xx/710.html 710} and their linked alternates. Joins subfields
|
189
|
+
# 'a', 'b', 'c', 'd', 'j', and 'q'. Then appends resulting string with joined subfields 'e', 'u', '3', and '4'.
|
190
|
+
# @note legacy version returns array of hash objects including data for display link
|
191
|
+
# @param [MARC::Record] record
|
192
|
+
# @ param [Hash] relator_map
|
193
|
+
# @return [Array<String>]
|
194
|
+
def contributor_show(record, relator_map: Mappers.relator)
|
195
|
+
indicator_2_options = ['', ' ', '0']
|
196
|
+
contributors = record.fields(%w[700 710]).filter_map do |field|
|
197
|
+
next unless indicator_2_options.member?(field.indicator2)
|
198
|
+
next if subfield_defined? field, 'i'
|
199
|
+
|
200
|
+
contributor = join_subfields(field, &subfield_in?(%w[a b c d j q]))
|
201
|
+
contributor_append_subfields = %w[e u 3 4]
|
202
|
+
contributor_append = field.filter_map { |subfield|
|
203
|
+
next unless contributor_append_subfields.member?(subfield.code)
|
204
|
+
|
205
|
+
if subfield.code == '4'
|
206
|
+
", #{translate_relator(subfield.value, relator_map)}"
|
207
|
+
else
|
208
|
+
" #{subfield.value}"
|
209
|
+
end
|
210
|
+
}.join
|
211
|
+
"#{contributor} #{contributor_append}".squish
|
212
|
+
end
|
213
|
+
contributors + record.fields('880').filter_map do |field|
|
214
|
+
next unless subfield_value_in?(field, '6', %w[700 710])
|
215
|
+
next if subfield_defined?(field, 'i')
|
216
|
+
|
217
|
+
contributor = join_subfields(field, &subfield_in?(%w[a b c d j q]))
|
218
|
+
contributor_append = join_subfields(field, &subfield_in?(%w[e u 3]))
|
219
|
+
"#{contributor} #{contributor_append}".squish
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
186
223
|
private
|
187
224
|
|
188
225
|
# Trim punctuation method extracted from Traject macro, to ensure consistent output
|
@@ -209,8 +246,9 @@ module PennMARC
|
|
209
246
|
# @param [MARC::Field] field
|
210
247
|
# @return [String] joined subfield values for value from field
|
211
248
|
def name_from_main_entry(field, mapping)
|
212
|
-
|
213
|
-
|
249
|
+
name_subfields = %w[0 1 4 6 8]
|
250
|
+
s = field.filter_map { |sf|
|
251
|
+
if name_subfields.exclude?(sf.code)
|
214
252
|
" #{sf.value}"
|
215
253
|
elsif sf.code == '4'
|
216
254
|
relator = translate_relator(sf.value, mapping)
|
@@ -218,8 +256,8 @@ module PennMARC
|
|
218
256
|
|
219
257
|
", #{relator}"
|
220
258
|
end
|
221
|
-
|
222
|
-
(s + (
|
259
|
+
}.join
|
260
|
+
(s + (%w[. -].member?(s.last) ? '' : '.')).squish
|
223
261
|
end
|
224
262
|
|
225
263
|
# Convert "Lastname, First" to "First Lastname"
|
@@ -21,7 +21,7 @@ module PennMARC
|
|
21
21
|
def type(record)
|
22
22
|
record.fields('944').filter_map do |field|
|
23
23
|
# skip unless specified database format type present
|
24
|
-
next unless subfield_value?(field, 'a', /#{DATABASES_FACET_VALUE}/)
|
24
|
+
next unless subfield_value?(field, 'a', /#{DATABASES_FACET_VALUE}/o)
|
25
25
|
|
26
26
|
type = field.find { |subfield| subfield.code == 'b' }
|
27
27
|
type&.value
|
@@ -39,7 +39,7 @@ module PennMARC
|
|
39
39
|
|
40
40
|
record.fields('943').filter_map do |field|
|
41
41
|
# skip unless Community of Interest code is in subfield '2'
|
42
|
-
next unless subfield_value?(field, '2', /#{COI_CODE}/)
|
42
|
+
next unless subfield_value?(field, '2', /#{COI_CODE}/o)
|
43
43
|
|
44
44
|
category = field.find { |subfield| subfield.code == 'a' }
|
45
45
|
category&.value
|
@@ -60,17 +60,17 @@ module PennMARC
|
|
60
60
|
|
61
61
|
record.fields('943').filter_map do |field|
|
62
62
|
# skip unless Community of Interest code is in subfield '2'
|
63
|
-
next unless subfield_value?(field, '2', /#{COI_CODE}/)
|
63
|
+
next unless subfield_value?(field, '2', /#{COI_CODE}/o)
|
64
64
|
|
65
65
|
category = field.find { |subfield| subfield.code == 'a' }
|
66
66
|
|
67
|
-
# skip
|
68
|
-
next
|
67
|
+
# skip if category is blank
|
68
|
+
next if category.blank?
|
69
69
|
|
70
70
|
subcategory = field.find { |subfield| subfield.code == 'b' }
|
71
71
|
|
72
|
-
# skip
|
73
|
-
next
|
72
|
+
# skip if subcategory is blank
|
73
|
+
next if subcategory.blank?
|
74
74
|
|
75
75
|
"#{category.value}--#{subcategory.value}"
|
76
76
|
end
|
@@ -82,7 +82,7 @@ module PennMARC
|
|
82
82
|
# @param [Marc::Record]
|
83
83
|
# @return [TrueClass, FalseClass]
|
84
84
|
def curated_db?(record)
|
85
|
-
record.fields('944').any? { |field| subfield_value?(field, 'a', /#{DATABASES_FACET_VALUE}/) }
|
85
|
+
record.fields('944').any? { |field| subfield_value?(field, 'a', /#{DATABASES_FACET_VALUE}/o) }
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
@@ -10,13 +10,13 @@ module PennMARC
|
|
10
10
|
# @param [MARC::Record] record
|
11
11
|
# @return [DateTime, nil] The publication date, or nil if date found in record is invalid
|
12
12
|
def publication(record)
|
13
|
-
record.fields('008').filter_map
|
13
|
+
record.fields('008').filter_map { |field|
|
14
14
|
four_digit_year = sanitize_partially_known_date(field.value[7, 4], '0')
|
15
15
|
|
16
|
-
next
|
16
|
+
next if four_digit_year.blank?
|
17
17
|
|
18
18
|
DateTime.new(four_digit_year.to_i)
|
19
|
-
|
19
|
+
}.first
|
20
20
|
end
|
21
21
|
|
22
22
|
# Retrieve date added (subfield 'q') from enriched marc 'itm' field.
|
@@ -24,7 +24,7 @@ module PennMARC
|
|
24
24
|
# @param [MARC::Record] record
|
25
25
|
# @return [DateTime, nil] The date added, or nil if date found in record is invalid
|
26
26
|
def added(record)
|
27
|
-
record.fields(EnrichedMarc::TAG_ITEM).flat_map
|
27
|
+
record.fields(EnrichedMarc::TAG_ITEM).flat_map { |field|
|
28
28
|
field.filter_map do |subfield|
|
29
29
|
# skip unless field has date created subfield
|
30
30
|
next unless subfield_defined?(field, EnrichedMarc::SUB_ITEM_DATE_CREATED)
|
@@ -42,7 +42,7 @@ module PennMARC
|
|
42
42
|
puts "Error parsing date in date added subfield: #{subfield.value} - #{e}"
|
43
43
|
nil
|
44
44
|
end
|
45
|
-
|
45
|
+
}.max
|
46
46
|
end
|
47
47
|
|
48
48
|
# Retrieve date last updated from {https://www.loc.gov/marc/bibliographic/bd005.html 005 field}.
|
@@ -51,19 +51,20 @@ module PennMARC
|
|
51
51
|
# @param [MARC::Record] record
|
52
52
|
# @return [DateTime, nil] The date last updated, or nil if date found in record is invalid
|
53
53
|
def last_updated(record)
|
54
|
-
record.fields('005').filter_map
|
55
|
-
|
54
|
+
record.fields('005').filter_map { |field|
|
55
|
+
begin
|
56
|
+
date_time_string = field.value
|
56
57
|
|
57
|
-
|
58
|
+
next if date_time_string.blank?
|
58
59
|
|
59
|
-
|
60
|
+
next if date_time_string.start_with?('0000')
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
62
|
+
DateTime.iso8601(date_time_string).to_datetime
|
63
|
+
rescue ArgumentError => e
|
64
|
+
puts "Error parsing last updated date: #{date_time_string} - #{e}"
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
}.first
|
67
68
|
end
|
68
69
|
|
69
70
|
private
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module PennMARC
|
4
|
-
# Do Edition-
|
4
|
+
# Do Edition and edition-related field processing.
|
5
5
|
class Edition < Helper
|
6
6
|
class << self
|
7
7
|
# Edition values for display on a record page. Field 250 is information relating to the edition of a work as
|
@@ -14,9 +14,9 @@ module PennMARC
|
|
14
14
|
# @param [MARC::Record] record
|
15
15
|
# @return [Array<String>] array of editions and their alternates
|
16
16
|
def show(record)
|
17
|
-
record.fields('250').map
|
17
|
+
record.fields('250').map { |field|
|
18
18
|
join_subfields(field, &subfield_not_in?(%w[6 8]))
|
19
|
-
|
19
|
+
} + linked_alternate_not_6_or_8(record, '250')
|
20
20
|
end
|
21
21
|
|
22
22
|
# Edition values for display in search results. Just grab the first 250 field.
|
@@ -24,7 +24,7 @@ module PennMARC
|
|
24
24
|
# @return [String, NilClass] string of all first 250 subfields, excluding 6 and 8
|
25
25
|
def values(record)
|
26
26
|
edition = record.fields('250').first
|
27
|
-
return
|
27
|
+
return if edition.blank?
|
28
28
|
|
29
29
|
join_subfields(edition, &subfield_not_in?(%w[6 8]))
|
30
30
|
end
|
@@ -34,17 +34,19 @@ module PennMARC
|
|
34
34
|
# display.
|
35
35
|
# https://www.loc.gov/marc/bibliographic/bd775.html
|
36
36
|
# @param [MARC::Record] record
|
37
|
+
# @param [Hash] relator_map
|
37
38
|
# @return [Array<String>] array of other edition strings
|
38
|
-
def other_show(record,
|
39
|
-
record.fields('775').filter_map do |field|
|
39
|
+
def other_show(record, relator_map: Mappers.relator)
|
40
|
+
values = record.fields('775').filter_map do |field|
|
40
41
|
next unless subfield_defined?(field, :i)
|
41
42
|
|
42
|
-
other_edition_value(field,
|
43
|
-
end
|
43
|
+
other_edition_value(field, relator_map)
|
44
|
+
end
|
45
|
+
values + record.fields('880').filter_map do |field|
|
44
46
|
next unless field.indicator2.blank? && subfield_value_in?(field, '6', %w[775]) &&
|
45
47
|
subfield_defined?(field, 'i')
|
46
48
|
|
47
|
-
other_edition_value(field,
|
49
|
+
other_edition_value(field, relator_map)
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
@@ -52,31 +54,34 @@ module PennMARC
|
|
52
54
|
|
53
55
|
# Assemble a string of relevant edition information.
|
54
56
|
# @param [MARC::DataField] field
|
55
|
-
# @param [Hash]
|
57
|
+
# @param [Hash] relator_map
|
56
58
|
# @return [String (frozen)] assembled other version string
|
57
|
-
def other_edition_value(field,
|
59
|
+
def other_edition_value(field, relator_map)
|
58
60
|
subi = remove_paren_value_from_subfield_i(field) || ''
|
59
|
-
|
60
|
-
|
61
|
+
excluded_subfields = %w[6 8]
|
62
|
+
other_edition_subfields = %w[s x z]
|
63
|
+
other_editions = field.filter_map { |sf|
|
64
|
+
next if excluded_subfields.member?(sf.code)
|
61
65
|
|
62
|
-
if
|
66
|
+
if other_edition_subfields.member?(sf.code)
|
63
67
|
" #{sf.value}"
|
64
68
|
elsif sf.code == 't'
|
65
|
-
relator = translate_relator(sf.value,
|
69
|
+
relator = translate_relator(sf.value, relator_map)
|
66
70
|
next if relator.blank?
|
67
71
|
|
68
72
|
" #{relator}. "
|
69
73
|
end
|
70
|
-
|
71
|
-
|
72
|
-
|
74
|
+
}.join
|
75
|
+
other_editions_append_subfields = %w[i h s t x z e f o r w y 7]
|
76
|
+
other_editions_append = field.filter_map { |sf|
|
77
|
+
next if excluded_subfields.member?(sf.code)
|
73
78
|
|
74
|
-
if
|
79
|
+
if other_editions_append_subfields.exclude?(sf.code)
|
75
80
|
" #{sf.value}"
|
76
81
|
elsif sf.code == 'h'
|
77
82
|
" (#{sf.value}) "
|
78
83
|
end
|
79
|
-
|
84
|
+
}.join
|
80
85
|
prepend = trim_trailing(:period, subi).squish
|
81
86
|
|
82
87
|
if other_editions.present? || other_editions_append.present?
|
@@ -71,7 +71,7 @@ module PennMARC
|
|
71
71
|
# @param [Hash] location_map
|
72
72
|
# @return [Array<String>] format values for faceting
|
73
73
|
|
74
|
-
def facet(record, location_map)
|
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,8 @@ module PennMARC
|
|
88
88
|
end
|
89
89
|
|
90
90
|
# get all specific_location values from inventory info
|
91
|
-
locations = Location.location record: record, location_map: location_map,
|
91
|
+
locations = Location.location record: record, location_map: location_map,
|
92
|
+
display_value: :specific_location
|
92
93
|
|
93
94
|
if include_manuscripts?(locations)
|
94
95
|
formats << MANUSCRIPT
|
@@ -147,6 +148,16 @@ module PennMARC
|
|
147
148
|
end
|
148
149
|
end
|
149
150
|
|
151
|
+
# Retrieve cartographic reference data for map/atlas formats for display from
|
152
|
+
# {https://www.oclc.org/bibformats/en/2xx/255.html 255} and {https://www.oclc.org/bibformats/en/3xx/342.html 342}
|
153
|
+
# @param [MARC::Record] record
|
154
|
+
# @return [Array<String>]
|
155
|
+
def cartographic_show(record)
|
156
|
+
record.fields(%w[255 342]).map do |field|
|
157
|
+
join_subfields(field, &subfield_not_in?(%w[6 8]))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
150
161
|
# Check if a set of locations has any locations that include the term 'manuscripts'
|
151
162
|
# @param [Array<String>] locations
|
152
163
|
# @return [Boolean]
|
@@ -162,12 +173,12 @@ module PennMARC
|
|
162
173
|
# @param [MARC::Record] record
|
163
174
|
# @return [Array]
|
164
175
|
def curated_format(record)
|
165
|
-
record.fields('944').filter_map
|
176
|
+
record.fields('944').filter_map { |field|
|
166
177
|
subfield_a = field.find { |sf| sf.code == 'a' }
|
167
178
|
next if subfield_a.nil? || (subfield_a.value == subfield_a.value.to_i.to_s)
|
168
179
|
|
169
180
|
subfield_a.value
|
170
|
-
|
181
|
+
}.uniq
|
171
182
|
end
|
172
183
|
|
173
184
|
# @param [String] format_code
|