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

pulibrary / bibdata / 1dcebae2-3318-4e77-bc53-82276e293354

02 May 2025 04:45PM UTC coverage: 28.256% (-63.9%) from 92.189%
1dcebae2-3318-4e77-bc53-82276e293354

push

circleci

sandbergja
Add basic infrastructure for compiling rust code

* Add a rake compile task to compile
* Run the rake task in CI
* Run the rake task before rspec tests with the rust tag, to provide quick feedback on rust changes in TDD cycles

2 of 7 new or added lines in 2 files covered. (28.57%)

2467 existing lines in 97 files now uncovered.

1089 of 3854 relevant lines covered (28.26%)

0.29 hits per line

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

24.14
/app/adapters/alma_adapter/availability_status.rb
1
class AlmaAdapter
1✔
2
  class AvailabilityStatus
1✔
3
    # @param bib [Alma::Bib]
4
    def self.from_bib(bib:)
1✔
UNCOV
5
      new(bib:)
×
6
    end
7

8
    attr_reader :bib
1✔
9

10
    def initialize(bib:, deep_check: false)
1✔
UNCOV
11
      @bib = bib
×
UNCOV
12
      @deep_check = deep_check
×
13
    end
14

15
    # Returns availability information for each of the holdings in the Bib record.
16
    def bib_availability
1✔
UNCOV
17
      sequence = 0
×
UNCOV
18
      holdings.each_with_object({}) do |holding, acc|
×
UNCOV
19
        sequence += 1
×
UNCOV
20
        status = holding_status(holding:)
×
UNCOV
21
        acc[status[:id]] = status unless status.nil?
×
22
      end
23
    end
24

25
    # Returns availability information for each of the holdings in the Bib record.
26
    # Notice that although we return the information by holding, we drill into item
27
    # information to get details.
28
    def bib_availability_from_items
1✔
UNCOV
29
      availability = {}
×
UNCOV
30
      item_data.each do |holding_id, items|
×
UNCOV
31
        next if items.count == 0
×
32

33
        # Process all the items for the holding and keep the "status" information from the last one.
34
        # Notice that we also gather enough information to determine whether the holding as a whole
35
        # is available, not available, or some items available.
UNCOV
36
        all_available = true
×
UNCOV
37
        none_available = true
×
UNCOV
38
        items.each do |item|
×
UNCOV
39
          alma_item = AlmaAdapter::AlmaItem.new(Alma::BibItem.new(item.item))
×
UNCOV
40
          status = holding_status_from_item(alma_item)
×
UNCOV
41
          availability[holding_id] = status
×
UNCOV
42
          all_available &&= status[:status_label] == 'Available'
×
UNCOV
43
          none_available &&= status[:status_label] == 'Unavailable'
×
44
        end
45

46
        # Update the availability's status_label of the holding as a whole.
UNCOV
47
        holding_availability = if all_available
×
UNCOV
48
                                 'Available'
×
UNCOV
49
                               elsif none_available
×
UNCOV
50
                                 'Unavailable'
×
51
                               else
UNCOV
52
                                 'Some items not available'
×
53
                               end
UNCOV
54
        availability[holding_id][:status_label] = holding_availability
×
55
      end
UNCOV
56
      availability
×
57
    end
58

59
    def holding_status(holding:)
1✔
60
      # Ignore electronic and digital records
UNCOV
61
      return nil if holding['inventory_type'] != 'physical'
×
62

UNCOV
63
      location_info = location_record(holding)
×
UNCOV
64
      status_label = Status.new(bib:, holding:, aeon: aeon?(location_info)).to_s
×
65
      status = {
UNCOV
66
        on_reserve: AlmaItem.reserve_location?(holding['library_code'], holding['location_code']) ? 'Y' : 'N',
×
67
        location: holding_location_code(holding),
68
        label: holding_location_label(holding, location_info),
69
        status_label:,
70
        copy_number: nil,
71
        temp_location: false,
72
        id: holding['holding_id']
73
      }
74

UNCOV
75
      if holding['holding_id'].nil?
×
UNCOV
76
        holding['holding_id'] = "#{holding['library_code']}$#{holding['location_code']}"
×
77
        # The ALma call from the Alma::AvailabilityResponse returns holding in temp_location with holding_id nil
78
        # see https://github.com/tulibraries/alma_rb/blob/affabad4094bc2abf0e8546b336d2a667d5ffab5/lib/alma/bib_item.rb#L53
79
        # In this case we create a holding_id using the name of the 'temporary_library$temporary_location'
UNCOV
80
        status[:id] = holding['holding_id']
×
UNCOV
81
        status[:temp_location] = true
×
82
      end
83

UNCOV
84
      status
×
85
    end
86

87
    # @param alma_item [AlmaAdapter::AlmaItem]
88
    def holding_status_from_item(alma_item)
