Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions app/models/alma_sru.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# frozen_string_literal: true

# Queries the Alma SRU endpoint for holdings data
#
# @reference https://developers.exlibrisgroup.com/alma/integrations/SRU/
class AlmaSru
class LookupFailure < StandardError; end

class InvalidAlmaId < StandardError; end

# lookup will receive an Alma ID, validate it, look it up in the Alma SRU, and return a formatted result.
#
# It accepts an "alma_client" argument for use when testing, but this is not used in normal operations.
def self.lookup(raw_identifier, alma_client: nil)
return nil unless alma_base_url

# Validate the raw identifier received. This will raise an InvalidAlmaId if validation fails.
identifier = validate_alma_id(raw_identifier)

# Build URL
url = alma_sru_url(identifier)

# Retrieve that URL
alma_http = setup(url, alma_client)

parse_response(alma_http.timeout(6).get(url))
rescue InvalidAlmaId
Rails.logger.error("Invalid Alma ID: #{raw_identifier}")
rescue LookupFailure => e
Rails.logger.error("Alma lookup failure: #{e}")
end

def self.parse_response(raw_response)
raise LookupFailure, raw_response.status unless raw_response.status == 200

raw_response
end

# validate_alma_id ensures we are only submitting valid Alma IDs to the SRU endpoint.
#
# It needs to do two thigns:
# 1. Remove the "alma" prefix if one is present. Otherwise, no manipulation of the submitted value should occur.
# 2. Enforce the formatting requirements for a valid alma identifier (start with "99", and end with "6761").
def self.validate_alma_id(raw)
parsed = if raw.start_with?('alma')
raw.delete_prefix('alma')
else
raw
end

raise InvalidAlmaId unless parsed.to_s.start_with?('99')
raise InvalidAlmaId unless parsed.to_s.end_with?('6761')

parsed
end

def self.alma_base_url
ENV.fetch('MIT_ALMA_URL', nil)
end

def self.alma_sru_url(identifier)
# example identifier: 990000959610106761
"#{alma_base_url}/view/sru/#{ENV.fetch('EXL_INST_ID')}?version=1.2&operation=searchRetrieve&recordSchema=marcxml" \
"&query=alma.all_for_ui=#{identifier}"
end

def self.setup(url, alma_client)
alma_client || HTTP.persistent(url)
end
end
23 changes: 23 additions & 0 deletions test/models/alma_sru_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'test_helper'

class AlmaSruTest < ActiveSupport::TestCase
test 'validate_alma_id succeeds with valid numeric input' do
needle = '990002935920106761'
assert_nothing_raised do
AlmaSru.validate_alma_id(needle)
end
end

test 'validate_alma_id succeeds despite and "alma" prefix' do
needle = 'alma990002935920106761'
assert_nothing_raised do
AlmaSru.validate_alma_id(needle)
end
end

test 'validate_alma_id raises InvalidAlmaId with invalid input' do
assert_raises(AlmaSru::InvalidAlmaId) do
AlmaSru.validate_alma_id('foo')
end
end
end