Class: PennMARC::Creator

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

Overview

TODO:

can there ever be multiple 100 fields? can ǂe and ǂ4 both be used at the same time? seems to result in duplicate values

Do Creator & Author field processing. Main methods pull from 110 and 111 fields.

Constant Summary collapse

TAGS =

Main tags for Author/Creator information

%w[100 110].freeze
DISPLAY_EXCLUDED_SUBFIELDS =

For creator fields intended for display, these subfields are ignored

%w[a 0 1 4 5 6 8 t].freeze
SEARCH_EXCLUDED_SUBFIELDS =

For creator fields intended for searching, these subfields are ignored

%w[a 1 4 5 6 8 t].freeze
AUX_TAGS =

Aux tags for Author/Creator information, for use in search_aux method

%w[100 110 111 400 410 411 700 710 711 800 810 811].freeze
CONFERENCE_SEARCH_TAGS =
%w[111 711 811].freeze
CORPORATE_SEARCH_TAGS =
%w[110 710 810].freeze
CONTRIBUTOR_TAGS =
%w[700 710].freeze
CONTRIBUTOR_DISPLAY_SUBFIELDS =
%w[a b c d j q u 3].freeze
FACET_SOURCE_MAP =
{
  100 => 'abcdjq', 110 => 'abcdjq', 111 => 'abcen',
  700 => 'abcdjq', 710 => 'abcdjq', 711 => 'abcen',
  800 => 'abcdjq', 810 => 'abcdjq', 811 => 'abcen'
}.freeze

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

.authors_list(record, main_tags_only: false, first_initial_only: false) ⇒ Array<String>

Returns the list of authors with name (subfield $a) only

Parameters:

  • record (MARC::Record)
  • main_tags_only (Boolean) (defaults to: false)

    only use TAGS; otherwise use both TAGS and CONTRIBUTOR_TAGS

  • first_initial_only (Boolean) (defaults to: false)

    only use the first initial instead of first name

Returns:

  • (Array<String>)

    names of the authors



123
124
125
126
127
128
129
130
131
# File 'lib/pennmarc/helpers/creator.rb', line 123

def authors_list(record, main_tags_only: false, first_initial_only: false)
  fields = record.fields(main_tags_only ? TAGS : TAGS + CONTRIBUTOR_TAGS)
  fields.filter_map { |field|
    if field['a'].present?
      name = trim_trailing(:comma, field['a'])
      first_initial_only ? abbreviate_name(name) : name
    end
  }.uniq
end

.conference_detail_show(record, relator_map: Mappers.relator) ⇒ Array<String>

TODO:

what is ǂi for?

Note:

ported from get_conference_values

Conference detailed display, intended for record show page. Retrieve conference values for record display from 111, 711 , and their linked 880s. If there is no $i, we join subfield $i we join subfield values other than $0, $4, $5, $6, $8, $e, $j, and $w. to create the conference value. We then join the conference subunit value using subfields $e and $w. We append any relators, preferring those defined in $4 and using $j as a fallback.

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    array of conference values



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/pennmarc/helpers/creator.rb', line 234

def conference_detail_show(record, relator_map: Mappers.relator)
  conferences = record.fields(%w[111 711]).filter_map do |field|
    next unless field.indicator2.in? ['', ' ']

    parse_conference_detail_show_value(field, relator_map: relator_map)
  end
  conferences += record.fields('880').filter_map do |field|
    next unless subfield_value? field, '6', /^(111|711)/

    next if subfield_defined? field, 'i'

    conf = join_subfields(field, &subfield_not_in?(%w[0 4 5 6 8 e j w]))
    sub_unit = join_subfields(field, &subfield_in?(%w[e w]))
    conf = [conf, sub_unit].compact_blank.join(' ')

    append_relator(field: field, joined_subfields: conf, relator_term_sf: 'j', relator_map: relator_map)
  end
  conferences.uniq
end

.conference_detail_show_facet_map(record, relator_map: Mappers.relator) ⇒ Hash

Return hash of detailed conference values mapped to their corresponding facets from fields 111 and 711. Does not include linked 880s.

