alma 0.2.4 → 0.2.5

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
  SHA1:
3
- metadata.gz: a61f0bfe79181cdb4d99e0eca51ba16b1be6550f
4
- data.tar.gz: 8f024c368175b3a8ac0fe2e6eb836f436516a566
3
+ metadata.gz: 3bcedc3a4e5136aa43268412c062c91dc2d905dd
4
+ data.tar.gz: 37f3892ff4a0fc27e8c6a79a540ea52f0f5199d4
5
5
  SHA512:
6
- metadata.gz: 58b8bcfbe9b5c4f6ccd688df845bfb86e3fe8115199b06862c03b6faeaf31e08e4f9a33cca5209c082fa69f8416461dc9c45bef34a9c57179a48d4f29f7b2397
7
- data.tar.gz: 60e8ea0221d2dce2001e53afd41d0f046cb822e56c74f2e07ecffcacc7fa9e94ce9c4730572f79cd0463d12c09506e64a4af9b52ed871cefa2be625a650e6cbb
6
+ metadata.gz: 120bef80c621c53709475f2c54dd2a7b3379fe307ac0f1227adb1f0a8627e064ea19f87260432a5a45ad65d342623fbc314e5079aea7fae930a0ac719bbf5f7c
7
+ data.tar.gz: 2e190810b76aa0b0041b021364d5879cff6a6122ee9f0c17be212cc69bb1d1c2af63059c801752754f6b711ec4e948777d2a1285ef428b1838a7ce1c6fc5eb80
@@ -1 +1 @@
1
- ruby-2.3.3
1
+ ruby-2.4.1
data/README.md CHANGED
@@ -36,27 +36,20 @@ end
36
36
  Now you can access those configuration attributes with `Alma.configuration.apikey`
37
37
 
38
38
  ### Making Requests
39
-
40
- #### Get a list of Users
41
- ```ruby
42
- users = Alma::User.find
43
-
44
- users.total count
45
- > 402
46
-
47
- users.list.first.id
48
- > 123456789
49
- ```
50
39
 
51
40
  #### Get a Single user
52
41
  ```ruby
53
- user = Alma::User.find({:user_id => 123456789})
42
+ user = Alma::User.find(123456789)
54
43
 
55
44
  user.first_name
56
45
  > Chad
57
46
 
58
47
  user.email
59
48
  > chad.nelson@fictional.edu
49
+
50
+ user.keys
51
+ >{first_name: "Chad",
52
+ ...}
60
53
  ```
61
54
 
62
55
  #### Get details on a users fines
@@ -69,18 +62,18 @@ Now you can access those configuration attributes with `Alma.configuration.apike
69
62
  fines.total_record_count
70
63
  > "2"
71
64
 
72
- fines.list
65
+ fines
73
66
  > [#<Alma::AlmaRecord:0x000000038b7b50
74
67
  ...>,
75
68
  #<Alma::AlmaRecord:0x000000038b7b28
76
69
  ...>]
77
70
 
78
- fines.list.first.title
71
+ fines.first.title
79
72
  > "Practical Object Oriented Design with Ruby"
80
73
 
81
74
  ```
82
75
 
