• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / lsp-data / c71c594a-a277-4514-8d89-b789e7a04d24

11 Aug 2025 06:19PM UTC coverage: 99.884% (-0.1%) from 100.0%
c71c594a-a277-4514-8d89-b789e7a04d24

Pull #111

circleci

mzelesky
refine oclc_record_match
Pull Request #111: create oclc match class

59 of 60 new or added lines in 3 files covered. (98.33%)

858 of 859 relevant lines covered (99.88%)

4.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.18
/lib/lsp-data/oclc_record_match.rb
1
# frozen_string_literal: true
2

3
module LspData
1✔
4
  ### Return all matched records by a standard number identifier
5
  ###   and have a separate method to return records deemed acceptable
6
  ###   for copy cataloging
7
  ### Must provide a Z3950Connection object for OCLC
8
  ### identifier_type is either `isbn` or 'oclc'
9
  class OCLCRecordMatch
1✔
10
    attr_reader :identifier, :identifier_type, :conn
1✔
11

12
    def initialize(identifier:, identifier_type:, conn:)
1✔
13
      @identifier = identifier
3✔
14
      @identifier_type = identifier_type
3✔
15
      @conn = conn
3✔
16
    end
17

18
    def records
1✔
19
      search_index = case identifier_type
3✔
20
                     when 'isbn'
21
                       7
2✔
22
                     when 'oclc'
23
                       12
1✔
24
                     end
25
      return unless search_index
3✔
26

27
      result = conn.search_by_id(index: search_index, identifier: identifier)
3✔
28
      result.reject(&:nil?)
3✔
29
    end
30

31
    def filtered_records(title)
1✔
32
      all_records = records
2✔
33
      all_records&.select { |record| acceptable_record?(record, title) }
20✔
34
    end
35

36
    private
1✔
37

38
    def acceptable_leader?(record)
1✔
39
      [' ', '1', '4', 'I', 'M', 'L'].include?(record.leader[17]) &&
15✔
40
        record.leader[6..7] == 'am'
41
    end
42

43
    def belle_lettres?(record)
1✔
44
      %w[1 d f j m p].include?(record['008'].value[33])
3✔
45
    end
46

47
    def acceptable_subject?(record)
1✔
48
      record.fields('600'..'655').any? { |field| field.indicator2 == '0' }
6✔
49
    end
50

51
    def pcc050?(record)
1✔
52
      record.fields('042').any? { |f| f['a'] == 'pcc' } && record['050']
17✔
53
    end
54

55
    def call_num050?(record)
1✔
56
      record.fields('050').any? { |f| f['a'] =~ /\d/ }
5✔
57
    end
58

59
    def dlc040?(record)
1✔
60
      record['040'] =~ /DLC/
7✔
61
    end
62

63
    def lc?(record)
1✔
64
      record.fields('050').any? { |f| f.indicator1 == '0' || f.indicator2 == '0' } &&
27✔
65
        dlc040?(record) &&
66
        record.fields('010').any? { |f| f['a'] }
2✔
67
    end
68

69
    def electronic_reproduction_fixed_fields?(record)
1✔
70
      record.fields('006').any? { |field| field.value[0] == 'm' } ||
3✔
NEW
71
        record.fields('007').any? { |field| field.value[0] == 'c' }
×
72
    end
73

74
    def electronic_reproduction?(record)
1✔
75
      electronic_reproduction_fixed_fields?(record) ||
2✔
76
        record.fields('245').any? { |field| field['h'] } ||
1✔
77
        record.fields('533').size.positive?
78
    end
79

80
    def normalize_string(string)
1✔
81
      strip_punctuation(string).unicode_normalize(:nfd)
8✔
82
                               .gsub(/\p{InCombiningDiacriticalMarks}/, '')
83
                               .downcase
84
    end
85

86
    def strip_punctuation(string)
1✔
87
      string.gsub('%22', '')
8✔
88
            .gsub(/^\s*[aA]\s+/, '')
89
            .gsub(/^\s*[aA]n\s+/, '')
90
            .gsub(/^\s*[Tt]he\s+/, '')
91
            .gsub(/['{}]/, '')
92
            .gsub('&', 'and')
93
            .gsub(/[\u0020-\u0025\u0028-\u002f]/, '')
94
            .gsub(/[\u003a-\u0040\u005b-\u0060]/, '')
95
            .gsub(/[\u007c\u007e\u00a9]/, '')
96
    end
97

98
    def process_title(title)
1✔
99
      normalized = normalize_string(title)
8✔
100
      "#{normalized[5..9]}#{normalized[14..18]}"
8✔
101
    end
102

103
    def title_match?(record, title)
1✔
104
      process_title(title) == process_title(record['245']['a'])
4✔
105
    end
106

107
    def acceptable_non_lc?(record)
1✔
108
      acceptable_leader?(record) &&
15✔
109
        acceptable_f040b?(record) &&
110
        (belle_lettres?(record) || acceptable_subject?(record)) &&
3✔
111
        call_num050?(record) &&
112
        electronic_reproduction?(record)
113
    end
114

115
    def acceptable_record?(record, title)
1✔
116
      (lc?(record) || pcc050?(record) || acceptable_non_lc?(record)) &&
18✔
117
        title_match?(record, title)
118
    end
119

120
    def acceptable_f040b?(record)
1✔
121
      record['040']['b'].nil? || record['040']['b'] == 'eng'
8✔
122
    end
123
  end
124
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc