alma 0.2.8 → 0.3.1

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.
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module Alma
6
+ class Response
7
+ class StandardError < Alma::StandardError
8
+ end
9
+
10
+ extend ::Forwardable
11
+
12
+ attr_reader :raw_response
13
+ def_delegators :raw_response, :body, :success?, :response, :request
14
+
15
+ def initialize(response)
16
+ @raw_response = response
17
+ # We could validate and throw an error here but currently a
18
+ validate(response)
19
+ end
20
+
21
+ def loggable
22
+ { uri: @raw_response&.request&.uri.to_s
23
+ }.select { |k, v| !(v.nil? || v.empty?) }
24
+ end
25
+
26
+ def validate(response)
27
+ if errors.first&.dig("errorCode") == "401136"
28
+ message = "The requested item already exists."
29
+ log = loggable.merge(response.parsed_response)
30
+
31
+ raise Alma::BibRequest::ItemAlreadyExists.new(message, log)
32
+ end
33
+
34
+ if response.code != 200
35
+ log = loggable.merge(response.parsed_response)
36
+ raise StandardError.new("Invalid Response.", log)
37
+ end
38
+ end
39
+
40
+ # Returns an array of errors
41
+ def errors
42
+ @raw_response.parsed_response&.dig("errorList", "error") || []
43
+ end
44
+ end
45
+ end
@@ -1,50 +1,42 @@
1
- module Alma
2
- class ResultSet
3
- extend Forwardable
1
+ # frozen_string_literal: true
4
2
 
5
- include Enumerable
6
- include Alma::Error
3
+ require "forwardable"
7
4
 
8
- def_delegators :list, :each, :size
5
+ class Alma::ResultSet
6
+ extend ::Forwardable
7
+ include Enumerable
8
+ include Alma::Error
9
9
 
10
- def initialize(ws_response)
11
- @response = ws_response
12
- end
10
+ attr_reader :response
13
11
 
14
- def total_record_count
15
- @response[top_level_key].fetch('total_record_count', 0).to_i
16
- end
12
+ def_delegators :response, :[], :fetch
13
+ def_delegators :each, :each_with_index, :size
17
14
 
18
- def list
19
- @list ||= list_results
20
- end
15
+ def initialize(response_body_hash)
16
+ @response = response_body_hash
17
+ end
21
18
 
19
+ def loggable
20
+ { uri: @response&.request&.uri&.to_s }
21
+ .select { |k, v| !(v.nil? || v.empty?) }
22
+ end
22
23
 
23
- def top_level_key
24
- raise NotImplementedError 'Subclasses of ResultSet Need to define the top level key'
25
- end
24
+ def each
25
+ @results ||= @response.fetch(key, [])
26
+ .map { |item| single_record_class.new(item) }
27
+ end
26
28
 
27
- def response_records_key
28
- raise NotImplementedError 'Subclasses of ResultSet Need to define the key for response records'
29
- end
29
+ def total_record_count
30
+ fetch("total_record_count", 0).to_i
31
+ end
32
+ alias :total_records :total_record_count
30
33
 
31
- private
32
- def response_records
33
- @response[top_level_key].fetch(response_records_key,[])
34
+ protected
35
+ def key
36
+ raise NotImplementedError "Subclasses of ResultSet need to define a response key"
34
37
  end
35
38
 
36
- # Subclasses Can override this to use a Custom Class for single record objects.
37
39
  def single_record_class
38
40
  Alma::AlmaRecord
39
41
  end
40
-
41
- def list_results
42
- #If there is only one record in the response, HTTParty returns as a hash, not
43
- # an array of hashes, so wrap in array to normalize.
44
- response_array = (response_records.is_a? Array) ? response_records : [response_records]
45
- response_array.map do |record|
46
- single_record_class.new(record)
47
- end
48
- end
49
- end
50
42
  end
@@ -1,14 +1,15 @@
1
1
  module Alma
2
2
  class User
3
+ class ResponseError < Alma::StandardError
4
+ end
3
5
  extend Forwardable
6
+ extend Alma::ApiDefaults
7
+
8
+ def self.find(user_id, args={})
9
+ args[:expand] ||= "fees,requests,loans"
10
+ response = HTTParty.get("#{self.users_base_path}/#{user_id}", query: args, headers: headers, timeout: timeout)
4
11
 
5
- def self.find(user_id)
6
- response = HTTParty.get("#{self.users_base_path}/#{user_id}", headers: headers)
7
- if response.code == 200
8
- Alma::User.new JSON.parse(response.body)
9
- else
10
- raise StandardError, parse(response.body)
11
- end
12
+ Alma::User.new response
12
13
  end
13
14
 
14
15
  # Authenticates a Alma user with their Alma Password
@@ -19,7 +20,7 @@ module Alma
19
20
  def self.authenticate(args)
20
21
  user_id = args.delete(:user_id) { raise ArgumentError }
21
22
  args.merge!({op: 'auth'})
22
- response = HTTParty.post("#{users_base_path}/#{user_id}", query: args, headers: headers)
23
+ response = HTTParty.post("#{users_base_path}/#{user_id}", query: args, headers: headers, timeout: timeout)
23
24
  response.code == 204
24
25
  end
25
26
 
@@ -27,9 +28,23 @@ module Alma
27
28
  # The User object can respond directly to Hash like access of attributes
28
29
  def_delegators :response, :[], :[]=, :has_key?, :keys, :to_json
29
30
 
30
- def initialize(response_body)
31
- @response = response_body
32
- @recheck_loans = true
31
+ def initialize(response)
32
+ @raw_response = response
33
+ @response = response.parsed_response
34
+ validate(response)
35
+ end
36
+
37
+ def loggable
38
+ { uri: @raw_response&.request&.uri.to_s
39
+ }.select { |k, v| !(v.nil? || v.empty?) }
40
+ end
41
+
42
+ def validate(response)
43
+ if response.code != 200
44
+ log = loggable.merge(response.parsed_response)
45
+ error = "The user was not found."
46
+ raise ResponseError.new(error, log)
47
+ end
33
48
  end
34
49
 
35
50
  def response
@@ -40,6 +55,18 @@ module Alma
40
55
  self['primary_id']
41
56
  end
42
57
 
58
+ def total_fines
59
+ response.dig('fees','value') || "0"
60
+ end
61
+
62
+ def total_requests
63
+ response.dig('requests','value') || "0"
64
+ end
65
+
66
+ def total_loans
67
+ response.dig('loans','value') || "0"
68
+ end
69
+
43
70
 
44
71
  # Access the top level JSON attributes as object methods
45
72
  def method_missing(name)
@@ -54,35 +81,22 @@ module Alma
54
81
 
55
82
  # Persist the user in it's current state back to Alma
56
83
  def save!
57
- response = HTTParty.put("#{users_base_path}/#{id}", headers: headers, body: to_json)
84
+ response = HTTParty.put("#{users_base_path}/#{id}", timeout: timeout, headers: headers, body: to_json)
58
85
  get_body_from(response)
59
86
  end
60
87
 
61
88
 
62
89
  def fines
63
- response = HTTParty.get("#{users_base_path}/#{id}/fees", headers: headers)
64
- if response.code == 200
65
- Alma::FineSet.new get_body_from(response)
66
- else
67
- raise StandardError, get_body_from(response)
68
- end
90
+ Alma::Fine.where_user(id)
69
91
  end
70
92
 
71
93
  def requests
72
- #TODO Handle Additional Parameters
73
- #TODO Handle Pagination
74
- #TODO Handle looping through all results
75
- response = HTTParty.get("#{users_base_path}/#{id}/requests", headers: headers)
76
- Alma::RequestSet.new(get_body_from(response))
94
+ Alma::UserRequest.where_user(id)
77
95
  end
78
96
 
79
97
 
80
98
  def loans(args={})
81
- unless @loans && !recheck_loans?
82
- @loans = send_loans_request(args)
83
- @recheck_loans = false
84
- end
85
- @loans
99
+ @loans ||= Alma::Loan.where_user(id, args)
86
100
  end
87
101
 
88
102
  def renew_loan(loan_id)
@@ -97,38 +111,45 @@ module Alma
97
111
  loan_ids.map { |id| renew_loan(id) }
98
112
  end
99
113
 
100
-
101
114
  def renew_all_loans
102
115
  renew_multiple_loans(loans.map(&:loan_id))
103
116
  end
104
117
 
105
-
106
- def recheck_loans?
107
- @recheck_loans
108
- end
109
-
110
-
111
118
  def preferred_email
112
119
  self["contact_info"]["email"].select { |k, v| k["preferred"] }.first["email_address"]
113
120
  end
114
121
 
115
-
116
122
  def email
117
123
  self["contact_info"]["email"].map { |e| e["email_address"] }
118
124
  end
119
125
 
126
+ def preferred_first_name
127
+ pref_first = self["pref_first_name"] unless self["pref_first_name"] == ""
128
+ pref_first || self["first_name"] || ""
129
+ end
120
130
 
121
- private
131
+ def preferred_middle_name
132
+ pref_middle = self["pref_middle_name"] unless self["pref_middle_name"] == ""
133
+ pref_middle || self["middle_name"] || ""
134
+ end
122
135
 
123
- def send_loans_request(args={})
124
- #TODO Handle looping through all results
136
+ def preferred_last_name
137
+ pref_last = self["pref_last_name"] unless self["pref_last_name"] == ""
138
+ pref_last || self["last_name"]
139
+ end
140
+
141
+ def preferred_suffix
142
+ self["pref_name_suffix"] || ""
143
+ end
125
144
 
126
- # Always expand renewable unless you really don't want to
127
- args["expand"] ||= "renewable"
128
- response = HTTParty.get("#{users_base_path}/#{id}/loans", query: args, headers: headers)
129
- Alma::LoanSet.new(get_body_from(response))
145
+ def preferred_name
146
+ "#{preferred_first_name} #{preferred_middle_name} #{preferred_last_name} #{preferred_suffix}"
130
147
  end
131
148
 
149
+
150
+
151
+ private
152
+
132
153
  # Attempts to renew a single item for a user