83
- Each fine object reflects the available fields in the returned XML,[as documented on the Ex Libris Api docs](https://developers.exlibrisgroup.com/alma/apis/xsd/rest_fees.xsd?tags=GET)
76
+ Each fine object reflects the available fields in the returned JSON,[as documented on the Ex Libris Api docs](https://developers.exlibrisgroup.com/alma/apis/xsd/rest_fees.xsd?tags=GET)
84
77
 
85
78
  #### Get details on a users loans
86
79
 
@@ -90,37 +83,23 @@ loans = user.loans
90
83
  loans.total_record_count
91
84
  > "2"
92
85
 
93
- loans.list
86
+ loans
94
87
  > [#<Alma::Loan:0x000000038c6b79
95
88
  ...>,
96
89
  #<Alma::Loan:0x000000038c6b34
97
90
  ...>]
98
91
 
99
- loans.list.first.title
92
+ loans.first.title
100
93
  > "Javascript: The Good Parts"
101
94
 
102
- loans.list.first.due_date
95
+ loans.first.due_date
103
96
  "2016-12-26z
104
97
 
105
98
  ```
106
99
  Each loan object reflects the available fields in the returned XML,[as documented on the Ex Libris Api docs](https://developers.exlibrisgroup.com/alma/apis/xsd/rest_item_loans.xsd?tags=GET)
107
100
 
108
- To renew an item you can can call the Loan objects renew method
109
-
110
- ```ruby
111
- renewal = loans.list.first.renew
112
-
113
- renewal.renewed?
114
- > True
115
-
116
- renewal.message
117
- > "Javascript: The Good Parts is now due 02-20-17"
118
-
119
- ```
120
-
121
-
122
101
 
123
- #### Get details on a users requests
102
+ #### Get details on a users requests - WIP
124
103
  ```ruby
125
104
  requests = user.requests
126
105
 
@@ -160,7 +139,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
160
139
 
161
140
  ## Contributing
162
141
 
163
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/alma. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
142
+ Bug reports and pull requests are welcome on GitHub at https://github.com/tulibraries/alma_rb. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
164
143
 
165
144
 
166
145
  ## License
@@ -22,6 +22,10 @@ Gem::Specification.new do |spec|
22
22
  spec.require_paths = ["lib"]
23
23
 
24
24
  spec.add_dependency 'ezwadl'
25
+ spec.add_dependency 'httparty'
26
+ spec.add_dependency 'xml-simple'
27
+
28
+
25
29
 
26
30
 
27
31
  spec.add_development_dependency "bundler", "~> 1.13"
@@ -15,45 +15,12 @@ require 'alma/bib_set'
15
15
  require 'alma/request_set'
16
16
  require 'alma/renewal_response'
17
17
  require 'alma/availability_response'
18
+ require 'alma/bib_items'
18
19
 
19
20
  module Alma
20
21
 
21
22
  ROOT = File.dirname __dir__
22
23
  WADL_DIR = File.join(Alma::ROOT, 'lib','alma','wadl')
23
24
 
24
- INVENTORY_TO_SUBFIELD_TO_FIELDNAME =
25
- {
26
- 'AVA' => {
27
- 'INVENTORY_TYPE' => 'physical',
28
- 'a' => 'institution',
29
- 'b' => 'library_code',
30
- 'c' => 'location',
31
- 'd' => 'call_number',
32
- 'e' => 'availability',
33
- 'f' => 'total_items',
34
- 'g' => 'non_available_items',
35
- 'j' => 'location_code',
36
- 'k' => 'call_number_type',
37
- 'p' => 'priority',
38
- 'q' => 'library',
39
- },
40
- 'AVD' => {
41
- 'INVENTORY_TYPE' => 'digital',
42
- 'a' => 'institution',
43
- 'b' => 'representations_id',
44
- 'c' => 'representation',
45
- 'd' => 'repository_name',
46
- 'e' => 'label',
47
- },
48
- 'AVE' => {
49
- 'INVENTORY_TYPE' => 'electronic',
50
- 'l' => 'library_code',
51
- 'm' => 'collection',
52
- 'n' => 'public_note',
53
- 's' => 'coverage_statement',
54
- 't' => 'interface_name',
55
- 'u' => 'link_to_service_page',
56
- }
57
- }
58
25
 
59
26
  end
@@ -1,3 +1,5 @@
1
+ require 'xmlsimple'
2
+
1
3
  module Alma
2
4
  class AvailabilityResponse
3
5
 
@@ -6,45 +8,84 @@ module Alma
6
8
 
7
9
  def initialize(response)
8
10
  @availability = parse_bibs_data(response.list)
9
-
10
11
  end
11
12
 
13
+ # Data structure for holdings information of bib records.
14
+ # A hash with mms ids as keys, with values of an array of
15
+ # one or more hashes of holdings info
12
16
  def parse_bibs_data(bibs)
13
-
14
- bibs.map do |bib|
15
- record = Hash.new
16
-
17
- record['mms_id'] = bib.id
18
- record['holdings'] = build_holdings_for(bib)
19
-
20
- record
21
- end.reduce(Hash.new) do |acc, avail|
22
- acc[avail['mms_id']] = avail.select { |k, v| k != 'mms_id' }
23
- acc
24
- end
17
+ bibs.reduce(Hash.new) { |acc, bib|
18
+ acc.merge({"#{bib.id}" => {holdings: build_holdings_for(bib)}})
19
+ }
25
20
  end
26
21
 
27
-
28
22
  def build_holdings_for(bib)
29
-
30
23
  get_inventory_fields_for(bib).map do |inventory_field|
31
- subfield_codes_to_fieldnames = Alma::INVENTORY_TO_SUBFIELD_TO_FIELDNAME[inventory_field['tag']]
32
-
33
- # make sure subfields is always an Array (which isn't the case if there's only one subfield element)
34
- subfields = [inventory_field.fetch('subfield', [])].flatten(1)
35
-
36
- holding = subfields.reduce(Hash.new) do |acc, subfield|
37
- fieldname = subfield_codes_to_fieldnames[subfield['code']]
38
- acc[fieldname] = subfield['__content__']
39
- acc
40
- end
41
- holding['inventory_type'] = subfield_codes_to_fieldnames['INVENTORY_TYPE']
42
- holding
24
+ # Use the mapping for this inventory type
25
+ subfield_codes = Alma::INVENTORY_SUBFIELD_MAPPING[inventory_field['tag']]
26
+
27
+ inventory_field.
28
+ # Get all the subfields for this inventory field
29
+ fetch('subfield', []).
30
+ # Limit to only subfields codes for which we have a mapping
31
+ select {|sf| subfield_codes.key? sf['code'] }.
32
+ # Transform the array of subfields into a hash with mapped code as key
33
+ reduce(Hash.new) { |acc, subfield|
34
+ acc.merge({"#{subfield_codes[subfield['code']]}" => subfield['content']})
35
+ }.
36
+ # Include the inventory type
37
+ merge({'inventory_type' => subfield_codes['INVENTORY_TYPE']})
43
38
  end
44
39
  end
45
40
 
46
41
  def get_inventory_fields_for(bib)
47
- bib.record.fetch('datafield', []).select { |df| Alma::INVENTORY_TO_SUBFIELD_TO_FIELDNAME.key?(df['tag']) } || []
42
+ # Return only the datafields with tags AVA, AVD, or AVE
43
+ bib.record
44
+ .fetch('datafield', [])
45
+ .select { |df| Alma::INVENTORY_SUBFIELD_MAPPING.key?(df['tag']) }
48
46
  end
49
47
  end
48
+
49
+ INVENTORY_SUBFIELD_MAPPING =
50
+ {
51
+ 'AVA' => {
52
+ 'INVENTORY_TYPE' => 'physical',
53
+ 'a' => 'institution',
54
+ 'b' => 'library_code',
55
+ 'c' => 'location',
56
+ 'd' => 'call_number',
57
+ 'e' => 'availability',
58
+ 'f' => 'total_items',
59
+ 'g' => 'non_available_items',
60
+ 'j' => 'location_code',
61
+ 'k' => 'call_number_type',
62
+ 'p' => 'priority',
63
+ 'q' => 'library',
64
+ 't' => 'holding_info',
65
+ '8' => 'holding_id',
66
+ },
67
+ 'AVD' => {
68
+ 'INVENTORY_TYPE' => 'digital',
69
+ 'a' => 'institution',
70
+ 'b' => 'representations_id',
71
+ 'c' => 'representation',
72
+ 'd' => 'repository_name',
73
+ 'e' => 'label',
74
+ },
75
+ 'AVE' => {
76
+ 'INVENTORY_TYPE' => 'electronic',
77
+ 'c' => 'collection_id',
78
+ 'e' => 'activation_status',
79
+ 'l' => 'library_code',
80
+ 'm' => 'collection',
81
+ 'n' => 'public_note',
82
+ 's' => 'coverage_statement',
83
+ 't' => 'interface_name',
84
+ 'u' => 'link_to_service_page',
85
+ '8' => 'portfolio_pid',
86
+ }
87
+ }
88
+
89
+
90
+
50
91
  end
@@ -1,46 +1,87 @@
1
1
  module Alma
2
- class Bib < AlmaRecord
3
- extend Alma::Api
2
+ class Bib
3
+ extend Forwardable
4
+
5
+ def self.find(ids, args)
6
+ get_bibs(ids, args)
7
+ end
4
8
 
5
- attr_accessor :id, :record
9
+ def self.get_bibs(ids, args={})
10
+ response = HTTParty.get(
11
+ self.bibs_base_path,
12
+ query: {mms_id: ids_from_array(ids)},
13
+ headers: headers
14
+ )
6
15
 
7
- def post_initialize
8
- @id = response['mms_id'].to_s
9
- @record = response.fetch('record', {})
16
+ if response.code == 200
17
+ Alma::BibSet.new(get_body_from(response))
18
+ else
19
+ raise StandardError, get_body_from(response)
20
+ end
10
21
  end
11
22
 
12
- class << self
13
23
 
14
- def get_availability(ids, args={})
15
- args.merge!({expand: 'p_avail,e_avail,d_avail'})
16
- bibs = get_bibs(ids, args)
24
+ def self.get_availability(ids, args={})
25
+ args.merge!({expand: 'p_avail,e_avail,d_avail'})
26
+ bibs = get_bibs(ids, args)
17
27
 
18
- return bibs if bibs.has_error?
19
- Alma::AvailabilityResponse.new(bibs)
20
- end
28
+ Alma::AvailabilityResponse.new(bibs)
29
+ end
21
30
 
22
- def find(ids, args)
23
- get_bibs(ids, args)
24
- end
25
31
 
26
- def get_bibs(ids, args={})
27
- args[:mms_id] = ids_from_array(ids)
28
- params = query_merge(args)
29
- response = resources.almaws_v1_bibs.get(params)
30
32
 
31
- Alma::BibSet.new(response)
32
- end
33
+ attr_accessor :id, :response
34
+
35
+ # The User object can respond directly to Hash like access of attributes
36
+ def_delegators :response, :[], :[]=, :has_key?, :keys, :to_json, :each
37
+
38
+ def initialize(response_body)
39
+ @response = response_body
40
+ @id = @response['mms_id'].to_s
41
+ end
42
+
43
+ # The raw MARCXML record, converted to a Hash
44
+ def record
45
+ @record ||= XmlSimple.xml_in(response['anies'].first)
46
+ end
47
+
33
48
 
34
49
  private
35
50
 
36
- def ids_from_array(ids)
37
- ids.map(&:to_s).map(&:strip).join(',')
51
+ def self.bibs_base_path
52
+ "#{self.region}/almaws/v1/bibs"
38
53
  end
39
54
 
40
- def set_wadl_filename
41
- 'bib.wadl'
55
+ def bibs_base_path
56
+ self.class.bibs_base_path
42
57
  end
43
58
 
44
- end
59
+ def self.headers
60
+ { "Authorization": "apikey #{self.apikey}",
61
+ "Accept": "application/json",
62
+ "Content-Type": "application/json" }
63
+ end
64
+
65
+
66
+ def headers
67
+ self.class.headers
68
+ end
69
+
70
+
71
+ def self.apikey
72
+ Alma.configuration.apikey
73
+ end
74
+
75
+ def self.region
76
+ Alma.configuration.region
77
+ end
78
+
79
+ def self.get_body_from(response)
80
+ JSON.parse(response.body)
81
+ end
82
+
83
+ def self.ids_from_array(ids)
84
+ ids.map(&:to_s).map(&:strip).join(',')
85
+ end
45
86
  end
46
87
  end
@@ -0,0 +1,49 @@
1
+ module Alma
2
+ class BibItems
3
+ extend Forwardable
4
+
5
+ attr_accessor :items
6
+ def_delegators :items, :[], :[]=, :has_key?, :keys, :to_json
7
+
8
+ attr_reader :raw_response
9
+ def_delegators :raw_response, :response, :request
10
+
11
+ def initialize(response)
12
+ @raw_response = response
13
+ @items = JSON.parse(response.body)
14
+ end
15
+
16
+ PERMITTED_ARGS = [
17
+ :limit, :offset, :expand, :user_id, :current_library,
18
+ :current_location, :q, :order_by, :direction
19
+ ]
20
+
21
+ def self.find(mms_id, options={})
22
+ holding_id = options.delete(:holding_id) || "ALL"
23
+ options.select! {|k,_| PERMITTED_ARGS.include? k }
24
+ url = "#{bibs_base_path}/#{mms_id}/holdings/#{holding_id}/items"
25
+ response = HTTParty.get(url, headers: headers, query: options)
26
+ new(response)
27
+ end
28
+
29
+ private
30
+
31
+ def self.region
32
+ Alma.configuration.region
33
+ end
34
+
35
+ def self.bibs_base_path
36
+ "#{region}/almaws/v1/bibs"
37
+ end
38
+
39
+ def self.headers
40
+ { "Authorization": "apikey #{apikey}",
41
+ "Accept": "application/json",
42
+ "Content-Type": "application/json" }
43
+ end
44
+
45
+ def self.apikey
46
+ Alma.configuration.apikey
47
+ end
48
+ end
49
+ end
@@ -1,21 +1,30 @@
1
1
  module Alma
2
- class BibSet < ResultSet
2
+ class BibSet
3
3
 
4
- def top_level_key
5
- 'bibs'
4
+ extend Forwardable
5
+ include Enumerable
6
+ #include Alma::Error
7
+
8
+ attr_reader :response
9
+ def_delegators :list, :each, :size
10
+ def_delegators :response, :[], :fetch
11
+
12
+ def initialize(response_body_hash)
13
+ @response = response_body_hash
6
14
  end
7
15
 
8
- def response_records_key
9
- 'bib'
16
+ def list
17
+ @list ||= response.fetch(key, []).map do |record|
18
+ Alma::Bib.new(record)
19
+ end
10
20
  end
11
21
 
12
- def single_record_class
13
- Alma::Bib
22
+ def key
23
+ 'bib'
14
24
  end
15
25
 
16
- # Doesn't seem to actually return a total record count as documented.
17
26
  def total_record_count
18
- (response_records.is_a? Array) ? size : 1
27
+ size
19
28
  end
20
29
 
21
30
  end
@@ -1,21 +1,39 @@
1
1
  module Alma
2
- class FineSet < ResultSet
2
+ class FineSet
3
+ extend Forwardable
4
+ include Enumerable
5
+ #include Alma::Error
3
6
 
4
- def top_level_key
5
- 'fees'
7
+ attr_reader :response
8
+ def_delegators :list, :each, :size
9
+ def_delegators :response, :[], :fetch
10
+
11
+ def initialize(response_body_hash)
12
+ @response = response_body_hash
6
13
  end
7
14
 
8
- def response_records_key
15
+ def key
9
16
  'fee'
10
17
  end
11
18
 
19
+ def list
20
+ fetch(key, [])
21
+ end
22
+
12
23
  def sum
13
- @response[top_level_key].fetch('total_sum', 0)
24
+ fetch('total_sum', 0)
14
25
  end
26
+ alias :total_sum :sum
15
27
 
16
28
  def currency
17
- @response[top_level_key].fetch('currency', nil)
29
+ fetch('currency', nil)
18
30
  end
19
31
 
32
+ def total_record_count
33
+ fetch('total_record_count', 0)
34
+ end
35
+ alias :total_records :total_record_count
36
+
37
+
20
38
  end
21
- end
39
+ end
@@ -1,18 +1,29 @@
1
1
  module Alma
2
- class LoanSet < ResultSet
2
+ class LoanSet
3
+ extend Forwardable
4
+ include Enumerable
5
+ #include Alma::Error
3
6
 
7
+ attr_reader :response
8
+ def_delegators :list, :each, :size
9
+ def_delegators :response, :[], :fetch
4
10
 
5
- def top_level_key
6
- 'item_loans'
11
+ def initialize(response_body_hash)
12
+ @response = response_body_hash
7
13
  end
8
14
 
9
- def response_records_key
15
+ def list
16
+ fetch(key, [])
17
+ end
18
+
19
+ def key
10
20
  'item_loan'
11
21
  end
12
22
 
13
- def single_record_class
14
- Alma::Loan
23
+ def total_record_count
24
+ fetch('total_record_count', 0)
15
25
  end
26
+ alias :total_records :total_record_count
16
27
 
17
28
  end
18
29
  end
@@ -1,20 +1,19 @@
1
1
  module Alma
2
2
  class RenewalResponse
3
3
 
4
- include Alma::Error
4
+
5
5
 
6
6
  def initialize(response)
7
7
  @response = response
8
- @success = response.fetch('item_loan', {})
9
- @renewed = error.empty?
8
+ @success = response.has_key?('loan_id')
10
9
  end
11
10
 
12
11
  def renewed?
13
- @renewed
12
+ @success
14
13
  end
15
14
 
16
15
  def due_date
17
- @success.fetch('due_date', '')
16
+ @response.fetch('dueDate', '')
18
17
  end
19
18
 
20
19
 
@@ -23,20 +22,24 @@ module Alma
23
22
  end
24
23
 
25
24
  def item_title
26
- if @success
27
- @success['title']
25
+ if renewed?
26
+ @response['title']
28
27
  else
29
28
  'This Item'
30
29
  end
31
30
  end
32
31
 
33
32
  def message
34
- if @success
33
+ if renewed?
35
34
  "#{item_title} is now due #{due_date}"
36
35
  else
37
36
  "#{item_title} could not be renewed."
38
37
  end
39
38
  end
40
39
 
40
+ def error_message
41
+ @response unless renewed?
42
+ end
43
+
41
44
  end
42
- end
45
+ end
@@ -1,14 +1,29 @@
1
1
  module Alma
2
- class RequestSet < ResultSet
2
+ class RequestSet
3
+ extend Forwardable
4
+ include Enumerable
5
+ #include Alma::Error
3
6
 
7
+ attr_reader :response
8
+ def_delegators :list, :each, :size
9
+ def_delegators :response, :[], :fetch
4
10
 
5
- def top_level_key
6
- 'user_requests'
11
+ def initialize(response_body_hash)
12
+ @response = response_body_hash
7
13
  end
8
14
 
9
- def response_records_key
15
+ def list
16
+ fetch(key, [])
17
+ end
18
+
19
+ def total_record_count
20
+ fetch('total_record_count', 0)
21
+ end
22
+ alias :total_records :total_record_count
23
+
24
+ def key
10
25
  'user_request'
11
26
  end
12
27
 
13
28
  end
14
- end
29
+ end
@@ -1,141 +1,177 @@
1
1
  module Alma
2
- class User < AlmaRecord
3
- extend Alma::Api
2
+ class User
3
+ extend Forwardable
4
+
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
+ end
13
+
14
+ # Authenticates a Alma user with their Alma Password
15
+ # @param [Hash] args
16
+ # @option args [String] :user_id The unique id of the user
17
+ # @option args [String] :password The users local alma password
18
+ # @return [Boolean] Whether or not the user Successfully authenticated
19
+ def self.authenticate(args)
20
+ user_id = args.delete(:user_id) { raise ArgumentError }
21
+ args.merge!({op: 'auth'})
22
+ response = HTTParty.post("#{users_base_path}/#{user_id}", query: args, headers: headers)
23
+ response.code == 204
24
+ end
4
25
 
5
- attr_accessor :id
6
26
 
7
- def post_initialize
8
- @id = response['primary_id'].to_s
27
+ # The User object can respond directly to Hash like access of attributes
28
+ def_delegators :response, :[], :[]=, :has_key?, :keys, :to_json
29
+
30
+ def initialize(response_body)
31
+ @response = response_body
9
32
  @recheck_loans = true
10
33
  end
11
34
 
35
+ def response
36
+ @response
37
+ end
38
+
39
+ def id
40
+ self['primary_id']
41
+ end
42
+
43
+
44
+ # Access the top level JSON attributes as object methods
45
+ def method_missing(name)
46
+ return response[name.to_s] if has_key?(name.to_s)
47
+ super.method_missing name
48
+ end
49
+
50
+ def respond_to_missing?(name, include_private = false)
51
+ has_key?(name.to_s) || super
52
+ end
53
+
54
+
55
+ # Persist the user in it's current state back to Alma
56
+ def save!
57
+ response = HTTParty.put("#{users_base_path}/#{id}", headers: headers, body: to_json)
58
+ get_body_from(response)
59
+ end
60
+
61
+
12
62
  def fines
13
- self.class.get_fines({user_id: self.id})
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
69
+ end
70
+
71
+ 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))
14
77
  end
