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

pulibrary / bibdata / 474603db-3a91-41f8-a417-232df02b6c05

19 Aug 2025 09:09PM UTC coverage: 89.972% (-2.1%) from 92.112%
474603db-3a91-41f8-a417-232df02b6c05

Pull #2870

circleci

christinach
Refactor items_by_852 method
Extract code and write non_private_items in Rust

Co-authored-by: Jane Sandberg <sandbergja@users.noreply.github.com>
Pull Request #2870: Refactor items_by_852 method

1 of 15 new or added lines in 3 files covered. (6.67%)

153 existing lines in 7 files now uncovered.

6980 of 7758 relevant lines covered (89.97%)

329.49 hits per line

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

49.52
/marc_to_solr/lib/process_holdings_helpers.rb
1
class ProcessHoldingsHelpers
1✔
2
  attr_reader :record, :marc_breaker
1✔
3

4
  def initialize(record:, marc_breaker:)
1✔
5
    @record = record
40✔
6
    @marc_breaker = marc_breaker
40✔
7
  end
8

9
  def holding_id(field_852)
1✔
10
    if field_852['8'] && alma?(field_852)
4✔
11
      holding_id = field_852['8']
4✔
UNCOV
12
    elsif field_852['0'] && scsb?(field_852)
×
UNCOV
13
      holding_id = field_852['0']
×
14
    end
15
  end
16

17
  def alma?(field_852)
1✔
18
    BibdataRs::Marc.alma_code_start_22?(field_852['8'].to_s)
6✔
19
  end
20

21
  def scsb?(field_852)
1✔
22
    BibdataRs::Marc.is_scsb?(marc_breaker) && field_852['0']
4✔
23
  end
24

25
  def group_866_867_868_on_holding_perm_id(holding_perm_id, field_852)
1✔
26
    if scsb?(field_852)
2✔
UNCOV
27
      record.fields('866'..'868').select { |f| f['0'] == holding_perm_id }
×
28
    else
29
      record.fields('866'..'868').select { |f| f['8'] == holding_perm_id }
2✔
30
    end
31
  end
32

33
  def items_by_852(field_852)
1✔
34
    holding_id = holding_id(field_852)
2✔
35
    BibdataRs::Marc.non_private_items?(marc_breaker, holding_id)
2✔
36
  end
37

38
  def private_scsb_item?(field_876, field_852)
1✔
UNCOV
39
    field_876['x'] == 'Private' && scsb?(field_852)
×
40
  end
41

42
  # Select 852 fields from an Alma or SCSB record
43
  # returns an array of MARC 852 (full holdings) fields
44
  def fields_852_alma_or_scsb
1✔
45
    record.fields('852').select do |f|
40✔
46
      BibdataRs::Marc.alma_code_start_22?(f['8'].to_s) || (BibdataRs::Marc.is_scsb?(marc_breaker) && f['0'])
2✔
47
    end
48
  end
49

50
  # Build the current location code from 876$y and 876$z
51
  def current_location_code(field_876)
1✔
UNCOV
52
    "#{field_876['y']}$#{field_876['z']}" if field_876['y'] && field_876['z']
×
53
  end
54

55
  # Build the permanent location code from 852$b and 852$c
56
  # Do not append the 852c if it is a SCSB - we save the SCSB locations as scsbnypl and scsbcul
57
  def permanent_location_code(field_852)
1✔
58
    if alma?(field_852)
2✔
59
      "#{field_852['b']}$#{field_852['c']}"
2✔
60
    else
UNCOV
61
      field_852['b']
×
62
    end
63
  end
64

65
  # Select 876 fields (items) with permanent location. 876 location is equal to the 852 permanent location.
66
  def select_permanent_location_876(group_876_fields, field_852)
1✔
67
    return group_876_fields if /^scsb/.match?(field_852['b'])
2✔
68

69
    group_876_fields.select do |field_876|
2✔
UNCOV
70
      !in_temporary_location(field_876, field_852)
×
71
    end
72
  end
73

74
  # Select 876 fields (items) with current location. 876 location is NOT equal to the 852 permanent location.
75
  def select_temporary_location_876(group_876_fields, field_852)
1✔
UNCOV
76
    return [] if /^scsb/.match?(field_852['b'])
×
77

UNCOV
78
    group_876_fields.select do |field_876|
×
UNCOV
79
      in_temporary_location(field_876, field_852)
×
80
    end
81
  end
82

83
  def in_temporary_location(field_876, field_852)
1✔
84
    # temporary location is any item whose 876 and 852 do not match
UNCOV
85
    current_location_code(field_876) != permanent_location_code(field_852)
×
86
  end
87

88
  def build_call_number(field_852)
1✔
89
    # rubocop:disable Rails/CompactBlank
90
    call_number = [field_852['h'], field_852['i'], field_852['k'], field_852['j']].reject(&:blank?)
4✔
91
    # rubocop:enable Rails/CompactBlank
