folio_api_client 0.3.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd0f25ee382d9468806b7ae7c39a0d7801f43d5e45c7f7bd248565673fe9da23
4
- data.tar.gz: e05cb433eb2134c574d2de93a3e9de4cdad6a4c9bd9c6ae3f67483179f64e855
3
+ metadata.gz: b840ff7acc1495be7cb4dc3895c9a0e372d98df6db09bd45e5a77725e1cc3444
4
+ data.tar.gz: 187a19aa42bfe6e1f64e859dfd1b7d71c03db8a0967ab93a7df2318bdc2c4b32
5
5
  SHA512:
6
- metadata.gz: f68f5dab0e5080f62b307c8f72bf2fb75e5d4033f7fb70fdfdd99f749edf821ae2c9d1c697e31f70f8af4e1be60aa55c930c9c9bd494348fbff9fe1e7337e563
7
- data.tar.gz: 6cdc0f1d8a571a11599ae906f985f0e2901dedcbc07b8f26f71f316337507693dd22ea0f8a841bbd6083ce6436c5b7dbebe252f4f54d685bb1366c66ec29ebdf
6
+ metadata.gz: 4b1d313a2cf74cd8b28f5d151239136a3fd8c7fe4db9a2bb85c924dd9390ab464e733012fc95d8bc8bf274db6571e2638f66ab0e4fa0633e4e0b5f372184647c
7
+ data.tar.gz: 52216d3b49b1b5d5c45c3698eb95eb8350aca7b59846de99f9498524c3e2fe8f202f7a8227a7f53b9f5b6e03da9ad6d33be816e7e87a12412579ecd6c1e445ee
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2025 The Trustees of Columbia University in the City of New York
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md CHANGED
@@ -47,9 +47,16 @@ client.delete(path, body, content_type: 'application/json'))
47
47
 
48
48
  client.find_item_record(barcode: 'some-barcode')
49
49
  client.find_location_record(location_id: 'some-location-id')
50
+ client.find_material_type_record(material_type_id: 'some-material-type-id')
50
51
  client.find_holdings_record(holdings_record_id: 'some-holdings-record-id')
51
52
  client.find_instance_record(instance_record_id: 'some-instance-record-id')
