alma 0.2.8 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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