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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84864756f38d54ec58b75b355931ba9b4310f7f880245c2c437ecebb63fee447
4
- data.tar.gz: ee807c262dc0f5e2117b779b44a47cf10012c8e019340a789ac4c60d21223842
3
+ metadata.gz: e574f1fae4f59435df3bf467da310ae7e426d82c2fe54ae2321ad326c05e5e99
4
+ data.tar.gz: de545e5a150b26c73e814e36b167bb688d267a97205cf4cdbab15dfd5c3225a8
5
5
  SHA512:
6
- metadata.gz: fee3c852594dcdbb871e093f0bd45efb4043e14bfe323f6da3d48bab3dc75eb58f968b26a24e3ae786742c112f3a9ebf7ae43fb1688f33011d4b89c4ded7af1c
7
- data.tar.gz: 1192019b7f5b79c90a2d68fa46d7aa6ce7b8a2cea55f78072db3191401a4109c8d96fc5eb47ff86d05805a4cabb3409d4d90062c57ff96bdcbd9d987037160fd
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-07-28 16:23:59 UTC using RuboCop version 1.51.0.
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: 21
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: 22
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] relator_mapping
27
+ # @param [Hash] relator_map
28
28
  # @return [Array<String>] array of author/creator values for indexing
29
- def search(record, relator_mapping = relator_map)
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 %w[a 1 4 6 8].exclude?(sf.code)
35
+ elsif creator_subfields.exclude?(sf.code)
35
36
  sf.value
36
37
  elsif sf.code == '4'
37
- relator = translate_relator(sf.value, relator_mapping)
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 !%w[4 6 8].member?(sf.code)
55
+ if secondary_subfields.exclude?(sf.code)
54
56
  sf.value
55
57
  elsif sf.code == '4'
56
- relator = translate_relator(sf.value, relator_mapping)
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] relator_mapping
93
+ # @param [Hash] relator_map
92
94
  # @return [Array<String>] array of author/creator values for display
93
- def values(record, relator_mapping = relator_map)
95
+ def values(record, relator_map: Mappers.relator)
94
96
  record.fields(TAGS).map do |field|
95
- name_from_main_entry(field, relator_mapping)
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] relator_mapping
147
+ # @param [Hash] relator_map
147
148
  # @return [Array<String>] array of conference values
148
- def conference_show(record, relator_mapping = relator_map)
149
+ def conference_show(record, relator_map: Mappers.relator)
149
150
  record.fields('111').filter_map do |field|
150
- name_from_main_entry field, relator_mapping
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] relator_mapping
192
+ # @ param [Hash] relator_map
192
193
  # @return [Array<String>]
193
- def contributor_show(record, relator_mapping = relator_map)
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 ['', ' ', '0'].member?(field.indicator2)
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 %w[e u 3 4].member?(subfield.code)
203
+ next unless contributor_append_subfields.member?(subfield.code)
201
204
 
202
205
  if subfield.code == '4'
203
- ", #{translate_relator(subfield.value, relator_mapping)}"
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 %w[0 1 4 6 8].exclude?(sf.code)
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] relator_mapping
37
+ # @param [Hash] relator_map
38
38
  # @return [Array<String>] array of other edition strings
39
- def other_show(record, relator_mapping = relator_map)
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, relator_mapping)
43
+ other_edition_value(field, relator_map)
44
44
  end
45
- values += record.fields('880').filter_map do |field|
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, relator_mapping)
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] relator_mapping
57
+ # @param [Hash] relator_map
59
58
  # @return [String (frozen)] assembled other version string
60
- def other_edition_value(field, relator_mapping)
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 %w[6 8].member?(sf.code)
64
+ next if excluded_subfields.member?(sf.code)
64
65
 
65
- if %w[s x z].member?(sf.code)
66
+ if other_edition_subfields.member?(sf.code)
66
67
  " #{sf.value}"
67
68
  elsif sf.code == 't'
68
- relator = translate_relator(sf.value, relator_mapping)
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 %w[6 8].member?(sf.code)
77
+ next if excluded_subfields.member?(sf.code)
76
78
 
77
- if %w[i h s t x z e f o r w y 7].exclude?(sf.code)
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] location_mapping
71
+ # @param [Hash] location_map
72
72
  # @return [Array<String>] format values for faceting
73
73
 
74
- def facet(record, location_mapping = 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,7 @@ module PennMARC
88
88
  end
89
89
 
90
90
  # get all specific_location values from inventory info
91
- locations = Location.location record: record, location_mapping: location_mapping,
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 = %w[a b].exclude?(sf.code) ? ' -- ' : ' '
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] location_mapping
50
+ # @param [Hash] location_map
50
51
  # @return [Array<String>]
51
- def facet(record, location_mapping = location_map)
52
- locations = Location.location record: record, location_mapping: location_mapping,
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' }
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../enriched_marc'
4
+ require_relative '../mappers'
4
5
  require_relative '../util'
5
6
 
6
7
  module PennMARC
@@ -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] mapping hash for language code translation
28
+ # @param [Hash] language_map hash for language code translation
29
29
  # @return [String] nice value for language
30
- def search(record, mapping = language_map)
30
+ def search(record, language_map: Mappers.language)
31
31
  control_field = record['008']&.value
32
32
  language_code = control_field[35..37]
33
- mapping[language_code.to_sym || UNDETERMINED_CODE]
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] location_mapping hash with location_code as key and location hash as value
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, location_mapping = location_map)
16
- location(record: record, location_mapping: location_mapping, display_value: 'library')
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] location_mapping hash with location_code as key and location hash as value
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, location_mapping = location_map)
29
- location(record: record, location_mapping: location_mapping, display_value: 'specific_location')
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] location_mapping hash with location_code as key and location hash as value
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:, location_mapping: location_map)
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 location_mapping.key?(subfield.value.to_sym)
59
+ next unless location_map.key?(subfield.value.to_sym)
60
60
 
61
- location_mapping[subfield.value.to_sym][display_value.to_sym]
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] relator_mapping
49
+ # @param [Hash] relator_map
50
50
  # @return [Array]
51
- def related_work_show(record, relator_mapping = relator_map)
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: relator_mapping)
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: relator_mapping)
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] relator_mapping
74
+ # @param [Hash] relator_map
75
75
  # @return [Array]
76
- def contains_show(record, relator_mapping = relator_map)
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: relator_mapping)
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] relator_mapping
23
+ # @param [Hash] relator_map
24
24
  # @return [Array<String>] array of series information
25
- def show(record, relator_mapping = relator_map)
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, relator_mapping)
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] relator_mapping
40
+ # @param [Hash] relator_map
41
41
  # @return [Array<String>] array of series values
42
- def values(record, relator_mapping = relator_map)
42
+ def values(record, relator_map: Mappers.relator)
43
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
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
- return Array.wrap(series_4xx_field(series_4x, relator_mapping)) if series_4x
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 %w[e w v n t].member?(sf.code)
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 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.
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 [String] field
170
+ # @param [MARC::Field] field
187
171
  # @param [Hash] relator_mapping
188
172
  # @return [String] series 4xx field
189
- def series_4xx_field(field, relator_mapping)
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 %w[0 4 6 8].exclude?(sf.code)
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 69X,
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] relator_mapping
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, relator_mapping = relator_map)
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} #{relator_mapping[subfield.value.to_sym]}".strip
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? DISPLAY_TAGS + LOCAL_TAGS
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 if field.blank?
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 if field.blank?
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 if field.blank? || SEARCH_SOURCE_INDICATORS.exclude?(field.indicator2)
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