Parameters:

  • record (MARC::Record)
  • relator_map (Hash) (defaults to: Mappers.relator)

Returns:

  • (Hash)


260
261
262
263
264
265
266
267
268
269
270
# File 'lib/pennmarc/helpers/creator.rb', line 260

def conference_detail_show_facet_map(record, relator_map: Mappers.relator)
  conferences = record.fields(%w[111 711]).filter_map do |field|
    next unless field.indicator2.in? ['', ' ']

    show = parse_conference_detail_show_value(field, relator_map: relator_map)
    facet = parse_facet_value(field, FACET_SOURCE_MAP[field.tag.to_i].chars)
    { show: show, facet: facet }
  end

  conferences.to_h { |conf| [conf[:show], conf[:facet]] }
end

.conference_search(record) ⇒ Array<String>

Conference name values for searching

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)


275
276
277
278
279
# File 'lib/pennmarc/helpers/creator.rb', line 275

def conference_search(record)
  record.fields(CONFERENCE_SEARCH_TAGS).filter_map { |field|
    join_subfields(field, &subfield_in?(%w[a c d e]))
  }.uniq
end

.conference_show(record, relator_map: Mappers.relator) ⇒ Array<String>

Note:

ported from get_conference_values

Conference for display, intended for results display

Parameters:

  • record (MARC::Record)
  • relator_map (Hash) (defaults to: Mappers.relator)

Returns:

  • (Array<String>)

    array of conference values



219
220
221
222
223
# File 'lib/pennmarc/helpers/creator.rb', line 219

def conference_show(record, relator_map: Mappers.relator)
  record.fields('111').filter_map { |field|
    name_from_main_entry field, relator_map
  }.uniq
end

.contributor_show(record, relator_map: Mappers.relator, name_only: false, vernacular: true) ⇒ Array<String>

Note:

legacy version returns array of hash objects including data for display link

Retrieve contributor values for display from fields 700 and 710 and their linked alternates. Joins subfields defined in CONTRIBUTOR_DISPLAY_SUBFIELDS, then appends resulting string with any encoded relationships found in $4. If there are no valid encoded relationships, uses the value found in $e.

Parameters:

  • record (MARC::Record)
  • relator_map (Hash) (defaults to: Mappers.relator)
  • name_only (Boolean) (defaults to: false)
  • vernacular (Boolean) (defaults to: true)

Returns:

  • (Array<String>)


300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/pennmarc/helpers/creator.rb', line 300