92
    call_number.present? ? call_number.join(' ').strip : []
4✔
93
  end
94

95
  def includes_only_private_scsb_items?(field_852)
1✔
96
    return false unless scsb?(field_852)
2✔
97

NEW
98
    items_by_852(field_852)
×
99
  end
100

101
  # Builds the holding, without any item-specific information
102
  # @returns [Hash]
103
  def build_holding(field_852, field_876 = nil, permanent:)
1✔
104
    holding = {}
2✔
105
    if permanent
2✔
106
      holding['location_code'] = permanent_location_code(field_852)
2✔
107
      holding['location'] = Traject::TranslationMap.new('locations', default: '__passthrough__')[holding['location_code']]
2✔
108
      holding['library'] = Traject::TranslationMap.new('location_display', default: '__passthrough__')[holding['location_code']]
2✔
109
    else
UNCOV
110
      holding['location_code'] = current_location_code(field_876)
×
UNCOV
111
      holding['current_location'] = Traject::TranslationMap.new('locations', default: '__passthrough__')[holding['location_code']]
×
UNCOV
112
      holding['current_library'] = Traject::TranslationMap.new('location_display', default: '__passthrough__')[holding['location_code']]
×
113
    end
114

115
    holding['call_number'] = build_call_number(field_852)
2✔
116
    holding['call_number_browse'] = build_call_number(field_852)
2✔
117
    # Updates current holding key; values are from 852
118
    if field_852['k']
2✔
UNCOV
119
      holding['sub_location'] = []
×
UNCOV
120
      holding['sub_location'] << field_852['k']
×
121
    end
122
    if field_852['l']
2✔
123
      holding['shelving_title'] = []
×
124
      holding['shelving_title'] << field_852['l']
×
125
    end
126
    if field_852['z']
2✔
UNCOV
127
      holding['location_note'] = []
×
UNCOV
128
      holding['location_note'] << field_852['z']
×
129
    end
130
    holding
2✔
131
  end
132

133
  # Build the items array in all_holdings hash
134
  def holding_items(value:, all_holdings:, item:)
1✔
UNCOV
135
    if all_holdings[value].present?
×
UNCOV
136
      all_holdings[value]['items'] ||= []
×
UNCOV
137
      all_holdings[value]['items'] << item
×
138
    end
UNCOV
139
    all_holdings
×
140
  end
141

142
  def build_item(field_852:, field_876:)
1✔
UNCOV
143
    is_scsb = scsb?(field_852)
×
UNCOV
144
    item = {}
×
UNCOV
145
    item[:holding_id] = field_876['0'] if field_876['0']
×
UNCOV
146
    item[:description] = field_876['3'] if field_876['3']
×
UNCOV
147
    item[:id] = field_876['a'] if field_876['a']
×
UNCOV
148
    item[:status_at_load] = field_876['j'] if field_876['j']
×
UNCOV
149
    item[:barcode] = field_876['p'] if field_876['p']
×
UNCOV
150
    item[:copy_number] = field_876['t'] if field_876['t']
×
UNCOV
151
    item[:use_statement] = field_876['h'] if field_876['h'] && is_scsb
×
UNCOV
152
    item[:storage_location] = field_876['l'] if field_876['l'] && is_scsb
×
UNCOV
153
    if field_876['x']
×
UNCOV
154
      if is_scsb
×
UNCOV
155
        item[:cgd] = field_876['x']
×
156
      else
UNCOV
157
        item[:process_type] = field_876['x']
×
158
      end
159
    end
UNCOV
160
    item[:collection_code] = field_876['z'] if field_876['z'] && is_scsb
×
UNCOV
161
    item
×
162
  end
163

164
  def process_866_867_868_fields(fields:, all_holdings:, holding_id:)
1✔
UNCOV
165
    fields.each do |field|
×
UNCOV
166
      all_holdings[holding_id]['location_has'] ||= []
×
UNCOV
167
      all_holdings[holding_id]['supplements'] ||= []
×
UNCOV
168
      all_holdings[holding_id]['indexes'] ||= []
×
UNCOV
169
      all_holdings[holding_id]['location_has'] << parse_textual_holdings(field, '866')
×
UNCOV
170
      all_holdings[holding_id]['supplements'] << parse_textual_holdings(field, '867')
×
UNCOV
171
      all_holdings[holding_id]['indexes'] << parse_textual_holdings(field, '868')
×
172
    end
UNCOV
173
    all_holdings
×
174
  end
175

176
  def parse_textual_holdings(field, field_tag)
1✔
UNCOV
177
    textual_holdings = []
×
UNCOV
178
    textual_holdings << field['a'] if field.tag == field_tag && field['a']
×
UNCOV
179
    textual_holdings << field['z'] if field.tag == field_tag && field['z']
×
UNCOV
180
    textual_holdings.join(' ') if textual_holdings.present?
×
181
  end
182
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