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 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