pennmarc 1.0.30 → 1.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/Gemfile +0 -1
 - data/Gemfile.lock +0 -2
 - data/lib/pennmarc/heading_control.rb +9 -5
 - data/lib/pennmarc/helpers/access.rb +4 -4
 - data/lib/pennmarc/helpers/citation.rb +2 -2
 - data/lib/pennmarc/helpers/classification.rb +10 -7
 - data/lib/pennmarc/helpers/creator.rb +27 -25
 - data/lib/pennmarc/helpers/database.rb +8 -8
 - data/lib/pennmarc/helpers/date.rb +5 -5
 - data/lib/pennmarc/helpers/edition.rb +7 -7
 - data/lib/pennmarc/helpers/format.rb +36 -40
 - data/lib/pennmarc/helpers/genre.rb +5 -5
 - data/lib/pennmarc/helpers/identifier.rb +18 -18
 - data/lib/pennmarc/helpers/inventory.rb +7 -7
 - data/lib/pennmarc/helpers/inventory_entry/base.rb +2 -2
 - data/lib/pennmarc/helpers/language.rb +4 -4
 - data/lib/pennmarc/helpers/link.rb +6 -6
 - data/lib/pennmarc/helpers/location.rb +14 -14
 - data/lib/pennmarc/helpers/note.rb +2 -2
 - data/lib/pennmarc/helpers/production.rb +7 -6
 - data/lib/pennmarc/helpers/relation.rb +14 -14
 - data/lib/pennmarc/helpers/series.rb +19 -19
 - data/lib/pennmarc/helpers/subject.rb +28 -28
 - data/lib/pennmarc/helpers/title.rb +18 -18
 - data/lib/pennmarc/mappings/headings_override.yml +12 -8
 - data/lib/pennmarc/parser.rb +5 -5
 - data/lib/pennmarc/test/marc_helpers.rb +11 -11
 - data/lib/pennmarc/util.rb +18 -18
 - data/lib/pennmarc/version.rb +1 -1
 - data/pennmarc.gemspec +0 -1
 - data/spec/lib/pennmarc/heading_control_spec.rb +17 -10
 - data/spec/lib/pennmarc/helpers/creator_spec.rb +15 -12
 - data/spec/lib/pennmarc/marc_util_spec.rb +12 -0
 - data/spec/support/fixture_helpers.rb +1 -1
 - metadata +2 -16
 
| 
         @@ -30,8 +30,8 @@ module PennMARC 
     | 
|
| 
       30 
30 
     | 
    
         
             
                  # 69X, including any linked 880 fields. Fields must have an indicator2 value in {VALID_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] 
     | 
| 
       34 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 33 
     | 
    
         
            +
                  # @param relator_map [Hash]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       35 
35 
     | 
    
         
             
                  # @return [Array<String>] array of all subject values for search
         
     | 
| 
       36 
36 
     | 
    
         
             
                  def search(record, relator_map: Mappers.relator)
         
     | 
| 
       37 
