Class: PennMARC::Title

Inherits:
Helper
  • Object
show all
Defined in:
lib/pennmarc/helpers/title.rb

Overview

This helper contains logic for parsing out Title and Title-related fields.

Constant Summary collapse

AUX_TITLE_TAGS =

We use these fields when retrieving auxiliary titles in the *search_aux methods: 130, 210, 245, 246, 247, 440, 490, 730, 740, 830, 773, 774, 780, 785, 700, 710, 711, 505

{
  main: %w[130 210 240 245 246 247 440 490 730 740 830],
  related: %w[773 774 780 785],
  entity: %w[700 710 711],
  note: %w[505]
}.freeze
HOST_BIB_TITLE =

This text is used in Alma to indicate a Bib record is a “Host” record for other bibs (bound-withs)

'Host bibliographic record for boundwith'

Constants included from Util

Util::TRAILING_PUNCTUATIONS_PATTERNS

Class Method Summary collapse

Methods included from Util

#append_relator, #append_trailing, #datafield_and_linked_alternate, #field_defined?, #field_or_its_linked_alternate?, #join_and_squish, #join_subfields, #linked_alternate, #linked_alternate_not_6_or_8, #no_subfield_value_matches?, #prefixed_subject_and_alternate, #relator, #relator_join_separator, #relator_term_subfield, #remove_paren_value_from_subfield_i, #subfield_defined?, #subfield_in?, #subfield_not_in?, #subfield_undefined?, #subfield_value?, #subfield_value_in?, #subfield_value_not_in?, #subfield_values, #subfield_values_for, #substring_after, #substring_before, #translate_relator, #trim_punctuation, #trim_trailing, #trim_trailing!, #valid_subject_genre_source_code?

Class Method Details

.alternate_show(record) ⇒ String?

Same structure as show, but linked alternate title.

Parameters:

  • record (MARC::Record)

Returns:

  • (String, nil)

    alternate title for display



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/pennmarc/helpers/title.rb', line 113

def alternate_show(record)
  field = record.fields('880').filter_map { |alternate_field|
    next unless subfield_value?(alternate_field, '6', /^245/)

    alternate_field
  }.first
  return unless field

  values = title_values(field)
  [format_title(values[:title_or_form]), values[:punctuation], values[:other_info]].compact_blank.join(' ')
end

.detailed_show(record) ⇒ String

Same as show, but with all subfields included as found - except for subfield c.

Parameters:

  • record (MARC::Record)

Returns:

  • (String)

    detailed title for display



103
104
105
106
107
108
# File 'lib/pennmarc/helpers/title.rb', line 103

def detailed_show(record)
  field = record.fields('245')&.first
  return unless field

  join_subfields(field, &subfield_not_in?(%w[6 8]))
end

.former_show(record) ⇒ Array<String>

TODO:

what are e and w subfields?

Note:

Ported from get_former_title_display. That method returns a hash for constructing a search link. We may need to do something like that eventually.

Former Title for display. These values come from 247.

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    array of former titles



225
226
227
228
229
230
231
232
233
234
235
# File 'lib/pennmarc/helpers/title.rb', line 225

def former_show(record)
  record.fields
        .filter_map { |field|
          next unless field.tag == '247' || (field.tag == '880' && subfield_value?(field, '6', /^247/))

          # 6 and 8 are not meaningful for display
          former_title = join_subfields field, &subfield_not_in?(%w[6 8 e w])
          former_title_append = join_subfields field, &subfield_in?(%w[e w])
          "#{former_title} #{former_title_append}".strip
        }.uniq
end

.host_bib_record?(record) ⇒ Boolean

Determine if the record is a “Host” bibliographic record for other bib records (“bound-withs”)

Parameters:

  • record (MARC::Record)

Returns:

  • (Boolean)


240
241
242
243
244
245
# File 'lib/pennmarc/helpers/title.rb', line 240

def host_bib_record?(record)
  record.fields('245').any? do |f|
    title = join_subfields(f, &subfield_in?(%w[a]))
    title.include?(HOST_BIB_TITLE)
  end
end

.journal_search(record) ⇒ Array<String>

Journal Title Search field. Takes from 245 and linked 880. We do not return any values if the MARC leader indicates that the record is not a serial.

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    journal title information for search



65
66
67
68
69
70
71
72
73
# File 'lib/pennmarc/helpers/title.rb', line 65

def journal_search(record)
  return [] if not_a_serial?(record)

  record.fields(%w[245 880]).filter_map { |field|
    next if field.tag == '880' && no_subfield_value_matches?(field, '6', /^245/)

    join_subfields(field, &subfield_not_in?(%w[c 6 8 h]))
  }.uniq
end

.journal_search_aux(record) ⇒ Array<String>

Auxiliary Journal Title Search field. Takes from many fields defined in AUX_TITLE_TAGS that contain title-like information. Does not return any titles if the MARC leader indicates that the record is not a serial.

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    auxiliary journal title information for search



80
81
82
83
84
85
86
# File 'lib/pennmarc/helpers/title.rb', line 80

def journal_search_aux(record)
  values = search_aux_values(record: record, title_type: :main, journal: true, &subfield_not_in?(%w[c 6 8])) +
           search_aux_values(record: record, title_type: :related, journal: true, &subfield_not_in?(%w[s t])) +
           search_aux_values(record: record, title_type: :entity, journal: true, &subfield_in?(%w[t])) +
           search_aux_values(record: record, title_type: :note, journal: true, &subfield_in?(%w[t]))
  values.uniq