52
- client.find_marc_record(instance_record_id: 'some-instance-record-id') # returns a MARC::Record
53
+ client.find_instance_record(instance_record_hrid: 'some-instance-record-hrid')
54
+ client.find_source_record(instance_record_id: 'some-instance-record-id')
55
+ client.find_source_record(instance_record_hrid: 'some-instance-record-hrid')
56
+
57
+ # Convert a FOLIO MARC source record to a marc gem MARC::Record object:
58
+ source_record = client.find_source_record(instance_record_id: 'some-instance-record-id')
59
+ marc_record = MARC::Record.new_from_hash(source_record['parsedRecord']['content'])
53
60
  ```
54
61
 
55
62
  See [https://dev.folio.org/reference/api/](https://dev.folio.org/reference/api/) for the full list of available FOLIO API endpoints.
@@ -11,40 +11,83 @@ class FolioApiClient
11
11
  'Only expected one item with this barcode, but found more than one.'
12
12
  end
13
13
 
14
- item_record_id = item_search_results.first['id']
15
- self.get("/item-storage/items/#{item_record_id}")
14
+ item_search_results.first
16
15
  end
17
16
 
18
17
  def find_location_record(location_id:)
18
+ return nil if location_id.nil?
19
+
19
20
  self.get("/locations/#{location_id}")
21
+ rescue Faraday::ResourceNotFound
22
+ nil
23
+ end
24
+
25
+ def find_material_type_record(material_type_id:)
26
+ return nil if material_type_id.nil?
27
+
28
+ self.get("/material-types/#{material_type_id}")
29
+ rescue Faraday::ResourceNotFound
30
+ nil
31
+ end
32
+
33
+ def find_loan_type_record(loan_type_id:)
34
+ self.get("/loan-types/#{loan_type_id}")
20
35
  end
21
36
 
22
37
  def find_holdings_record(holdings_record_id:)
23
38
  self.get("/holdings-storage/holdings/#{holdings_record_id}")
24
39
  end
25
40
 
26
- def find_instance_record(instance_record_id:)
27
- self.get("/instance-storage/instances/#{instance_record_id}")
41
+ def find_instance_record(instance_record_id: nil, instance_record_hrid: nil)
42
+ instance_search_results = self.get(
43
+ '/instance-storage/instances',
44
+ instance_record_query(instance_record_id: instance_record_id, instance_record_hrid: instance_record_hrid)
45
+ )['instances']
46
+ return nil if instance_search_results.empty?
47
+
48
+ if instance_search_results.length > 1
49
+ raise FolioApiClient::Exceptions::UnexpectedMultipleRecordsFoundError,
50
+ 'Only expected one instance with this '\
51
+ "#{instance_record_id ? 'instance_record_id' : 'instance_record_hrid'}, "\
52
+ 'but found more than one.'
53
+ end
54
+
55
+ instance_search_results.first
28
56
  end
29
57
 
30
- # Find a MARC::Record by its instance record id or instance record hrid
31
- def find_marc_record(instance_record_id: nil, instance_record_hrid: nil)
58
+ # Find a source record by its instance record id or instance record hrid.
59
+ # @return [Hash] A Source Record (which can hold data for a MARC record).
60
+ def find_source_record(instance_record_id: nil, instance_record_hrid: nil)
32
61
  source_record_search_results = self.get(
33
62
  '/source-storage/source-records',
34
- marc_record_query(instance_record_id: instance_record_id, instance_record_hrid: instance_record_hrid)
63
+ source_record_query(instance_record_id: instance_record_id, instance_record_hrid: instance_record_hrid)
35
64
  )
36
65
  return nil if source_record_search_results['totalRecords'].zero?
37
66
 
38
- bib_record_marc_hash = source_record_search_results['sourceRecords'].first['parsedRecord']['content']
39
- MARC::Record.new_from_hash(bib_record_marc_hash)
67
+ if source_record_search_results['totalRecords'] > 1
68
+ raise FolioApiClient::Exceptions::UnexpectedMultipleRecordsFoundError,
69
+ 'Only expected one record with this '\
70
+ "#{instance_record_id ? 'instance_record_id' : 'instance_record_hrid'}, "\
71
+ 'but found more than one.'
72
+ end
73
+
74
+ source_record_search_results['sourceRecords'].first
40
75
  end
41
76
 
42
- def marc_record_query(instance_record_id: nil, instance_record_hrid: nil)
77
+ def source_record_query(instance_record_id: nil, instance_record_hrid: nil)
43
78
  return { instanceId: instance_record_id } if instance_record_id
44
79
  return { instanceHrid: instance_record_hrid } if instance_record_hrid
45
80
 
46
81
  raise FolioApiClient::Exceptions::MissingQueryFieldError,
47
82
  'Missing query field. Must supply either an instance_record_id or instance_record_hrid.'
48
83
  end
84
+
85
+ def instance_record_query(instance_record_id: nil, instance_record_hrid: nil)
86
+ return { query: "id==#{instance_record_id}", limit: 2 } if instance_record_id
87
+ return { query: "hrid==#{instance_record_hrid}", limit: 2 } if instance_record_hrid
88
+
89
+ raise FolioApiClient::Exceptions::MissingQueryFieldError,
90
+ 'Missing query field. Must supply either an instance_record_id or instance_record_hrid.'
91
+ end
49
92
  end
50
93
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class FolioApiClient
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.2'
5
5
  end
@@ -38,7 +38,7 @@ class FolioApiClient
38
38
  end
39
39
 
40
40
  def retrieve_new_auth_token
41
- response = connection.post('/authn/login', { username: config.username, password: config.password }.to_json)
41
+ response = connection.post('/authn/login', JSON.generate({ username: config.username, password: config.password }))
42
42
  response_data = JSON.parse(response.body)
43
43
  response_data['okapiToken']
44
44
  end
@@ -68,12 +68,12 @@ class FolioApiClient
68
68
  end
69
69
 
70
70
  def exec_request_with_body(method, path, body = nil, content_type: 'application/json')
71
- body = body.to_json if content_type == 'application/json' && !body.is_a?(String)
71
+ body = JSON.generate(body) if content_type == 'application/json' && !body.is_a?(String)
72
72
  response = with_token_refresh_attempt_when_unauthorized do
73
73
  connection.send(method, path, body, { 'x-okapi-token': config.token, 'content-type': content_type })
74
74
  end
75
75
 
76
- response.body.nil? ? nil : JSON.parse(response.body)
76
+ response.body.nil? || response.body == '' ? nil : JSON.parse(response.body)
77
77
  end
78
78
 
79
79
  def post(path, body = nil, content_type: 'application/json')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: folio_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric O'Hanlon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-04-30 00:00:00.000000000 Z
11
+ date: 2025-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -63,6 +63,7 @@ files:
63
63
  - ".rspec"
64
64
  - ".rubocop.yml"
65
65
  - ".ruby-version"
66
+ - LICENSE
66
67
  - README.md
67
68
  - Rakefile
68
69
  - lib/folio_api_client.rb
@@ -71,7 +72,8 @@ files:
71
72
  - lib/folio_api_client/finders.rb
72
73
  - lib/folio_api_client/version.rb
73
74
  homepage: https://www.github.com/cul/folio_api_client
74
- licenses: []
75
+ licenses:
76
+ - Apache-2.0
75
77
  metadata:
76
78
  homepage_uri: https://www.github.com/cul/folio_api_client
77
79
  source_code_uri: https://www.github.com/cul/folio_api_client