37 
     | 
    
         
             
                    subject_fields(record, type: :search).filter_map { |field|
         
     | 
| 
         @@ -61,8 +61,8 @@ module PennMARC 
     | 
|
| 
       61 
61 
     | 
    
         
             
                  # All Subjects for faceting
         
     | 
| 
       62 
62 
     | 
    
         
             
                  #
         
     | 
| 
       63 
63 
     | 
    
         
             
                  # @note this is ported mostly form MG's new-style Subject parsing
         
     | 
| 
       64 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
       65 
     | 
    
         
            -
                  # @param [Boolean]  
     | 
| 
      
 64 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
      
 65 
     | 
    
         
            +
                  # @param override [Boolean] remove undesirable terms or not
         
     | 
| 
       66 
66 
     | 
    
         
             
                  # @return [Array<String>] array of all subject values for faceting
         
     | 
| 
       67 
67 
     | 
    
         
             
                  def facet(record, override: true)
         
     | 
| 
       68 
68 
     | 
    
         
             
                    values = subject_fields(record, type: :facet).filter_map { |field|
         
     | 
| 
         @@ -77,8 +77,8 @@ module PennMARC 
     | 
|
| 
       77 
77 
     | 
    
         
             
                  # All Subjects for display. This includes all {DISPLAY_TAGS} and {LOCAL_TAGS}. For tags that specify a source,
         
     | 
| 
       78 
78 
     | 
    
         
             
                  # only those with an allowed source code (see ALLOWED_SOURCE_CODES) are included.
         
     | 
| 
       79 
79 
     | 
    
         
             
                  #
         
     | 
| 
       80 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
       81 
     | 
    
         
            -
                  # @param [Boolean]  
     | 
| 
      
 80 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
      
 81 
     | 
    
         
            +
                  # @param override [Boolean] to remove undesirable terms or not
         
     | 
| 
       82 
82 
     | 
    
         
             
                  # @return [Array] array of all subject values for display
         
     | 
| 
       83 
83 
     | 
    
         
             
                  def show(record, override: true)
         
     | 
| 
       84 
84 
     | 
    
         
             
                    values = subject_fields(record, type: :all).filter_map { |field|
         
     | 
| 
         @@ -92,8 +92,8 @@ module PennMARC 
     | 
|
| 
       92 
92 
     | 
    
         | 
| 
       93 
93 
     | 
    
         
             
                  # Get Subjects from "Children" ontology
         
     | 
| 
       94 
94 
     | 
    
         
             
                  #
         
     | 
| 
       95 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
       96 
     | 
    
         
            -
                  # @param [Boolean]  
     | 
| 
      
 95 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
      
 96 
     | 
    
         
            +
                  # @param override [Boolean] remove undesirable terms or not
         
     | 
| 
       97 
97 
     | 
    
         
             
                  # @return [Array] array of children's subject values for display
         
     | 
| 
       98 
98 
     | 
    
         
             
                  def childrens_show(record, override: true)
         
     | 
| 
       99 
99 
     | 
    
         
             
                    values = subject_fields(record, type: :display, options: { tags: DISPLAY_TAGS, indicator2: '1' })
         
     | 
| 
         @@ -108,8 +108,8 @@ module PennMARC 
     | 
|
| 
       108 
108 
     | 
    
         | 
| 
       109 
109 
     | 
    
         
             
                  # Get Subjects from "MeSH" ontology
         
     | 
| 
       110 
110 
     | 
    
         
             
                  #
         
     | 
| 
       111 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
       112 
     | 
    
         
            -
                  # @param [Boolean]  
     | 
| 
      
 111 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
      
 112 
     | 
    
         
            +
                  # @param override [Boolean] remove undesirable terms or not
         
     | 
| 
       113 
113 
     | 
    
         
             
                  # @return [Array] array of MeSH subject values for display
         
     | 
| 
       114 
114 
     | 
    
         
             
                  def medical_show(record, override: true)
         
     | 
| 
       115 
115 
     | 
    
         
             
                    values = subject_fields(record, type: :display, options: { tags: DISPLAY_TAGS, indicator2: '2' })
         
     | 
| 
         @@ -125,8 +125,8 @@ module PennMARC 
     | 
|
| 
       125 
125 
     | 
    
         
             
                  # Get Subject values from {DISPLAY_TAGS} where indicator2 is 4 and {LOCAL_TAGS}. Do not include any values where
         
     | 
| 
       126 
126 
     | 
    
         
             
                  # sf2 includes "penncoi" (Community of Interest).
         
     | 
| 
       127 
127 
     | 
    
         
             
                  #
         
     | 
| 
       128 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
       129 
     | 
    
         
            -
                  # @param [Boolean]  
     | 
| 
      
 128 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
      
 129 
     | 
    
         
            +
                  # @param override [Boolean] to remove undesirable terms
         
     | 
| 
       130 
130 
     | 
    
         
             
                  # @return [Array] array of local subject values for display
         
     | 
| 
       131 
131 
     | 
    
         
             
                  def local_show(record, override: true)
         
     | 
| 
       132 
132 
     | 
    
         
             
                    local_fields = subject_fields(record, type: :display, options: { tags: DISPLAY_TAGS, indicator2: '4' }) +
         
     | 
| 
         @@ -149,9 +149,9 @@ module PennMARC 
     | 
|
| 
       149 
149 
     | 
    
         
             
                  # - facet
         
     | 
| 
       150 
150 
     | 
    
         
             
                  # - display
         
     | 
| 
       151 
151 
     | 
    
         
             
                  # - local
         
     | 
| 
       152 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
       153 
     | 
    
         
            -
                  # @param [String, Symbol] type of fields desired
         
     | 
| 
       154 
     | 
    
         
            -
                  # @param [Hash] options to be passed to the selector method
         
     | 
| 
      
 152 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
      
 153 
     | 
    
         
            +
                  # @param type [String, Symbol] type of fields desired
         
     | 
| 
      
 154 
     | 
    
         
            +
                  # @param options [Hash] options to be passed to the selector method
         
     | 
| 
       155 
155 
     | 
    
         
             
                  # @return [Array<MARC::DataField>] selected fields
         
     | 
| 
       156 
156 
     | 
    
         
             
                  def subject_fields(record, type:, options: {})
         
     | 
| 
       157 
157 
     | 
    
         
             
                    selector_method = case type.to_sym
         
     | 
| 
         @@ -171,8 +171,8 @@ module PennMARC 
     | 
|
| 
       171 
171 
     | 
    
         
             
                  # Format a term hash as a string for display
         
     | 
| 
       172 
172 
     | 
    
         
             
                  #
         
     | 
| 
       173 
173 
     | 
    
         
             
                  # @todo support search field formatting?
         
     | 
| 
       174 
     | 
    
         
            -
                  # @param [Symbol] 
     | 
| 
       175 
     | 
    
         
            -
                  # @param [Hash]  
     | 
| 
      
 174 
     | 
    
         
            +
                  # @param type [Symbol]
         
     | 
| 
      
 175 
     | 
    
         
            +
                  # @param term [Hash] components and information as a hash
         
     | 
| 
       176 
176 
     | 
    
         
             
                  # @return [String]
         
     | 
| 
       177 
177 
     | 
    
         
             
                  def format_term(type:, term:)
         
     | 
| 
       178 
178 
     | 
    
         
             
                    return unless type.in? %i[facet display]
         
     | 
| 
         @@ -194,7 +194,7 @@ module PennMARC 
     | 
|
| 
       194 
194 
     | 
    
         
             
                  # indicator 2 is '7' - indicating "source specified", the specified source must be in our approved source code
         
     | 
| 
       195 
195 
     | 
    
         
             
                  # list.
         
     | 
| 
       196 
196 
     | 
    
         
             
                  # @see Util.valid_subject_genre_source_code?
         
     | 
| 
       197 
     | 
    
         
            -
                  # @param [MARC::DataField] 
     | 
| 
      
 197 
     | 
    
         
            +
                  # @param field [MARC::DataField]
         
     | 
| 
       198 
198 
     | 
    
         
             
                  # @return [Boolean] whether a MARC field is intended for display under general "Subjects"
         
     | 
| 
       199 
199 
     | 
    
         
             
                  def subject_general_display_field?(field)
         
     | 
| 
       200 
200 
     | 
    
         
             
                    return false unless field.tag.in?(DISPLAY_TAGS + LOCAL_TAGS) && field.respond_to?(:indicator2)
         
     | 
| 
         @@ -206,14 +206,14 @@ module PennMARC 
     | 
|
| 
       206 
206 
     | 
    
         
             
                    true
         
     | 
| 
       207 
207 
     | 
    
         
             
                  end
         
     | 
| 
       208 
208 
     | 
    
         | 
| 
       209 
     | 
    
         
            -
                  # @param [MARC::DataField] 
     | 
| 
      
 209 
     | 
    
         
            +
                  # @param field [MARC::DataField]
         
     | 
| 
       210 
210 
     | 
    
         
             
                  # @return [Boolean] whether a MARC field is a local subject field (69X)
         
     | 
| 
       211 
211 
     | 
    
         
             
                  def subject_local_field?(field)
         
     | 
| 
       212 
212 
     | 
    
         
             
                    field.tag.in? LOCAL_TAGS
         
     | 
| 
       213 
213 
     | 
    
         
             
                  end
         
     | 
| 
       214 
214 
     | 
    
         | 
| 
       215 
     | 
    
         
            -
                  # @param [MARC::DataField] 
     | 
| 
       216 
     | 
    
         
            -
                  # @param [Hash]  
     | 
| 
      
 215 
     | 
    
         
            +
                  # @param field [MARC::DataField]
         
     | 
| 
      
 216 
     | 
    
         
            +
                  # @param options [Hash] include :tags and :indicator2 values
         
     | 
| 
       217 
217 
     | 
    
         
             
                  # @return [Boolean] whether a MARC field should be considered for display
         
     | 
| 
       218 
218 
     | 
    
         
             
                  def subject_display_field?(field, options)
         
     | 
| 
       219 
219 
     | 
    
         
             
                    return false unless field.respond_to?(:indicator2)
         
     | 
| 
         @@ -223,7 +223,7 @@ module PennMARC 
     | 
|
| 
       223 
223 
     | 
    
         
             
                    false
         
     | 
| 
       224 
224 
     | 
    
         
             
                  end
         
     | 
| 
       225 
225 
     | 
    
         | 
| 
       226 
     | 
    
         
            -
                  # @param [MARC::DataField] 
     | 
| 
      
 226 
     | 
    
         
            +
                  # @param field [MARC::DataField]
         
     | 
| 
       227 
227 
     | 
    
         
             
                  # @return [Boolean]
         
     | 
| 
       228 
228 
     | 
    
         
             
                  def subject_facet_field?(field)
         
     | 
| 
       229 
229 
     | 
    
         
             
                    return false unless field.respond_to?(:indicator2)
         
     | 
| 
         @@ -241,7 +241,7 @@ module PennMARC 
     | 
|
| 
       241 
241 
     | 
    
         
             
                  #       because we're using (where? - MK) "subdivision count" as a heuristic for the quality level of the
         
     | 
| 
       242 
242 
     | 
    
         
             
                  #       heading. - MG
         
     | 
| 
       243 
243 
     | 
    
         
             
                  # @todo do i need all this?
         
     | 
| 
       244 
     | 
    
         
            -
                  # @param [MARC::DataField] 
     | 
| 
      
 244 
     | 
    
         
            +
                  # @param field [MARC::DataField]
         
     | 
| 
       245 
245 
     | 
    
         
             
                  # @return [Hash{Symbol => Integer, Array, Boolean}, Nil]
         
     | 
| 
       246 
246 
     | 
    
         
             
                  def build_subject_hash(field)
         
     | 
| 
       247 
247 
     | 
    
         
             
                    term_info = { count: 0, parts: [], append: [], uri: nil,
         
     | 
| 
         @@ -291,7 +291,7 @@ module PennMARC 
     | 
|
| 
       291 
291 
     | 
    
         | 
| 
       292 
292 
     | 
    
         
             
                  # Determine if a field should be considered for Subject search inclusion. It must be either contained in
         
     | 
| 
       293 
293 
     | 
    
         
             
                  # {SEARCH_TAGS}, be an 880 field otherwise linked to a valid Search tag, or be in {LOCAL_TAGS}.
         
     | 
| 
       294 
     | 
    
         
            -
                  # @param [MARC::DataField] 
     | 
| 
      
 294 
     | 
    
         
            +
                  # @param field [MARC::DataField]
         
     | 
| 
       295 
295 
     | 
    
         
             
                  # @return [Boolean]
         
     | 
| 
       296 
296 
     | 
    
         
             
                  def subject_search_field?(field)
         
     | 
| 
       297 
297 
     | 
    
         
             
                    return false unless field.respond_to?(:indicator2) && VALID_SOURCE_INDICATORS.include?(field.indicator2)
         
     | 
| 
         @@ -305,7 +305,7 @@ module PennMARC 
     | 
|
| 
       305 
305 
     | 
    
         
             
                  end
         
     | 
| 
       306 
306 
     | 
    
         | 
| 
       307 
307 
     | 
    
         
             
                  # Is a given tag a subject search field? Yes if it is contained in {SEARCH_TAGS} or starts with 69.
         
     | 
| 
       308 
     | 
    
         
            -
                  # @param [String,  
     | 
| 
      
 308 
     | 
    
         
            +
                  # @param tag [String, nil]
         
     | 
| 
       309 
309 
     | 
    
         
             
                  # @return [Boolean]
         
     | 
| 
       310 
310 
     | 
    
         
             
                  def subject_search_tag?(tag)
         
     | 
| 
       311 
311 
     | 
    
         
             
                    return false if tag.blank?
         
     | 
| 
         @@ -317,7 +317,7 @@ module PennMARC 
     | 
|
| 
       317 
317 
     | 
    
         
             
                  # when we've only encountered one subfield, assume that it might be a poorly-coded record
         
     | 
| 
       318 
318 
     | 
    
         
             
                  # with a bunch of subdivisions mashed together, and attempt to convert it to a consistent
         
     | 
| 
       319 
319 
     | 
    
         
             
                  # form.
         
     | 
| 
       320 
     | 
    
         
            -
                  # @param [String] 
     | 
| 
      
 320 
     | 
    
         
            +
                  # @param first_part [String]
         
     | 
| 
       321 
321 
     | 
    
         
             
                  # @return [String, nil] normalized string
         
     | 
| 
       322 
322 
     | 
    
         
             
                  def normalize_single_subfield(first_part)
         
     | 
| 
       323 
323 
     | 
    
         
             
                    first_part.gsub!(/([[[:alnum:]])])(\s+--\s*|\s*--\s+)([[[:upper:]][[:digit:]]])/, '\1--\3')
         
     | 
| 
         @@ -326,8 +326,8 @@ module PennMARC 
     | 
|
| 
       326 
326 
     | 
    
         
             
                  end
         
     | 
| 
       327 
327 
     | 
    
         | 
| 
       328 
328 
     | 
    
         
             
                  # removes trailing comma or period, manipulating the string in place
         
     | 
| 
       329 
     | 
    
         
            -
                  # @param [String,  
     | 
| 
       330 
     | 
    
         
            -
                  # @return [String,  
     | 
| 
      
 329 
     | 
    
         
            +
                  # @param subject_part [String, nil]
         
     | 
| 
      
 330 
     | 
    
         
            +
                  # @return [String, nil]
         
     | 
| 
       331 
331 
     | 
    
         
             
                  def trim_trailing_commas_or_periods!(subject_part)
         
     | 
| 
       332 
332 
     | 
    
         
             
                    return if subject_part.blank?
         
     | 
| 
       333 
333 
     | 
    
         | 
| 
         @@ -35,7 +35,7 @@ module PennMARC 
     | 
|
| 
       35 
35 
     | 
    
         
             
                class << self
         
     | 
| 
       36 
36 
     | 
    
         
             
                  # Main Title Search field. Takes from {https://www.loc.gov/marc/bibliographic/bd245.html 245} and linked 880.
         
     | 
| 
       37 
37 
     | 
    
         
             
                  # @note Ported from get_title_1_search_values.
         
     | 
| 
       38 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 38 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       39 
39 
     | 
    
         
             
                  # @return [Array<String>] array of title values for search
         
     | 
| 
       40 
40 
     | 
    
         
             
                  def search(record)
         
     | 
| 
       41 
41 
     | 
    
         
             
                    record.fields(%w[245 880]).filter_map { |field|
         
     | 
| 
         @@ -47,7 +47,7 @@ module PennMARC 
     | 
|
| 
       47 
47 
     | 
    
         | 
| 
       48 
48 
     | 
    
         
             
                  # Auxiliary Title Search field. Takes from many fields defined in {AUX_TITLE_TAGS} that contain title-like
         
     | 
| 
       49 
49 
     | 
    
         
             
                  # information.
         
     | 
| 
       50 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 50 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       51 
51 
     | 
    
         
             
                  # @return [Array<String>] array of auxiliary title values for search
         
     | 
| 
       52 
52 
     | 
    
         
             
                  def search_aux(record)
         
     | 
| 
       53 
53 
     | 
    
         
             
                    values = search_aux_values(record: record, title_type: :main, &subfield_not_in?(%w[c 6 8])) +
         
     | 
| 
         @@ -60,7 +60,7 @@ module PennMARC 
     | 
|
| 
       60 
60 
     | 
    
         
             
                  # Journal Title Search field. Takes from {https://www.loc.gov/marc/bibliographic/bd245.html 245} and linked 880.
         
     | 
| 
       61 
61 
     | 
    
         
             
                  # We do not return any values if the {https://www.loc.gov/marc/bibliographic/bdleader.html MARC leader}
         
     | 
| 
       62 
62 
     | 
    
         
             
                  # indicates that the record is not a serial.
         
     | 
| 
       63 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 63 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       64 
64 
     | 
    
         
             
                  # @return [Array<String>] journal title information for search
         
     | 
| 
       65 
65 
     | 
    
         
             
                  def journal_search(record)
         
     | 
| 
       66 
66 
     | 
    
         
             
                    return [] if not_a_serial?(record)
         
     | 
| 
         @@ -75,7 +75,7 @@ module PennMARC 
     | 
|
| 
       75 
75 
     | 
    
         
             
                  # Auxiliary Journal Title Search field. Takes from many fields defined in {AUX_TITLE_TAGS} that contain title-like
         
     | 
| 
       76 
76 
     | 
    
         
             
                  # information. Does not return any titles if the {https://www.loc.gov/marc/bibliographic/bdleader.html MARC leader}
         
     | 
| 
       77 
77 
     | 
    
         
             
                  # indicates that the record is not a serial.
         
     | 
| 
       78 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 78 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       79 
79 
     | 
    
         
             
                  # @return [Array<String>] auxiliary journal title information for search
         
     | 
| 
       80 
80 
     | 
    
         
             
                  def journal_search_aux(record)
         
     | 
| 
       81 
81 
     | 
    
         
             
                    values = search_aux_values(record: record, title_type: :main, journal: true, &subfield_not_in?(%w[c 6 8])) +
         
     | 
| 
         @@ -90,7 +90,7 @@ module PennMARC 
     | 
|
| 
       90 
90 
     | 
    
         
             
                  # {https://www.oclc.org/bibformats/en/2xx/245.html#punctuation punctuation practices}.
         
     | 
| 
       91 
91 
     | 
    
         
             
                  # @todo still consider ǂh? medium, which OCLC doc says DO NOT USE...but that is OCLC...
         
     | 
| 
       92 
92 
     | 
    
         
             
                  # @todo is punctuation handling still as desired? treatment here is described in spreadsheet from 2011
         
     | 
| 
       93 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 93 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       94 
94 
     | 
    
         
             
                  # @return [String] single title for display
         
     | 
| 
       95 
95 
     | 
    
         
             
                  def show(record)
         
     | 
| 
       96 
96 
     | 
    
         
             
                    field = record.fields('245').first
         
     | 
| 
         @@ -117,7 +117,7 @@ module PennMARC 
     | 
|
| 
       117 
117 
     | 
    
         
             
                  #       title_sort_tl (text left justified). It is not yet clear why this distinction is useful. For now, use a
         
     | 
| 
       118 
118 
     | 
    
         
             
                  #       properly normalized (leading articles and punctuation removed) single title value here.
         
     | 
| 
       119 
119 
     | 
    
         
             
                  # @todo refactor to reduce complexity
         
     | 
| 
       120 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 120 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       121 
121 
     | 
    
         
             
                  # @return [String] title value for sorting
         
     | 
| 
       122 
122 
     | 
    
         
             
                  def sort(record)
         
     | 
| 
       123 
123 
     | 
    
         
             
                    title_field = record.fields('245').first
         
     | 
| 
         @@ -152,7 +152,7 @@ module PennMARC 
     | 
|
| 
       152 
152 
     | 
    
         | 
| 
       153 
153 
     | 
    
         
             
                  # @note this is simplified from legacy practice as a linking hash is not returned. I believe this only supported
         
     | 
| 
       154 
154 
     | 
    
         
             
                  #       title browse and we will not be supporting that at this time
         
     | 
| 
       155 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 155 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       156 
156 
     | 
    
         
             
                  # @return [Array<String>] Array of standardized titles as strings
         
     | 
| 
       157 
157 
     | 
    
         
             
                  def standardized_show(record)
         
     | 
| 
       158 
158 
     | 
    
         
             
                    standardized_titles = record.fields(%w[130 240]).map do |field|
         
     | 
| 
         @@ -181,7 +181,7 @@ module PennMARC 
     | 
|
| 
       181 
181 
     | 
    
         
             
                  # Data comes from 246 ({https://www.oclc.org/bibformats/en/2xx/246.htm OCLC docs}) and 740
         
     | 
| 
       182 
182 
     | 
    
         
             
                  # ({https://www.oclc.org/bibformats/en/7xx/740.html OCLC docs)}
         
     | 
| 
       183 
183 
     | 
    
         
             
                  #
         
     | 
| 
       184 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 184 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       185 
185 
     | 
    
         
             
                  # @return [Array<String>] Array of other titles as strings
         
     | 
| 
       186 
186 
     | 
    
         
             
                  def other_show(record)
         
     | 
| 
       187 
187 
     | 
    
         
             
                    other_titles = record.fields('246').map do |field|
         
     | 
| 
         @@ -207,7 +207,7 @@ module PennMARC 
     | 
|
| 
       207 
207 
     | 
    
         
             
                  # @note Ported from get_former_title_display. That method returns a hash for constructing a search link.
         
     | 
| 
       208 
208 
     | 
    
         
             
                  #       We may need to do something like that eventually.
         
     | 
| 
       209 
209 
     | 
    
         
             
                  # @todo what are e and w subfields?
         
     | 
| 
       210 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 210 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       211 
211 
     | 
    
         
             
                  # @return [Array<String>] array of former titles
         
     | 
| 
       212 
212 
     | 
    
         
             
                  def former_show(record)
         
     | 
| 
       213 
213 
     | 
    
         
             
                    record.fields
         
     | 
| 
         @@ -221,7 +221,7 @@ module PennMARC 
     | 
|
| 
       221 
221 
     | 
    
         
             
                  end
         
     | 
| 
       222 
222 
     | 
    
         | 
| 
       223 
223 
     | 
    
         
             
                  # Determine if the record is a "Host" bibliographic record for other bib records ("bound-withs")
         
     | 
| 
       224 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 224 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       225 
225 
     | 
    
         
             
                  # @return [Boolean]
         
     | 
| 
       226 
226 
     | 
    
         
             
                  def host_bib_record?(record)
         
     | 
| 
       227 
227 
     | 
    
         
             
                    record.fields('245').any? do |f|
         
     | 
| 
         @@ -235,7 +235,7 @@ module PennMARC 
     | 
|
| 
       235 
235 
     | 
    
         
             
                  # Create prefix/filing hash for representing a title value with filing characters removed, with special
         
     | 
| 
       236 
236 
     | 
    
         
             
                  # consideration for bracketed titles
         
     | 
| 
       237 
237 
     | 
    
         
             
                  # @todo Is this still useful?
         
     | 
| 
       238 
     | 
    
         
            -
                  # @param [String] 
     | 
| 
      
 238 
     | 
    
         
            +
                  # @param title [String]
         
     | 
| 
       239 
239 
     | 
    
         
             
                  # @return [Hash]
         
     | 
| 
       240 
240 
     | 
    
         
             
                  def handle_bracket_prefix(title)
         
     | 
| 
       241 
241 
     | 
    
         
             
                    if title.starts_with? '['
         
     | 
| 
         @@ -246,14 +246,14 @@ module PennMARC 
     | 
|
| 
       246 
246 
     | 
    
         
             
                  end
         
     | 
| 
       247 
247 
     | 
    
         | 
| 
       248 
248 
     | 
    
         
             
                  # Evaluate {https://www.loc.gov/marc/bibliographic/bdleader.html MARC leader} to determine if record is a serial.
         
     | 
| 
       249 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
      
 249 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
       250 
250 
     | 
    
         
             
                  # @return [Boolean]
         
     | 
| 
       251 
251 
     | 
    
         
             
                  def not_a_serial?(record)
         
     | 
| 
       252 
252 
     | 
    
         
             
                    !record.leader[6..7].ends_with?('s')
         
     | 
| 
       253 
253 
     | 
    
         
             
                  end
         
     | 
| 
       254 
254 
     | 
    
         | 
| 
       255 
     | 
    
         
            -
                  # @param [MARC::DataField] 
     | 
| 
       256 
     | 
    
         
            -
                  # @param [String] 
     | 
| 
      
 255 
     | 
    
         
            +
                  # @param field [MARC::DataField]
         
     | 
| 
      
 256 
     | 
    
         
            +
                  # @param value [String]
         
     | 
| 
       257 
257 
     | 
    
         
             
                  # @return [Boolean]
         
     | 
| 
       258 
258 
     | 
    
         
             
                  def indicators_are_not_value?(field, value)
         
     | 
| 
       259 
259 
     | 
    
         
             
                    field.indicator1 != value && field.indicator2 != value
         
     | 
| 
         @@ -263,10 +263,10 @@ module PennMARC 
     | 
|
| 
       263 
263 
     | 
    
         
             
                  # {https://www.loc.gov/marc/bibliographic/bdleader.html MARC leader} indicates that the record is not a serial.
         
     | 
| 
       264 
264 
     | 
    
         
             
                  # We take special consideration for the {https://www.loc.gov/marc/bibliographic/bd505.html 505 field}, extracting
         
     | 
| 
       265 
265 
     | 
    
         
             
                  # values only when indicator1 and indicator2 are both '0'.
         
     | 
| 
       266 
     | 
    
         
            -
                  # @param [MARC::Record] 
     | 
| 
       267 
     | 
    
         
            -
                  # @param [Symbol] 
     | 
| 
       268 
     | 
    
         
            -
                  # @param [Boolean] 
     | 
| 
       269 
     | 
    
         
            -
                  # @ 
     | 
| 
      
 266 
     | 
    
         
            +
                  # @param record [MARC::Record]
         
     | 
| 
      
 267 
     | 
    
         
            +
                  # @param title_type [Symbol]
         
     | 
| 
      
 268 
     | 
    
         
            +
                  # @param journal [Boolean]
         
     | 
| 
      
 269 
     | 
    
         
            +
                  # @param join_selector [Proc]
         
     | 
| 
       270 
270 
     | 
    
         
             
                  # @return [Array<String>]
         
     | 
| 
       271 
271 
     | 
    
         
             
                  def search_aux_values(record:, title_type:, journal: false, &join_selector)
         
     | 
| 
       272 
272 
     | 
    
         
             
                    return [] if journal && not_a_serial?(record)
         
     | 
| 
         @@ -1,8 +1,12 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
            " 
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            " 
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
            " 
     | 
| 
       8 
     | 
    
         
            -
            " 
     | 
| 
      
 1 
     | 
    
         
            +
            # Important!: These terms should be listed in an order of decreasing complexity so that terms that may be contained in
         
     | 
| 
      
 2 
     | 
    
         
            +
            # other terms are not replaced first, e.g., if "Aliens" is listed first, "Illegal Aliens" will get overrode to
         
     | 
| 
      
 3 
     | 
    
         
            +
            # read "Illegal Noncitizens".
         
     | 
| 
      
 4 
     | 
    
         
            +
            # Also, use lower case only in the key to support efficient case-insensitive matching.
         
     | 
| 
      
 5 
     | 
    
         
            +
            "illegal alien children": Undocumented immigrant children
         
     | 
| 
      
 6 
     | 
    
         
            +
            "alien detention centers": Immigrant detention centers
         
     | 
| 
      
 7 
     | 
    
         
            +
            "alien criminals": Noncitizen criminals
         
     | 
| 
      
 8 
     | 
    
         
            +
            "alien property": Foreign-owned property
         
     | 
| 
      
 9 
     | 
    
         
            +
            "illegal aliens": Undocumented immigrants
         
     | 
| 
      
 10 
     | 
    
         
            +
            "alien labor": Foreign workers
         
     | 
| 
      
 11 
     | 
    
         
            +
            gypsies: Romanies
         
     | 
| 
      
 12 
     | 
    
         
            +
            aliens: Noncitizens
         
     | 
    
        data/lib/pennmarc/parser.rb
    CHANGED
    
    | 
         @@ -12,7 +12,7 @@ module PennMARC 
     | 
|
| 
       12 
12 
     | 
    
         
             
              # Access point for magic calls to helper methods
         
     | 
| 
       13 
13 
     | 
    
         
             
              class Parser
         
     | 
| 
       14 
14 
     | 
    
         
             
                # Allow calls to `respond_to?` on parser instances to respond accurately by checking helper classes
         
     | 
| 
       15 
     | 
    
         
            -
                # @param [String, Symbol] 
     | 
| 
      
 15 
     | 
    
         
            +
                # @param name [String, Symbol]
         
     | 
| 
       16 
16 
     | 
    
         
             
                # @return [Boolean]
         
     | 
| 
       17 
17 
     | 
    
         
             
                def respond_to_missing?(name, include_private = false)
         
     | 
| 
       18 
18 
     | 
    
         
             
                  helper, method_name = parse_call(name)
         
     | 
| 
         @@ -26,9 +26,9 @@ module PennMARC 
     | 
|
| 
       26 
26 
     | 
    
         
             
                # Call helper class methods, passing along additional arguments as needed, e.g.:
         
     | 
| 
       27 
27 
     | 
    
         
             
                # #title_show -> PennMARC::Title.show
         
     | 
| 
       28 
28 
     | 
    
         
             
                # #subject_facet -> PennMARC::Subject.facet
         
     | 
| 
       29 
     | 
    
         
            -
                # @param [Symbol] 
     | 
| 
       30 
     | 
    
         
            -
                # @param [MARC::Record] 
     | 
| 
       31 
     | 
    
         
            -
                # @param [Array] 
     | 
| 
      
 29 
     | 
    
         
            +
                # @param name [Symbol]
         
     | 
| 
      
 30 
     | 
    
         
            +
                # @param record [MARC::Record]
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @param opts [Array]
         
     | 
| 
       32 
32 
     | 
    
         
             
                def method_missing(name, record, *opts)
         
     | 
| 
       33 
33 
     | 
    
         
             
                  helper, method_name = parse_call(name)
         
     | 
| 
       34 
34 
     | 
    
         
             
                  raise NoMethodError unless helper && method_name
         
     | 
| 
         @@ -44,7 +44,7 @@ module PennMARC 
     | 
|
| 
       44 
44 
     | 
    
         
             
                private
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
46 
     | 
    
         
             
                # Parse out a method call name in the way method_missing is configured to handle
         
     | 
| 
       47 
     | 
    
         
            -
                # @param [String, Symbol] 
     | 
| 
      
 47 
     | 
    
         
            +
                # @param name [String, Symbol]
         
     | 
| 
       48 
48 
     | 
    
         
             
                # @return [Array]
         
     | 
| 
       49 
49 
     | 
    
         
             
                def parse_call(name)
         
     | 
| 
       50 
50 
     | 
    
         
             
                  call = name.to_s.split('_')
         
     | 
| 
         @@ -8,23 +8,23 @@ module PennMARC 
     | 
|
| 
       8 
8 
     | 
    
         
             
                # Helper methods for use in constructing MARC objects for testing
         
     | 
| 
       9 
9 
     | 
    
         
             
                module MarcHelpers
         
     | 
| 
       10 
10 
     | 
    
         
             
                  # Return a MARC::XMLReader that will parse a given file and return MARC::Record objects
         
     | 
| 
       11 
     | 
    
         
            -
                  # @param [String] filename of MARCXML fixture
         
     | 
| 
      
 11 
     | 
    
         
            +
                  # @param filename [String] filename of MARCXML fixture
         
     | 
| 
       12 
12 
     | 
    
         
             
                  # @return [MARC::Record, NilClass]
         
     | 
| 
       13 
13 
     | 
    
         
             
                  def record_from(filename)
         
     | 
| 
       14 
14 
     | 
    
         
             
                    MARC::XMLReader.new(marc_xml_path(filename)).first
         
     | 
| 
       15 
15 
     | 
    
         
             
                  end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
                  # Create an isolated MARC::Subfield object for use in specs or as part of a MARC::Field
         
     | 
| 
       18 
     | 
    
         
            -
                  # @param [String] 
     | 
| 
       19 
     | 
    
         
            -
                  # @param [String] 
     | 
| 
      
 18 
     | 
    
         
            +
                  # @param code [String]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # @param value [String]
         
     | 
| 
       20 
20 
     | 
    
         
             
                  # @return [MARC::Subfield]
         
     | 
| 
       21 
21 
     | 
    
         
             
                  def marc_subfield(code, value)
         
     | 
| 
       22 
22 
     | 
    
         
             
                    MARC::Subfield.new code.to_s, value
         
     | 
| 
       23 
23 
     | 
    
         
             
                  end
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
                  # Return a new ControlField (000-009)
         
     | 
| 
       26 
     | 
    
         
            -
                  # @param [String] 
     | 
| 
       27 
     | 
    
         
            -
                  # @param [String] 
     | 
| 
      
 26 
     | 
    
         
            +
                  # @param tag [String]
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # @param value [String]
         
     | 
| 
       28 
28 
     | 
    
         
             
                  # @return [MARC::ControlField]
         
     | 
| 
       29 
29 
     | 
    
         
             
                  def marc_control_field(tag:, value:)
         
     | 
| 
       30 
30 
     | 
    
         
             
                    MARC::ControlField.new tag, value
         
     | 
| 
         @@ -38,10 +38,10 @@ module PennMARC 
     | 
|
| 
       38 
38 
     | 
    
         
             
                  #                         z: 'United States.',
         
     | 
| 
       39 
39 
     | 
    
         
             
                  #                         '0': http://id.loc.gov/authorities/subjects/sh2008112546 }
         
     | 
| 
       40 
40 
     | 
    
         
             
                  #            )
         
     | 
| 
       41 
     | 
    
         
            -
                  # @param [String (frozen)]  
     | 
| 
       42 
     | 
    
         
            -
                  # @param [String (frozen)] 
     | 
| 
       43 
     | 
    
         
            -
                  # @param [String (frozen)] 
     | 
| 
       44 
     | 
    
         
            -
                  # @param [Hash]  
     | 
| 
      
 41 
     | 
    
         
            +
                  # @param tag [String (frozen)] MARC tag, e.g., 001, 665
         
     | 
| 
      
 42 
     | 
    
         
            +
                  # @param indicator1 [String (frozen)]  MARC indicator 1, e.g., 0
         
     | 
| 
      
 43 
     | 
    
         
            +
                  # @param indicator2 [String (frozen)]
         
     | 
| 
      
 44 
     | 
    
         
            +
                  # @param subfields [Hash] hash of subfield values as code => value or code => [value, value]
         
     | 
| 
       45 
45 
     | 
    
         
             
                  # @return [MARC::DataField]
         
     | 
| 
       46 
46 
     | 
    
         
             
                  def marc_field(tag: 'TST', indicator1: ' ', indicator2: ' ', subfields: {})
         
     | 
| 
       47 
47 
     | 
    
         
             
                    subfield_objects = subfields.each_with_object([]) do |(code, value), array|
         
     | 
| 
         @@ -51,8 +51,8 @@ module PennMARC 
     | 
|
| 
       51 
51 
     | 
    
         
             
                  end
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
53 
     | 
    
         
             
                  # Return a MARC::Record containing passed in DataFields
         
     | 
| 
       54 
     | 
    
         
            -
                  # @param [Array<MARC::DataField>] 
     | 
| 
       55 
     | 
    
         
            -
                  # @param [String, nil] 
     | 
| 
      
 54 
     | 
    
         
            +
                  # @param fields [Array<MARC::DataField>]
         
     | 
| 
      
 55 
     | 
    
         
            +
                  # @param leader [String, nil]
         
     | 
| 
       56 
56 
     | 
    
         
             
                  # @return [MARC::Record]
         
     | 
| 
       57 
57 
     | 
    
         
             
                  def marc_record(fields: [], leader: nil)
         
     | 
| 
       58 
58 
     | 
    
         
             
                    record = MARC::Record.new
         
     | 
    
        data/lib/pennmarc/util.rb
    CHANGED
    
    | 
         @@ -56,7 +56,7 @@ module PennMARC 
     | 
|
| 
       56 
56 
     | 
    
         
             
                end
         
     | 
| 
       57 
57 
     | 
    
         | 
| 
       58 
58 
     | 
    
         
             
                # returns true if a given field has a given subfield value in a given array
         
     | 
| 
       59 
     | 
    
         
            -
                # @param field [MARC 
     | 
| 
      
 59 
     | 
    
         
            +
                # @param field [MARC::DataField]
         
     | 
| 
       60 
60 
     | 
    
         
             
                # @param subfield [String|Integer|Symbol]
         
     | 
| 
       61 
61 
     | 
    
         
             
                # @param array [Array]
         
     | 
| 
       62 
62 
     | 
    
         
             
                # @return [Boolean]
         
     | 
| 
         @@ -118,9 +118,9 @@ module PennMARC 
     | 
|
| 
       118 
118 
     | 
    
         
             
                end
         
     | 
| 
       119 
119 
     | 
    
         | 
| 
       120 
120 
     | 
    
         
             
                # Get all subfield values for a provided subfield from any occurrence of a provided tag/tags
         
     | 
| 
       121 
     | 
    
         
            -
                # @param tag [String 
     | 
| 
       122 
     | 
    
         
            -
                # @param subfield [String 
     | 
| 
       123 
     | 
    
         
            -
                # @param record [MARC::Record]
         
     | 
| 
      
 121 
     | 
    
         
            +
                # @param tag [String,Array] tags to consider
         
     | 
| 
      
 122 
     | 
    
         
            +
                # @param subfield [String,Symbol] subfield to take the values from
         
     | 
| 
      
 123 
     | 
    
         
            +
                # @param record [MARC::Record] source
         
     | 
| 
       124 
124 
     | 
    
         
             
                # @return [Array] array of subfield values
         
     | 
| 
       125 
125 
     | 
    
         
             
                def subfield_values_for(tag:, subfield:, record:)
         
     | 
| 
       126 
126 
     | 
    
         
             
                  record.fields(tag).flat_map do |field|
         
     | 
| 
         @@ -155,8 +155,8 @@ module PennMARC 
     | 
|
| 
       155 
155 
     | 
    
         
             
                end
         
     | 
| 
       156 
156 
     | 
    
         | 
| 
       157 
157 
     | 
    
         
             
                # trim trailing punctuation, manipulating string in place
         
     | 
| 
       158 
     | 
    
         
            -
                # @param trailer [Symbol 
     | 
| 
       159 
     | 
    
         
            -
                # @param string [String] to modify
         
     | 
| 
      
 158 
     | 
    
         
            +
                # @param trailer [Symbol,String] trailer to target for removal
         
     | 
| 
      
 159 
     | 
    
         
            +
                # @param string [String] string to modify
         
     | 
| 
       160 
160 
     | 
    
         
             
                # @return [String, Nil] string to modify
         
     | 
| 
       161 
161 
     | 
    
         
             
                def trim_trailing!(trailer, string)
         
     | 
| 
       162 
162 
     | 
    
         
             
                  string.sub! TRAILING_PUNCTUATIONS_PATTERNS[trailer.to_sym], ''
         
     | 
| 
         @@ -218,17 +218,17 @@ module PennMARC 
     | 
|
| 
       218 
218 
     | 
    
         
             
                end
         
     | 
| 
       219 
219 
     | 
    
         | 
| 
       220 
220 
     | 
    
         
             
                # Get the substring of a string up to a given target character
         
     | 
| 
       221 
     | 
    
         
            -
                # @param string [ 
     | 
| 
       222 
     | 
    
         
            -
                # @param target [ 
     | 
| 
       223 
     | 
    
         
            -
                # @return [String (frozen)]
         
     | 
| 
      
 221 
     | 
    
         
            +
                # @param string [String] string to split
         
     | 
| 
      
 222 
     | 
    
         
            +
                # @param target [String] character to split upon
         
     | 
| 
      
 223 
     | 
    
         
            +
                # @return [String (frozen), nil]
         
     | 
| 
       224 
224 
     | 
    
         
             
                def substring_before(string, target)
         
     | 
| 
       225 
225 
     | 
    
         
             
                  string.scan(target).present? ? string.split(target, 2).first : ''
         
     | 
| 
       226 
226 
     | 
    
         
             
                end
         
     | 
| 
       227 
227 
     | 
    
         | 
| 
       228 
228 
     | 
    
         
             
                # Get the substring of a string after the first occurrence of a target character
         
     | 
| 
       229 
     | 
    
         
            -
                # @param string [ 
     | 
| 
       230 
     | 
    
         
            -
                # @param target [ 
     | 
| 
       231 
     | 
    
         
            -
                # @return [String (frozen)]
         
     | 
| 
      
 229 
     | 
    
         
            +
                # @param string [String] string to split
         
     | 
| 
      
 230 
     | 
    
         
            +
                # @param target [String] character to split upon
         
     | 
| 
      
 231 
     | 
    
         
            +
                # @return [String (frozen), nil]
         
     | 
| 
       232 
232 
     | 
    
         
             
                def substring_after(string, target)
         
     | 
| 
       233 
233 
     | 
    
         
             
                  string.scan(target).present? ? string.split(target, 2).second : ''
         
     | 
| 
       234 
234 
     | 
    
         
             
                end
         
     | 
| 
         @@ -262,7 +262,7 @@ module PennMARC 
     | 
|
| 
       262 
262 
     | 
    
         
             
                # @todo handle case of receiving a URI? E.g., http://loc.gov/relator/aut
         
     | 
| 
       263 
263 
     | 
    
         
             
                # @param relator_code [String, NilClass]
         
     | 
| 
       264 
264 
     | 
    
         
             
                # @param mapping [Hash]
         
     | 
| 
       265 
     | 
    
         
            -
                # @return [String,  
     | 
| 
      
 265 
     | 
    
         
            +
                # @return [String, nil] full relator string
         
     | 
| 
       266 
266 
     | 
    
         
             
                def translate_relator(relator_code, mapping)
         
     | 
| 
       267 
267 
     | 
    
         
             
                  return if relator_code.blank?
         
     | 
| 
       268 
268 
     | 
    
         | 
| 
         @@ -272,7 +272,7 @@ module PennMARC 
     | 
|
| 
       272 
272 
     | 
    
         
             
                # Get 650 & 880 for Provenance and Chronology: prefix should be 'PRO' or 'CHR' and may be preceded by a '%'
         
     | 
| 
       273 
273 
     | 
    
         
             
                # @note 11/2018: do not display $5 in PRO or CHR subjs
         
     | 
| 
       274 
274 
     | 
    
         
             
                # @param record [MARC::Record]
         
     | 
| 
       275 
     | 
    
         
            -
                # @param prefix [String] to select from subject field
         
     | 
| 
      
 275 
     | 
    
         
            +
                # @param prefix [String] prefix to select from subject field
         
     | 
| 
       276 
276 
     | 
    
         
             
                # @return [Array] array of values
         
     | 
| 
       277 
277 
     | 
    
         
             
                def prefixed_subject_and_alternate(record, prefix)
         
     | 
| 
       278 
278 
     | 
    
         
             
                  record.fields(%w[650 880]).filter_map { |field|
         
     | 
| 
         @@ -340,7 +340,7 @@ module PennMARC 
     | 
|
| 
       340 
340 
     | 
    
         | 
| 
       341 
341 
     | 
    
         
             
                  relator = subfield_values(field, '4').filter_map { |code| translate_relator(code, relator_map) }
         
     | 
| 
       342 
342 
     | 
    
         | 
| 
       343 
     | 
    
         
            -
                  relator = subfield_values(field, relator_term_sf) if relator.blank?
         
     | 
| 
      
 343 
     | 
    
         
            +
                  relator = subfield_values(field, relator_term_sf).map { |term| trim_trailing(:comma, term) } if relator.blank?
         
     | 
| 
       344 
344 
     | 
    
         | 
| 
       345 
345 
     | 
    
         
             
                  relator = append_trailing(:period, relator.join(', ')) if relator.present?
         
     | 
| 
       346 
346 
     | 
    
         | 
| 
         @@ -349,9 +349,9 @@ module PennMARC 
     | 
|
| 
       349 
349 
     | 
    
         | 
| 
       350 
350 
     | 
    
         
             
                # Returns a relator value of the given field. Like append_relator, it prioritizes relator codes found in subfileld
         
     | 
| 
       351 
351 
     | 
    
         
             
                # $4 and falls back to the specified relator term subfield relator_term_sf if no valid codes are found in $4
         
     | 
| 
       352 
     | 
    
         
            -
                # @param [MARC::Field]  
     | 
| 
       353 
     | 
    
         
            -
                # @param [String]  
     | 
| 
       354 
     | 
    
         
            -
                # @param [Hash] 
     | 
| 
      
 352 
     | 
    
         
            +
                # @param field [MARC::Field] where relator values are stored
         
     | 
| 
      
 353 
     | 
    
         
            +
                # @param relator_term_sf [String] MARC subfield that stores relator term
         
     | 
| 
      
 354 
     | 
    
         
            +
                # @param relator_map [Hash]
         
     | 
| 
       355 
355 
     | 
    
         
             
                # @return [String]
         
     | 
| 
       356 
356 
     | 
    
         
             
                def relator(field:, relator_term_sf:, relator_map: Mappers.relator)
         
     | 
| 
       357 
357 
     | 
    
         
             
                  relator = subfield_values(field, '4').filter_map { |code| translate_relator(code, relator_map) }
         
     | 
    
        data/lib/pennmarc/version.rb
    CHANGED
    
    
    
        data/pennmarc.gemspec
    CHANGED
    
    | 
         @@ -21,7 +21,6 @@ Gem::Specification.new do |s| 
     | 
|
| 
       21 
21 
     | 
    
         
             
              s.add_dependency 'activesupport', '~> 7'
         
     | 
| 
       22 
22 
     | 
    
         
             
              s.add_dependency 'library_stdnums', '~> 1.6'
         
     | 
| 
       23 
23 
     | 
    
         
             
              s.add_dependency 'marc', '~> 1.2'
         
     | 
| 
       24 
     | 
    
         
            -
              s.add_dependency 'multi_string_replace', '~> 2.0'
         
     | 
| 
       25 
24 
     | 
    
         
             
              s.add_dependency 'nokogiri', '~> 1.15'
         
     | 
| 
       26 
25 
     | 
    
         | 
| 
       27 
26 
     | 
    
         
             
              s.metadata['rubygems_mfa_required'] = 'false'
         
     | 
| 
         @@ -1,8 +1,8 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            describe 'PennMARC::HeadingControl' do
         
     | 
| 
       4 
     | 
    
         
            -
              let(:replace_term) { PennMARC::Mappers.heading_overrides. 
     | 
| 
       5 
     | 
    
         
            -
              let(:replaced_term) { PennMARC::Mappers.heading_overrides. 
     | 
| 
      
 4 
     | 
    
         
            +
              let(:replace_term) { PennMARC::Mappers.heading_overrides.keys[2] }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:replaced_term) { PennMARC::Mappers.heading_overrides.values[2] }
         
     | 
| 
       6 
6 
     | 
    
         
             
              let(:remove_term) { PennMARC::Mappers.headings_to_remove.first }
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
              describe '.process' do
         
     | 
| 
         @@ -23,15 +23,22 @@ describe 'PennMARC::HeadingControl' do 
     | 
|
| 
       23 
23 
     | 
    
         
             
                  end
         
     | 
| 
       24 
24 
     | 
    
         
             
                end
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                 
     | 
| 
       27 
     | 
    
         
            -
                   
     | 
| 
       28 
     | 
    
         
            -
                     
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
      
 26 
     | 
    
         
            +
                PennMARC::Mappers.heading_overrides.each do |target, replacement|
         
     | 
| 
      
 27 
     | 
    
         
            +
                  context "with the \"#{target}\" term" do
         
     | 
| 
      
 28 
     | 
    
         
            +
                    it 'replaces the term in isolation' do
         
     | 
| 
      
 29 
     | 
    
         
            +
                      values = [target]
         
     | 
| 
      
 30 
     | 
    
         
            +
                      expect(PennMARC::HeadingControl.term_override(values)).to eq [replacement]
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    it 'replaces the term when used with other headings' do
         
     | 
| 
      
 34 
     | 
    
         
            +
                      values = ["#{target}--History"]
         
     | 
| 
      
 35 
     | 
    
         
            +
                      expect(PennMARC::HeadingControl.term_override(values)).to eq ["#{replacement}--History"]
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
       31 
37 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
                    it 'replaces the term regardless of case' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                      values = ["#{target.titleize}--History"]
         
     | 
| 
      
 40 
     | 
    
         
            +
                      expect(PennMARC::HeadingControl.term_override(values)).to eq ["#{replacement}--History"]
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
       35 
42 
     | 
    
         
             
                  end
         
     | 
| 
       36 
43 
     | 
    
         
             
                end
         
     | 
| 
       37 
44 
     | 
    
         | 
| 
         @@ -9,9 +9,9 @@ describe 'PennMARC::Creator' do 
     | 
|
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                context 'with a single author record' do
         
     | 
| 
       11 
11 
     | 
    
         
             
                  let(:fields) do
         
     | 
| 
       12 
     | 
    
         
            -
                    [marc_field(tag: '100', subfields: { a: 'Surname, Name', '0': 'http://cool.uri/12345',
         
     | 
| 
      
 12 
     | 
    
         
            +
                    [marc_field(tag: '100', subfields: { a: 'Surname, Name,', '0': 'http://cool.uri/12345',
         
     | 
| 
       13 
13 
     | 
    
         
             
                                                         e: 'author', d: '1900-2000' }),
         
     | 
| 
       14 
     | 
    
         
            -
                     marc_field(tag: '880', subfields: { a: 'Surname, Alternative', '6': '100' })]
         
     | 
| 
      
 14 
     | 
    
         
            +
                     marc_field(tag: '880', subfields: { a: 'Surname, Alternative,', '6': '100' })]
         
     | 
| 
       15 
15 
     | 
    
         
             
                  end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
                  it 'contains the expected search field values for a single author work' do
         
     | 
| 
         @@ -109,18 +109,21 @@ describe 'PennMARC::Creator' do 
     | 
|
| 
       109 
109 
     | 
    
         
             
                  end
         
     | 
| 
       110 
110 
     | 
    
         
             
                end
         
     | 
| 
       111 
111 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                context 'with  
     | 
| 
      
 112 
     | 
    
         
            +
                context 'with five author records - abbreviated names' do
         
     | 
| 
       113 
113 
     | 
    
         
             
                  let(:fields) do
         
     | 
| 
       114 
     | 
    
         
            -
                    [marc_field(tag: '100', subfields: { a: 'Surname, Alex', '0': 'http://cool.uri/12345', d: '1900-2000',
         
     | 
| 
      
 114 
     | 
    
         
            +
                    [marc_field(tag: '100', subfields: { a: 'Surname, Alex, ', '0': 'http://cool.uri/12345', d: '1900-2000',
         
     | 
| 
       115 
115 
     | 
    
         
             
                                                         e: 'author.', '4': 'http://cool.uri/vocabulary/relators/aut' }),
         
     | 
| 
       116 
     | 
    
         
            -
                     marc_field(tag: '110', subfields: { a: 'Second, NameX', '0': 'http://cool.uri/12345', d: '1901-2010',
         
     | 
| 
      
 116 
     | 
    
         
            +
                     marc_field(tag: '110', subfields: { a: 'Second, NameX,  ', '0': 'http://cool.uri/12345', d: '1901-2010',
         
     | 
| 
       117 
117 
     | 
    
         
             
                                                         e: 'author.', '4': 'http://cool.uri/vocabulary/relators/aut' }),
         
     | 
| 
       118 
     | 
    
         
            -
                     marc_field(tag: '700', subfields: { a: 'Alt, Alternative', '6': '100', d: '1970-' }) 
     | 
| 
      
 118 
     | 
    
         
            +
                     marc_field(tag: '700', subfields: { a: 'Alt, Alternative', '6': '100', d: '1970-' }),
         
     | 
| 
      
 119 
     | 
    
         
            +
                     marc_field(tag: '100', subfields: { a: 'Name with no comma', e: 'author' }),
         
     | 
| 
      
 120 
     | 
    
         
            +
                     marc_field(tag: '100', subfields: { a: 'Name ends with comma,', e: 'author' })]
         
     | 
| 
       119 
121 
     | 
    
         
             
                  end
         
     | 
| 
       120 
122 
     | 
    
         | 
| 
       121 
123 
     | 
    
         
             
                  it 'returns single author values with no URIs anywhere' do
         
     | 
| 
       122 
124 
     | 
    
         
             
                    values = helper.authors_list(record, first_initial_only: true)
         
     | 
| 
       123 
     | 
    
         
            -
                    expect(values).to contain_exactly 'Surname, A.', 'Second, N.', 'Alt, A.'
         
     | 
| 
      
 125 
     | 
    
         
            +
                    expect(values).to contain_exactly 'Surname, A.', 'Second, N.', 'Alt, A.',
         
     | 
| 
      
 126 
     | 
    
         
            +
                                                      'Name ends with comma', 'Name with no comma'
         
     | 
| 
       124 
127 
     | 
    
         
             
                  end
         
     | 
| 
       125 
128 
     | 
    
         
             
                end
         
     | 
| 
       126 
129 
     | 
    
         
             
              end
         
     | 
| 
         @@ -132,14 +135,14 @@ describe 'PennMARC::Creator' do 
     | 
|
| 
       132 
135 
     | 
    
         
             
                  let(:fields) do
         
     | 
| 
       133 
136 
     | 
    
         
             
                    [marc_field(tag: '100', subfields: { a: 'Hamilton, Alex', '0': 'http://cool.uri/12345', d: '1900-2000',
         
     | 
| 
       134 
137 
     | 
    
         
             
                                                         e: 'author.' }),
         
     | 
| 
       135 
     | 
    
         
            -
                     marc_field(tag: '100', subfields: { a: 'Lincoln, Abraham', b: 'I', c: 'laureate', d: '1968', e: 'author',
         
     | 
| 
       136 
     | 
    
         
            -
                                                         j: 'pseud', q: 'Fuller Name', u: 'affiliation', '3': 'materials',
         
     | 
| 
      
 138 
     | 
    
         
            +
                     marc_field(tag: '100', subfields: { a: 'Lincoln, Abraham,   ', b: 'I', c: 'laureate', d: '1968', e: 'author',
         
     | 
| 
      
 139 
     | 
    
         
            +
                                                         j: 'pseud', q: 'Fuller Name,  ', u: 'affiliation', '3': 'materials',
         
     | 
| 
       137 
140 
     | 
    
         
             
                                                         '4': 'aut' }),
         
     | 
| 
       138 
141 
     | 
    
         
             
                     marc_field(tag: '700', subfields: { a: 'Einstein, Albert', '6': '100', d: '1970-', '4': 'trl',
         
     | 
| 
       139 
142 
     | 
    
         
             
                                                         e: 'translator' }),
         
     | 
| 
       140 
143 
     | 
    
         
             
                     marc_field(tag: '700', subfields: { a: 'Franklin, Ben', '6': '100', d: '1970-', '4': 'edt' }),
         
     | 
| 
       141 
144 
     | 
    
         
             
                     marc_field(tag: '710', subfields: { a: 'Jefferson, Thomas', '6': '100', d: '1870-', '4': 'edt' }),
         
     | 
| 
       142 
     | 
    
         
            -
                     marc_field(tag: '700', subfields: { a: 'Dickens, Charles', '6': '100', d: '1970-', '4': 'com' })]
         
     | 
| 
      
 145 
     | 
    
         
            +
                     marc_field(tag: '700', subfields: { a: 'Dickens, Charles, ', '6': '100', d: '1970-', '4': 'com' })]
         
     | 
| 
       143 
146 
     | 
    
         
             
                  end
         
     | 
| 
       144 
147 
     | 
    
         | 
| 
       145 
148 
     | 
    
         
             
                  it 'returns two authors and four contributors' do
         
     | 
| 
         @@ -153,7 +156,7 @@ describe 'PennMARC::Creator' do 
     | 
|
| 
       153 
156 
     | 
    
         | 
| 
       154 
157 
     | 
    
         
             
                context 'with two authors and four contributors records, with full information and relator' do
         
     | 
| 
       155 
158 
     | 
    
         
             
                  let(:fields) do
         
     | 
| 
       156 
     | 
    
         
            -
                    [marc_field(tag: '100', subfields: { a: 'Hamilton, Alex', '0': 'http://cool.uri/12345', d: '1900-2000',
         
     | 
| 
      
 159 
     | 
    
         
            +
                    [marc_field(tag: '100', subfields: { a: 'Hamilton, Alex,  ', '0': 'http://cool.uri/12345', d: '1900-2000',
         
     | 
| 
       157 
160 
     | 
    
         
             
                                                         e: 'author.', '4': 'aut' }),
         
     | 
| 
       158 
161 
     | 
    
         
             
                     marc_field(tag: '100', subfields: { a: 'Lincoln, Abraham', b: 'I', c: 'laureate', d: '1968', e: 'author',
         
     | 
| 
       159 
162 
     | 
    
         
             
                                                         j: 'pseud', q: 'Fuller Name', u: 'affiliation', '3': 'materials',
         
     | 
| 
         @@ -164,7 +167,7 @@ describe 'PennMARC::Creator' do 
     | 
|
| 
       164 
167 
     | 
    
         
             
                     marc_field(tag: '710', subfields: { a: 'Jefferson, Thomas', '6': '100', d: '1870-', '4': 'edt' }),
         
     | 
| 
       165 
168 
     | 
    
         
             
                     marc_field(tag: '700', subfields: { a: 'Dickens, Charles', '6': '100', d: '1970-', '4': 'com' }),
         
     | 
| 
       166 
169 
     | 
    
         
             
                     marc_field(tag: '880', subfields: { a: '狄更斯', '6': '700', d: '1970-', '4': 'com' }),
         
     | 
| 
       167 
     | 
    
         
            -
                     marc_field(tag: '700', subfields: { a: 'Twain, Mark', '6': '100', d: '1870-' })]
         
     | 
| 
      
 170 
     | 
    
         
            +
                     marc_field(tag: '700', subfields: { a: 'Twain, Mark,', '6': '100', d: '1870-' })]
         
     | 
| 
       168 
171 
     | 
    
         
             
                  end
         
     | 
| 
       169 
172 
     | 
    
         | 
| 
       170 
173 
     | 
    
         
             
                  it 'returns four contributors' do
         
     |