end

.other_show(record) ⇒ Array<String>

Other Title for display

Data comes from 246 (OCLC docs) and 740 (OCLC docs)

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    Array of other titles as strings



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/pennmarc/helpers/title.rb', line 199

def other_show(record)
  other_titles = record.fields('246').map do |field|
    join_subfields(field, &subfield_not_in?(%w[6 8]))
  end
  other_titles += record.fields('740')
                        .filter_map do |field|
    next unless field.indicator2.in? ['', ' ', '0', '1', '3']

    join_subfields(field, &subfield_not_in?(%w[5 6 8]))
  end
  titles = other_titles + record.fields('880').filter_map do |field|
    next unless subfield_value? field, '6', /^(246|740)/

    join_subfields(field, &subfield_not_in?(%w[5 6 8]))
  end
  titles.uniq
end

.search(record) ⇒ Array<String>

Note:

Ported from get_title_1_search_values.

Main Title Search field. Takes from 245 and linked 880.

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    array of title values for search



40
41
42
43
44
45
46
# File 'lib/pennmarc/helpers/title.rb', line 40

def search(record)
  record.fields(%w[245 880]).filter_map { |field|
    next if field.tag == '880' && no_subfield_value_matches?(field, '6', /^245/)

    join_subfields(field, &subfield_not_in?(%w[c 6 8 h]))
  }.uniq
end

.search_aux(record) ⇒ Array<String>

Auxiliary Title Search field. Takes from many fields defined in AUX_TITLE_TAGS that contain title-like information.

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    array of auxiliary title values for search



52
53
54
55
56
57
58
# File 'lib/pennmarc/helpers/title.rb', line 52

def search_aux(record)
  values = search_aux_values(record: record, title_type: :main, &subfield_not_in?(%w[c 6 8])) +
           search_aux_values(record: record, title_type: :related, &subfield_not_in?(%w[s t])) +
           search_aux_values(record: record, title_type: :entity, &subfield_in?(%w[t])) +
           search_aux_values(record: record, title_type: :note, &subfield_in?(%w[t]))
  values.uniq
end

.show(record) ⇒ String

TODO:

is punctuation handling still as desired? treatment here is described in spreadsheet from 2011

Single-valued Title, for use in headings. Takes the first 245 value. Special consideration for punctuation practices.

Parameters:

  • record (MARC::Record)

Returns:

  • (String)

    single title for display



94
95
96
97
98
# File 'lib/pennmarc/helpers/title.rb', line 94

def show(record)
  field = record.fields('245')&.first
  values = title_values(field)
  [format_title(values[:title_or_form]), values[:punctuation], values[:other_info]].compact_blank.join(' ')
end

.sort(record) ⇒ String

TODO:

refactor to reduce complexity

Note:

Currently we index two “title sort” fields: title_nssort (ssort type - regex token filter applied) and title_sort_tl (text left justified). It is not yet clear why this distinction is useful. For now, use a properly normalized (leading articles and punctuation removed) single title value here.

Canonical title with non-filing characters relocated to the end.

Parameters:

  • record (MARC::Record)

Returns:

  • (String)

    title value for sorting



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/pennmarc/helpers/title.rb', line 133

def sort(record)
  title_field = record.fields('245').first
  return unless title_field.present?

  # attempt to get number of non-filing characters present, default to 0
  offset = if /^[0-9]$/.match?(title_field.indicator2)
             title_field.indicator2.to_i
           else
             0
           end
  raw_title = join_subfields(title_field, &subfield_in?(['a'])) # get title from subfield a
  value = if offset.between?(1, 9)
            { prefix: raw_title[0..offset - 1]&.strip, filing: raw_title[offset..]&.strip }
          elsif raw_title.present?
            handle_bracket_prefix raw_title
          else
            # no subfield a, no indicator
            raw_form = join_subfields(title_field, &subfield_in?(['k']))
            handle_bracket_prefix raw_form
          end
  value[:filing] = [value[:filing],
                    join_subfields(title_field, &subfield_in?(%w[b n p]))].compact_blank.join(' ')
  [value[:filing], value[:prefix]].join(' ').strip
end

.standardized_show(record) ⇒ Array<String>

Note:

this is simplified from legacy practice as a linking hash is not returned. I believe this only supported title browse and we will not be supporting that at this time

Returns Array of standardized titles as strings.

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    Array of standardized titles as strings



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/pennmarc/helpers/title.rb', line 170

def standardized_show(record)
  standardized_titles = record.fields(%w[130 240]).map do |field|
    join_subfields(field, &subfield_not_in?(%w[0 6 8 e w]))
  end
  standardized_titles += record.fields('730').filter_map do |field|
    # skip unless one of the indicators is blank
    next unless field.indicator1 == '' || field.indicator2 == ''

    # skip if a subfield i is present
    next if subfield_defined?(field, 'i')

    join_subfields(field, &subfield_not_in?(%w[5 6 8 e w]))
  end
  titles = standardized_titles + record.fields('880').filter_map do |field|
    next unless subfield_undefined?(field, 'i') &&
                subfield_value?(field, '6', /^(130|240|730)/)

    join_subfields field, &subfield_not_in?(%w[5 6 8 e w])
  end
  titles.uniq
end