def contributor_show(record, relator_map: Mappers.relator, name_only: false, vernacular: true)
  indicator_2_options = ['', ' ', '0']
  fields = record.fields(CONTRIBUTOR_TAGS)
  if vernacular
    fields += record.fields('880').select { |f| subfield_value?(f, '6', /^(#{CONTRIBUTOR_TAGS.join('|')})/) }
  end
  sf = name_only ? %w[a] : CONTRIBUTOR_DISPLAY_SUBFIELDS
  fields.filter_map { |field|
    next if indicator_2_options.exclude?(field.indicator2) && field.tag.in?(CONTRIBUTOR_TAGS)
    next if subfield_defined? field, 'i'

    contributor = join_subfields(field, &subfield_in?(sf))
    append_relator(field: field, joined_subfields: contributor, relator_term_sf: 'e', relator_map: relator_map)
  }.uniq
end

.contributors_list(record, relator_map: Mappers.relator, include_authors: true, name_only: true, vernacular: false) ⇒ Hash

Show the authors and contributors grouped together by relators with only names

Parameters:

  • record (MARC::Record)
  • relator_map (Hash) (defaults to: Mappers.relator)
  • include_authors (Boolean) (defaults to: true)

    include author fields TAGS

  • name_only (Boolean) (defaults to: true)

    include only the name subfield $a

  • vernacular (Boolean) (defaults to: false)

    include field 880 with subfield $6

Returns:

  • (Hash)


140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/pennmarc/helpers/creator.rb', line 140

def contributors_list(record, relator_map: Mappers.relator, include_authors: true, name_only: true,
                      vernacular: false)
  indicator_2_options = ['', ' ', '0']
  tags = CONTRIBUTOR_TAGS

  fields = record.fields(tags)
  fields += record.fields('880').select { |field| subfield_value_in?(field, '6', CONTRIBUTOR_TAGS) } if vernacular

  contributors = {}
  fields.each do |field|
    next if indicator_2_options.exclude?(field.indicator2) && field.tag.in?(CONTRIBUTOR_TAGS)
    next if subfield_defined? field, 'i'

    relator = relator(field: field, relator_term_sf: 'e', relator_map: relator_map)
    relator = 'Contributor' if relator.blank?
    relator = trim_punctuation(relator).capitalize

    name = trim_trailing(:comma, field['a'])
    name = "#{name} #{join_subfields(field, &subfield_in?(%w[b c d j q u 3]))}, #{relator}" unless name_only

    if contributors.key?(relator)
      contributors[relator].push(name)
    else
      contributors[relator] = [name]
    end
  end

  # add the authors
  if include_authors
    authors = authors_list(record, main_tags_only: true)
    if contributors.key?('Author')
      contributors['Author'] += authors
    else
      contributors['Author'] = authors
    end
  end
  contributors
end

.corporate_search(record) ⇒ Array<String>

Corporate author search values for searching

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)


284
285
286
287
288
# File 'lib/pennmarc/helpers/creator.rb', line 284

def corporate_search(record)
  record.fields(CORPORATE_SEARCH_TAGS).filter_map do |field|
    join_subfields(field, &subfield_in?(%w[a b c d]))
  end
end

.extended_show(record, relator_map: Mappers.relator) ⇒ Array<String>

Show more credited authors - both 100 field and 700 entries where the relator term is aut

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    array of author/creator values for display



91
92
93
94
95
96
97
98
99
# File 'lib/pennmarc/helpers/creator.rb', line 91

def extended_show(record, relator_map: Mappers.relator)
  fields = record.fields(%w[100 700])
  fields.filter_map { |field|
    # for 700 entries, only include ones with relator code of aut
    next if (field.tag == '700') && field['4']&.downcase != 'aut'

    parse_show_value(field, relator_map: relator_map)
  }.uniq
end

.extended_show_facet_map(record, relator_map: Mappers.relator) ⇒ Hash

Hash with extended creators show values as the fields and the corresponding facet as the values. Only include 100, and 700 with relator of aut

Parameters:

  • record (MARC::Record)
  • relator_map (Hash) (defaults to: Mappers.relator)

Returns:

  • (Hash)


106
107
108
109
110
111
112
113
114
115
116
# File 'lib/pennmarc/helpers/creator.rb', line 106

def extended_show_facet_map(record, relator_map: Mappers.relator)
  creators = record.fields(%w[100 700]).filter_map do |field|
    # for 700 entries, only include ones with relator code of aut
    next if (field.tag == '700') && field['4']&.downcase != 'aut'

    show = parse_show_value(field, relator_map: relator_map)
    facet = parse_facet_value(field, FACET_SOURCE_MAP[field.tag.to_i].chars)
    { show: show, facet: facet }
  end
  creators.to_h { |h| [h[:show], h[:facet]] }
end

.facet(record) ⇒ Array<String>

TODO:

should trim_punctuation apply to each subfield value, or the joined values? i think the joined values

Author/Creator for faceting. Grabs values from a plethora of fields, joins defined subfields, then trims some punctuation (@see Util.trim_punctuation)

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    array of author/creator values for faceting



206
207
208
209
210
211
212
# File 'lib/pennmarc/helpers/creator.rb', line 206

def facet(record)
  FACET_SOURCE_MAP.flat_map { |field_num, subfields|
    record.fields(field_num.to_s).map do |field|
      parse_facet_value(field, subfields.chars)
    end
  }.uniq
end

.search(record, relator_map: Mappers.relator) ⇒ Array<String>

Author/Creator search field, from tags 100 Main Entry–Personal Name and 110 Main Entry–Corporate Name. Includes subfield values except for those in the DISPLAY_EXCLUDED_SUBFIELDS constant. Maps any relator codes found in ǂ4. To better handle name searches, returns names as both “First Last” and “Last, First” if a comma is found in ǂa. Also indexes any linked values in the 880.

Parameters:

  • record (MARC::Record)
  • relator_map (Hash) (defaults to: Mappers.relator)

Returns:

  • (Array<String>)

    array of author/creator values for indexing



42
43
44
# File 'lib/pennmarc/helpers/creator.rb', line 42

def search(record, relator_map: Mappers.relator)
  name_search_values record: record, tags: TAGS, relator_map: relator_map
end

.search_aux(record, relator_map: Mappers.relator) ⇒ Array<String>

Auxiliary Author/Creator search field This duplicates the values returned by the search method, but adds in additional MARC tags to include creator-adjacent entities. The added 4xx tags are mostly obsolete, but the 7xx tags are important. See: MARC 700, MARC 710, and MARC 711. The 800, 810 and 8111 tags are similar in theme to the 7xx fields but apply to serial records. Includes all subfield values except those in the SEARCH_EXCLUDED_SUBFIELDS constant.

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    array of extended author/creator values for indexing



56
57
58
# File 'lib/pennmarc/helpers/creator.rb', line 56

def search_aux(record, relator_map: Mappers.relator)
  name_search_values record: record, tags: AUX_TAGS, relator_map: relator_map
end

.show(record, relator_map: Mappers.relator) ⇒ Array<String>

Retrieve creator values for display from fields 100, 110 and their linked alternates. First, join each subfield value except for those defined in the DISPLAY_EXCLUDED_SUBFIELDS constant. Then, appends any encoded relators found in $4. If there are no valid encoded relators, uses the value found in $e.

Parameters:

  • record (MARC::Record)

Returns:

  • (Array<String>)

    array of author/creator values for display



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

def show(record, relator_map: Mappers.relator)
  fields = record.fields(TAGS)
  fields += record.fields('880').select { |field| subfield_value?(field, '6', /^(#{TAGS.join('|')})/) }
  fields.filter_map { |field|
    parse_show_value(field, relator_map: relator_map)
  }.uniq
end

.show_aux(record, relator_map: Mappers.relator) ⇒ Array<String>

Note:

ported from get_author_creator_values (indexed as author_creator_a) - shown on results page

All author/creator values for display (like #show, but multivalued?) - no 880 linkage Performs additional normalization of author names

Parameters:

  • record (MARC::Record)
  • relator_map (Hash) (defaults to: Mappers.relator)

Returns:

  • (Array<String>)

    array of author/creator values for display



185
186
187
188
189
# File 'lib/pennmarc/helpers/creator.rb', line 185

def show_aux(record, relator_map: Mappers.relator)
  record.fields(TAGS).map { |field|
    name_from_main_entry(field, relator_map)
  }.uniq
end

.show_facet_map(record, relator_map: Mappers.relator) ⇒ Hash

Hash with main creator show values as the fields and the corresponding facet as the values. Does not include linked 880s.

Parameters:

  • record (MARC::Record)
  • relator_map (Hash) (defaults to: Mappers.relator)

Returns:

  • (Hash)


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

def show_facet_map(record, relator_map: Mappers.relator)
  creators = record.fields(TAGS).filter_map do |field|
    show = parse_show_value(field, relator_map: relator_map)
    facet = parse_facet_value(field, FACET_SOURCE_MAP[field.tag.to_i].chars)
    { show: show, facet: facet }
  end
  creators.to_h { |h| [h[:show], h[:facet]] }
end

.sort(record) ⇒ String

TODO:

This includes any URI from ǂ0 which could help to disambiguate in sorts, but ǂ1 is excluded…

Note:

ported from get_author_creator_sort_values

Author/Creator sort. Does not map or include any relator codes.

Parameters:

  • record (MARC::Record)

Returns:

  • (String)

    string with author/creator value for sorting



196
197
198
199
# File 'lib/pennmarc/helpers/creator.rb', line 196

def sort(record)
  field = record.fields(TAGS).first
  join_subfields(field, &subfield_not_in?(%w[1 4 6 8 e]))
end