1✔
89
      {
UNCOV
90
        on_reserve: alma_item.on_reserve? ? 'Y' : 'N',
×
91
        location: alma_item.composite_location_display,
92
        label: alma_item.composite_location_label_display,
93
        status_label: alma_item.calculate_status[:code],
94
        copy_number: alma_item.copy_number,
95
        temp_location: alma_item.in_temp_location?,
96
        id: alma_item.holding_id
97
      }
98
    end
99

100
    def to_h
1✔
101
      holdings.each_with_object({}) do |holding, acc|
×
102
        acc[holding['holding_id']] = holding_summary(holding)
×
103
      end
104
    end
105

106
    def holding_summary(holding)
1✔
107
      holding_item_data = item_data[holding['holding_id']]
×
108
      location_info = location_record(holding)
×
109
      status = Status.new(bib:, holding:, aeon: aeon?(location_info))
×
110
      {
111
        item_id: holding_item_data&.first&.item_data&.fetch('pid', nil),
×
112
        location: "#{holding['library_code']}-#{holding['location_code']}",
113
        copy_number: holding_item_data&.first&.holding_data&.fetch('copy_id', ''),
114
        label: holding_location_label(holding, location_info),
115
        status: status.to_s
116
      }
117
    end
118

119
    def item_data
1✔
UNCOV
120
      return @item_data if @item_data
×
121

UNCOV
122
      options = { timeout: 10 }
×
UNCOV
123
      message = "All items for #{bib.id}"
×
UNCOV
124
      items = AlmaAdapter::Execute.call(options:, message:) do
×
125
        # This method DOES issue a separate call to the Alma API to get item information.
126
        # Internally this call passes "ALL" to ExLibris to get data for all the holdings
127
        # in the current bib record.
UNCOV
128
        opts = { order_by: 'enum_a' }
×
UNCOV
129
        Alma::BibItem.find(bib.id, opts).items
×
130
      end
131

UNCOV
132
      @item_data = items.group_by do |item|
×
UNCOV
133
        item['holding_data']['holding_id']
×
134
      end
135
    end
136

137
    def marc_record
1✔
138
      @marc_record ||= MARC::XMLReader.new(StringIO.new(bib.response['anies'].join(''))).to_a.first
×
139
    end
140

141
    def holdings
1✔
142
      # This method does NOT issue a separate call to the Alma API to get the information, instead it
143
      # extracts the availability information (i.e. the AVA and AVE fields) from the bib record.
144
      # If temp_location is true cannot get holding_id from this call because of https://github.com/tulibraries/alma_rb/blob/affabad4094bc2abf0e8546b336d2a667d5ffab5/lib/alma/bib_item.rb#L53
UNCOV
145
      @availability_response ||= Alma::AvailabilityResponse.new(Array.wrap(bib)).availability[bib.id][:holdings]
×
146
    end
147

148
    def holding(holding_id:)
1✔
149
      holdings.find { |h| h['holding_id'] == holding_id }
×
150
    end
151

152
    # Returns all the items for a given holding_id in the current bib.
153
    # This is a more specific version of `item_data`.
154
    #
155
    # If the holding has more than ITEMS_PER_PAGE items the Alma gem will automatically
156
    # make multiple calls to the Alma API.
157
    def holding_item_data(holding_id:)
1✔
UNCOV
158
      data = nil
×
UNCOV
159
      options = { enable_loggable: true, timeout: 10 }
×
UNCOV
160
      message = "Items for bib: #{bib.id}, holding_id: #{holding_id}"
×
UNCOV
161
      AlmaAdapter::Execute.call(options:, message:) do
×
UNCOV
162
        opts = { limit: Alma::BibItemSet::ITEMS_PER_PAGE, holding_id:, order_by: 'enum_a' }
×
UNCOV
163
        items = Alma::BibItem.find(bib.id, opts).all.map { |item| AlmaAdapter::AlmaItem.new(item) }
×
UNCOV
164
        data = { items:, total_count: items.count }
×
165
      end
UNCOV
166
      data
×
167
    end
168

169
    private
1✔
170

171
      # Returns the extra location information that we store in the local database
172
      def location_record(holding)
1✔
UNCOV
173
        HoldingLocation.find_by(code: holding_location_code(holding))
×
174
      end
175

176
      # The status label retrieves the value from holding_location.label
177
      # which is equivalent to the alma external_name value
178
      def holding_location_label(holding, location_record)
1✔
UNCOV
179
        label = location_record&.label
×
UNCOV
180
        [holding['library'], label].select(&:present?).join(' - ')
×
181
      end
182

183
      def holding_location_code(holding)
1✔
UNCOV
184
        [holding['library_code'], holding['location_code']].join('$')
×
185
      end
186

187
      def aeon?(location_record)
1✔
UNCOV
188
        location_record&.aeon_location
×
189
      end
190
  end
191
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