133
154
  # @param [Hash] args
134
155
  # @option args [String] :user_id The unique id of the user
@@ -140,7 +161,7 @@ module Alma
140
161
  user_id = args.delete(:user_id) { raise ArgumentError }
141
162
  params = {op: 'renew'}
142
163
  response = HTTParty.post("#{users_base_path}/#{user_id}/loans/#{loan_id}", query: params, headers: headers)
143
- RenewalResponse.new(JSON.parse(response.body))
164
+ RenewalResponse.new(response)
144
165
  end
145
166
 
146
167
  # Attempts to renew multiple items for a user
@@ -167,21 +188,8 @@ module Alma
167
188
  self.class.users_base_path
168
189
  end
169
190
 
170
- def self.headers
171
- { "Authorization": "apikey #{self.apikey}",
172
- "Accept": "application/json",
173
- "Content-Type": "application/json" }
174
- end
175
-
176
-
177
191
  def headers
178
192
  self.class.headers
179
193
  end
180
-
181
-
182
- def self.apikey
183
- Alma.configuration.apikey
184
- end
185
-
186
194
  end
187
195
  end
@@ -0,0 +1,17 @@
1
+ module Alma
2
+ class UserRequest < AlmaRecord
3
+ extend Alma::ApiDefaults
4
+
5
+ def self.where_user(user_id, args={})
6
+ # Default to upper limit
7
+ args[:limit] ||= 100
8
+ response = HTTParty.get(
9
+ "#{users_base_path}/#{user_id}/requests",
10
+ query: args,
11
+ headers: headers,
12
+ timeout: timeout
13
+ )
14
+ Alma::RequestSet.new(response)
15
+ end
16
+ end
17
+ end
@@ -1,18 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Alma
2
4
  class UserSet
3
-
4
5
  def top_level_key
5
- 'users'
6
-
6
+ "users"
7
7
  end
8
8
 
9
9
  def response_records_key
10
- 'user'
10
+ "user"
11
11
  end
12
12
 
13
13
  def single_record_class
14
14
  Alma::User
15
15
  end
16
-
17
16
  end
18
- end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module Alma
2
- VERSION = "0.2.8"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alma
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chad Nelson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-26 00:00:00.000000000 Z
11
+ date: 2020-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ezwadl
@@ -52,34 +52,48 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '1.13'
75
+ version: '2.0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '1.13'
82
+ version: '2.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '10.0'
89
+ version: '13.0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '10.0'
96
+ version: '13.0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rspec
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +136,48 @@ dependencies:
122
136
  - - ">="
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: byebug
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: guard
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: guard-rspec
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
125
181
  description: Client for Ex Libris Alma Web Services
126
182
  email:
127
183
  - chad.nelson@temple.edu
@@ -136,6 +192,7 @@ files:
136
192
  - ".travis.yml"
137
193
  - CODE_OF_CONDUCT.md
138
194
  - Gemfile
195
+ - Guardfile
139
196
  - LICENSE.txt
140
197
  - README.md
141
198
  - Rakefile
@@ -144,26 +201,36 @@ files:
144
201
  - bin/setup
145
202
  - lib/alma.rb
146
203
  - lib/alma/alma_record.rb
147
- - lib/alma/api.rb
204
+ - lib/alma/api_defaults.rb
148
205
  - lib/alma/availability_response.rb
149
206
  - lib/alma/bib.rb
150
207
  - lib/alma/bib_item.rb
151
208
  - lib/alma/bib_item_set.rb
152
209
  - lib/alma/bib_set.rb
153
210
  - lib/alma/config.rb
211
+ - lib/alma/electronic.rb
212
+ - lib/alma/electronic/README.md
213
+ - lib/alma/electronic/batch_utils.rb
214
+ - lib/alma/electronic/business.rb
154
215
  - lib/alma/error.rb
216
+ - lib/alma/fine.rb
155
217
  - lib/alma/fine_set.rb
218
+ - lib/alma/item_request_options.rb
156
219
  - lib/alma/loan.rb
157
220
  - lib/alma/loan_set.rb
158
221
  - lib/alma/renewal_response.rb
222
+ - lib/alma/request.rb
159
223
  - lib/alma/request_options.rb
160
224
  - lib/alma/request_set.rb
225
+ - lib/alma/response.rb
161
226
  - lib/alma/result_set.rb
162
227
  - lib/alma/user.rb
228
+ - lib/alma/user_request.rb
163
229
  - lib/alma/user_set.rb
164
230
  - lib/alma/version.rb
165
231
  - lib/alma/wadl/bib.wadl
166
232
  - lib/alma/wadl/user.wadl
233
+ - log/.gitignore
167
234
  homepage: https://github.com/tulibraries/alma_rb
168
235
  licenses:
169
236
  - MIT
@@ -184,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
251
  version: '0'
185
252
  requirements: []
186
253
  rubyforge_project:
187
- rubygems_version: 2.6.11
254
+ rubygems_version: 2.7.7
188
255
  signing_key:
189
256
  specification_version: 4
190
257
  summary: Client for Ex Libris Alma Web Services