15
78
 
79
+
16
80
  def loans
17
81
  unless @loans && !recheck_loans?
18
- @loans = self.class.get_loans({user_id: self.id})
82
+ @loans = send_loans_request
19
83
  @recheck_loans = false
20
84
  end
21
85
  @loans
22
86
  end
23
87
 
24
88
  def renew_loan(loan_id)
25
- response = self.class.renew_loan({user_id: self.id, loan_id: loan_id})
89
+ response = send_loan_renewal_request({user_id: id, loan_id: loan_id})
26
90
  if response.renewed?
27
91
  @recheck_loans ||= true
28
92
  end
29
- response
93
+ get_body_from response
30
94
  end
31
95
 
96
+
32
97
  def renew_multiple_loans(loan_ids)
33
98
  loan_ids.map { |id| renew_loan(id) }
34
99
  end
35
100
 
101
+
36
102
  def renew_all_loans
37
103
  renew_multiple_loans(loans.map(&:loan_id))
38
104
  end
39
105
 
106
+
40
107
  def recheck_loans?
41
108
  @recheck_loans
42
109
  end
43
110
 
44
- def requests
45
- self.class.get_requests({user_id:self.id})
111
+
112
+ def preferred_email
113
+ self["contact_info"]["email"].select { |k, v| k["preferred"] }.first["email_address"]
46
114
  end
