Class: PennMARC::Subject

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

Overview

This helper extracts subject heading in various ways to facilitate searching, faceting and display of subject values. Michael Gibney did a lot to “clean up” Subject parsing in discovery-app, but much of it was intended to support features (xfacet) that we will no longer support, and ties display and xfacet field parsing together too tightly to be preserved. As a result fo this, display methods and facet methods below are ported from their state prior to Michael’s 2/2021 subject parsing changes.

Constant Summary collapse

SEARCH_TAGS =
TODO:

why are 541 and 561 included here? these fields include info about source of acquisition

Tags that serve as sources for Subject search values

%w[541 561 600 610 611 630 650 651 653].freeze
SEARCH_SOURCE_INDICATORS =

Valid indicator 2 values indicating the source thesaurus for subject terms. These are:

  • 0: LCSH

  • 1: LC Children’s

  • 2: MeSH

  • 4: Source not specified (local?)

  • 7: Source specified in ǂ2

%w[0 1 2 4 7].freeze
DISPLAY_TAGS =

Tags that serve as sources for Subject facet values

%w[600 610 611 630 650 651].freeze
LOCAL_TAGS =

Local subject heading tags

%w[690 691 697].freeze

Class Method Summary collapse

Methods included from Util

#datafield_and_linked_alternate, #join_and_squish, #join_subfields, #linked_alternate, #linked_alternate_not_6_or_8, #prefixed_subject_and_alternate, #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_trailing, #valid_subject_genre_source_code?

Class Method Details

.childrens_show(record) ⇒ Array

Get Subjects from “Children” ontology



93
94
95
96
97
98
99
100
101
# File 'lib/pennmarc/helpers/subject.rb', line 93

def childrens_show(record)
  subject_fields(record, type: :display, options: { tags: DISPLAY_TAGS, indicator2: '1' })
    .filter_map { |field|
      term_hash = build_subject_hash(field)
      next if term_hash.blank? || term_hash[:count]&.zero?

      format_term type: :display, term: term_hash
    }.uniq
end

.facet(record) ⇒ Array

Note:

this is ported mostly form MG’s new-style Subject parsing

All Subjects for faceting



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

def facet(record)
  subject_fields(record, type: :facet).filter_map do |field|
    term_hash = build_subject_hash(field)
    next if term_hash.blank? || term_hash[:count]&.zero?

    format_term type: :facet, term: term_hash
  end
end

.local_show(record) ⇒ Array

Get Subject values from DISPLAY_TAGS where indicator2 is 4 and LOCAL_TAGS. Do not include any values where sf2 includes “penncoi” (Community of Interest).



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

def local_show(record)
  local_fields = subject_fields(record, type: :display, options: { tags: DISPLAY_TAGS, indicator2: '4' }) +
                 subject_fields(record, type: :local)
  local_fields.filter_map { |field|
    next if subfield_value?(field, '2', /penncoi/)

    term_hash = build_subject_hash(field)
    next if term_hash.blank? || term_hash[:count]&.zero?

    format_term type: :display, term: term_hash
  }.uniq
end

.medical_show(record) ⇒ Array

Get Subjects from “MeSH” ontology



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

def medical_show(record)
  subject_fields(record, type: :display, options: { tags: DISPLAY_TAGS, indicator2: '2' })
    .filter_map { |field|
      term_hash = build_subject_hash(field)
      next if term_hash.blank? || term_hash[:count]&.zero?

      format_term type: :display, term: term_hash
    }.uniq
end

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

TODO:

this includes subfields that may not be desired like 1 (uri) and 2 (source code) but this might be OK for a search (non-display) field?

All Subjects for searching. This includes most subfield content from any field contained in SEARCH_TAGS or 69X, including any linked 880 fields. Fields must have an indicator2 value in SEARCH_SOURCE_INDICATORS.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/pennmarc/helpers/subject.rb', line 36

def search(record, relator_map: Mappers.relator)
  subject_fields(record, type: :search).filter_map do |field|
    subj_parts = field.filter_map do |subfield|
      # TODO: use term hash here? pro/chr would be rejected...
      # TODO: should we care about punctuation in a search field? relator mapping?
      case subfield.code
      when '5', '6', '8' then next
      when 'a'
        # remove %PRO or PRO or %CHR or CHR
        # remove any ? at the end
        subfield.value.gsub(/^%?(PRO|CHR)/, '').gsub(/\?$/, '').strip
      when '4'
        # sf 4 should contain a 3-letter code or URI "that specifies the relationship from the entity described
        # in the record to the entity referenced in the field"
        "#{subfield.value} #{translate_relator(subfield.value.to_sym, relator_map)}".strip
      else
        subfield.value
      end
    end
    next if subj_parts.empty?

    join_and_squish subj_parts
  end
end

.show(record) ⇒ Array

All Subjects for display. This includes all DISPLAY_TAGS and LOCAL_TAGS. For tags that specify a source, only those with an allowed source code (see ALLOWED_SOURCE_CODES) are included.



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

def show(record)
  subject_fields(record, type: :all).filter_map { |field|
    term_hash = build_subject_hash(field)
    next if term_hash.blank? || term_hash[:count]&.zero?

    format_term type: :display, term: term_hash
  }.uniq
end