47
115
 
48
- class << self
49
- # Static methods that do the actual querying
50
116
 
51
- def find(args = {})
52
- #TODO Handle Search Queries
53
- #TODO Handle Pagination
54
- #TODO Handle looping through all results
117
+ def email
118
+ self["contact_info"]["email"].map { |e| e["email_address"] }
119
+ end
55
120
 
56
- return find_by_id(user_id: args[:user_id]) if args.fetch(:user_id, nil)
57
- params = query_merge args
58
- response = resources.almaws_v1_users.get(params)
59
- Alma::UserSet.new(response)
60
- end
61
121
 
62
- def find_by_id(user_id_hash)
63
- params = query_merge user_id_hash
64
- response = resources.almaws_v1_users.user_id.get(params)
65
- User.new(response['user'])
66
- end
122
+ private
67
123
 
68
- def get_fines(args)
69
- #TODO Handle Additional Parameters
70
- #TODO Handle Pagination
71
- #TODO Handle looping through all results
72
- params = query_merge args
73
- response = resources.almaws_v1_users.user_id_fees.get(params)
74
- Alma::FineSet.new(response)
75
- end
124
+ def send_loans_request
125
+ #TODO Handle Additional Parameters
126
+ #TODO Handle Pagination
127
+ #TODO Handle looping through all results
128
+ response = HTTParty.get("#{users_base_path}/#{id}/loans", headers: headers)
129
+ Alma::LoanSet.new(get_body_from(response))
130
+ end
76
131
 
77
- def get_loans(args)
78
- #TODO Handle Additional Parameters
79
- #TODO Handle Pagination
80
- #TODO Handle looping through all results
81
- params = query_merge args
82
- response = resources.almaws_v1_users.user_id_loans.get(params)
83
- Alma::LoanSet.new(response)
84
- end
132
+ # Attempts to renew a single item for a user
133
+ # @param [Hash] args
134
+ # @option args [String] :user_id The unique id of the user
135
+ # @option args [String] :loan_id The unique id of the loan
136
+ # @option args [String] :user_id_type Type of identifier being used to search. OPTIONAL
137
+ # @return [RenewalResponse] Object indicating the renewal message
138
+ def send_loan_renewal_request(args)
139
+ user_id = args.delete(:user_id) { raise ArgumentError }
140
+ loan_id = args.delete(:loan_id) { raise ArgumentError }
141
+ params = {op: 'renew'}
142
+ response = HTTParty.post("#{users_base_path}/#{id}/loans/#{loan_id}", query: params, headers: headers)
143
+ RenewalResponse.new(get_body_from(response))
144
+ end
85
145
 
86
- def get_requests(args)
87
- #TODO Handle Additional Parameters
88
- #TODO Handle Pagination
89
- #TODO Handle looping through all results
90
- params = query_merge args
91
- response = resources.almaws_v1_users.user_id_requests.get(params)
92
- Alma::RequestSet.new(response)
93
- end
94
146
 
95
- def authenticate(args)
96
- # Authenticates a Alma user with their Alma Password
97
- args.merge!({op: 'auth'})
98
- params = query_merge args
99
- response = resources.almaws_v1_users.user_id.post(params)
100
- response.code == 204
101
- end
147
+ def get_body_from(response)
148
+ JSON.parse(response.body)
149
+ end
102
150
 
103
- # Attempts to renew a single item for a user
104
- # @param [Hash] args
105
- # @option args [String] :user_id The unique id of the user
106
- # @option args [String] :loan_id The unique id of the loan
107
- # @option args [String] :user_id_type Type of identifier being used to search. OPTIONAL
108
- # @return [RenewalResponse] Object indicating the renewal message
109
- def renew_loan(args)
110
- args.merge!({op: 'renew'})
111
- params = query_merge args
112
- response = resources.almaws_v1_users.user_id_loans_loan_id.post(params)
113
- RenewalResponse.new(response)
114
- end
115
151
 
116
- # Attempts to renew a multiple items for a user
117
- # @param [Hash] args
118
- # @option args [String] :user_id The unique id of the user
119
- # @option args [Array<String>] :loan_ids Array of loan ids
120
- # @option args [String] :user_id_type Type of identifier being used to search. OPTIONAL
121
- # @return [Array<RenewalResponse>] Object indicating the renewal message
122
- def renew_multiple_loans(args)
123
-
124
- if args.fetch(:loans_ids, nil).respond_to? :map
125
- args.delete(:loan_ids).map do |loan_id|
126
- renew_loan(args.merge(loan_id: loan_id))
127
- end
128
- else
129
- []
130
- end
131
- end
152
+ def self.users_base_path
153
+ "https://api-na.hosted.exlibrisgroup.com/almaws/v1/users"
154
+ end
132
155
 
156
+ def users_base_path
157
+ self.class.users_base_path
158
+ end
133
159
 
160
+ def self.headers
161
+ { "Authorization": "apikey #{self.apikey}",
162
+ "Accept": "application/json",
163
+ "Content-Type": "application/json" }
164
+ end
134
165
 
135
166
 
136
- def set_wadl_filename
137
- 'user.wadl'
138
- end
167
+ def headers
168
+ self.class.headers
169
+ end
170
+
171
+
172
+ def self.apikey
173
+ Alma.configuration.apikey
174
+ end
175
+
139
176
  end
140
177
  end
141
- end
@@ -1,3 +1,3 @@
1
1
  module Alma
2
- VERSION = "0.2.4"
2
+ VERSION = "0.2.5"
3
3
  end
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.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chad Nelson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-08 00:00:00.000000000 Z
11
+ date: 2018-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ezwadl
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: xml-simple
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: bundler
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +147,7 @@ files:
119
147
  - lib/alma/api.rb
120
148
  - lib/alma/availability_response.rb
121
149
  - lib/alma/bib.rb
150
+ - lib/alma/bib_items.rb
122
151
  - lib/alma/bib_set.rb
123
152
  - lib/alma/config.rb
124
153
  - lib/alma/error.rb
@@ -153,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
182
  version: '0'
154
183
  requirements: []
155
184
  rubyforge_project:
156
- rubygems_version: 2.5.2
185
+ rubygems_version: 2.6.11
157
186
  signing_key:
158
187
  specification_version: 4
159
188
  summary: Client for Ex Libris Alma Web Services