alma 0.3.1 → 0.3.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 +4 -4
- data/.circleci/config.yml +54 -0
- data/.circleci/setup-rubygems.sh +3 -0
- data/.github/dependabot.yml +7 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +134 -0
- data/.ruby-version +1 -1
- data/Gemfile +4 -3
- data/Rakefile +3 -1
- data/alma.gemspec +17 -17
- data/lib/alma.rb +34 -26
- data/lib/alma/alma_record.rb +3 -3
- data/lib/alma/api_defaults.rb +10 -1
- data/lib/alma/availability_response.rb +49 -52
- data/lib/alma/bib.rb +23 -21
- data/lib/alma/bib_holding.rb +25 -0
- data/lib/alma/bib_item.rb +22 -9
- data/lib/alma/bib_item_set.rb +19 -8
- data/lib/alma/config.rb +3 -1
- data/lib/alma/course.rb +47 -0
- data/lib/alma/course_set.rb +17 -0
- data/lib/alma/electronic.rb +1 -1
- data/lib/alma/electronic/batch_utils.rb +11 -11
- data/lib/alma/error.rb +4 -3
- data/lib/alma/fine.rb +3 -2
- data/lib/alma/fine_set.rb +1 -1
- data/lib/alma/item_request_options.rb +4 -3
- data/lib/alma/library.rb +29 -0
- data/lib/alma/library_set.rb +21 -0
- data/lib/alma/loan.rb +4 -2
- data/lib/alma/loan_set.rb +3 -3
- data/lib/alma/location.rb +29 -0
- data/lib/alma/location_set.rb +21 -0
- data/lib/alma/renewal_response.rb +8 -8
- data/lib/alma/request.rb +16 -14
- data/lib/alma/request_options.rb +9 -7
- data/lib/alma/request_set.rb +1 -1
- data/lib/alma/user.rb +61 -59
- data/lib/alma/user_request.rb +3 -1
- data/lib/alma/version.rb +3 -1
- metadata +46 -5
- data/.travis.yml +0 -13
data/lib/alma/library.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alma
|
4
|
+
class Library < AlmaRecord
|
5
|
+
extend Alma::ApiDefaults
|
6
|
+
|
7
|
+
def self.all(args: {})
|
8
|
+
response = HTTParty.get("#{configuration_base_path}/libraries", query: args, headers: headers, timeout: timeout)
|
9
|
+
if response.code == 200
|
10
|
+
LibrarySet.new(response)
|
11
|
+
else
|
12
|
+
raise StandardError, get_body_from(response)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find(library_code:, args: {})
|
17
|
+
response = HTTParty.get("#{configuration_base_path}/libraries/#{library_code}", query: args, headers: headers, timeout: timeout)
|
18
|
+
if response.code == 200
|
19
|
+
AlmaRecord.new(response)
|
20
|
+
else
|
21
|
+
raise StandardError, get_body_from(response)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.get_body_from(response)
|
26
|
+
JSON.parse(response.body)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alma
|
4
|
+
class LibrarySet < ResultSet
|
5
|
+
def_delegators :results, :[], :empty?
|
6
|
+
|
7
|
+
def each(&block)
|
8
|
+
results.each(&block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def results
|
12
|
+
@results ||= @response.fetch(key, [])
|
13
|
+
.map { |item| single_record_class.new(item) }
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
def key
|
18
|
+
"library"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/alma/loan.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Alma
|
2
4
|
class Loan < AlmaRecord
|
3
5
|
extend Alma::ApiDefaults
|
@@ -16,10 +18,10 @@ module Alma
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def renew
|
19
|
-
Alma::User.renew_loan({user_id: user_id, loan_id: loan_id})
|
21
|
+
Alma::User.renew_loan({ user_id: user_id, loan_id: loan_id })
|
20
22
|
end
|
21
23
|
|
22
|
-
def self.where_user(user_id, args={})
|
24
|
+
def self.where_user(user_id, args = {})
|
23
25
|
# Always expand renewable unless you really don't want to
|
24
26
|
args[:expand] ||= "renewable"
|
25
27
|
# Default to upper limit
|
data/lib/alma/loan_set.rb
CHANGED
@@ -11,7 +11,7 @@ module Alma
|
|
11
11
|
attr_reader :results, :raw_response
|
12
12
|
def_delegators :results, :empty?
|
13
13
|
|
14
|
-
def initialize(raw_response, search_args={})
|
14
|
+
def initialize(raw_response, search_args = {})
|
15
15
|
@raw_response = raw_response
|
16
16
|
@response = raw_response.parsed_response
|
17
17
|
@search_args = search_args
|
@@ -40,7 +40,7 @@ module Alma
|
|
40
40
|
Enumerator.new do |yielder|
|
41
41
|
offset = 0
|
42
42
|
loop do
|
43
|
-
extra_args = @search_args.merge({limit: 100, offset: offset})
|
43
|
+
extra_args = @search_args.merge({ limit: 100, offset: offset })
|
44
44
|
r = (offset == 0) ? self : single_record_class.where_user(user_id, extra_args)
|
45
45
|
unless r.empty?
|
46
46
|
r.map { |item| yielder << item }
|
@@ -53,7 +53,7 @@ module Alma
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def each(&block)
|
56
|
-
|
56
|
+
@results.each(&block)
|
57
57
|
end
|
58
58
|
|
59
59
|
def success?
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alma
|
4
|
+
class Location < AlmaRecord
|
5
|
+
extend Alma::ApiDefaults
|
6
|
+
|
7
|
+
def self.all(library_code:, args: {})
|
8
|
+
response = HTTParty.get("#{configuration_base_path}/libraries/#{library_code}/locations", query: args, headers: headers, timeout: timeout)
|
9
|
+
if response.code == 200
|
10
|
+
LocationSet.new(response)
|
11
|
+
else
|
12
|
+
raise StandardError, get_body_from(response)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find(library_code:, location_code:, args: {})
|
17
|
+
response = HTTParty.get("#{configuration_base_path}/libraries/#{library_code}/locations/#{location_code}", query: args, headers: headers, timeout: timeout)
|
18
|
+
if response.code == 200
|
19
|
+
AlmaRecord.new(response)
|
20
|
+
else
|
21
|
+
raise StandardError, get_body_from(response)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.get_body_from(response)
|
26
|
+
JSON.parse(response.body)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alma
|
4
|
+
class LocationSet < ResultSet
|
5
|
+
def_delegators :results, :[], :empty?
|
6
|
+
|
7
|
+
def each(&block)
|
8
|
+
results.each(&block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def results
|
12
|
+
@results ||= @response.fetch(key, [])
|
13
|
+
.map { |item| single_record_class.new(item) }
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
def key
|
18
|
+
"location"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Alma
|
2
4
|
class RenewalResponse
|
3
|
-
|
4
5
|
def initialize(response)
|
5
6
|
@raw_response = response
|
6
7
|
@response = response.parsed_response
|
7
|
-
@success = response.has_key?(
|
8
|
+
@success = response.has_key?("loan_id")
|
8
9
|
end
|
9
10
|
|
10
11
|
def loggable
|
@@ -21,19 +22,19 @@ module Alma
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def due_date
|
24
|
-
@response.fetch(
|
25
|
+
@response.fetch("due_date", "")
|
25
26
|
end
|
26
27
|
|
27
28
|
|
28
29
|
def due_date_pretty
|
29
|
-
Time.parse(due_date).strftime(
|
30
|
+
Time.parse(due_date).strftime("%m-%e-%y %H:%M")
|
30
31
|
end
|
31
32
|
|
32
33
|
def item_title
|
33
34
|
if renewed?
|
34
|
-
@response[
|
35
|
+
@response["title"]
|
35
36
|
else
|
36
|
-
|
37
|
+
"This Item"
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
@@ -46,8 +47,7 @@ module Alma
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def error_message
|
49
|
-
|
50
|
+
@response unless renewed?
|
50
51
|
end
|
51
|
-
|
52
52
|
end
|
53
53
|
end
|
data/lib/alma/request.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Alma
|
2
4
|
class BibRequest
|
3
5
|
class ItemAlreadyExists < Alma::StandardError
|
@@ -11,11 +13,11 @@ module Alma
|
|
11
13
|
request = new(args)
|
12
14
|
response = HTTParty.post(
|
13
15
|
"#{bibs_base_path}/#{request.mms_id}/requests",
|
14
|
-
query: {user_id: request.user_id},
|
16
|
+
query: { user_id: request.user_id },
|
15
17
|
headers: headers,
|
16
18
|
body: request.body.to_json
|
17
19
|
)
|
18
|
-
|
20
|
+
Alma::Response.new(response)
|
19
21
|
end
|
20
22
|
|
21
23
|
attr_reader :mms_id, :user_id, :body, :request_type
|
@@ -69,18 +71,18 @@ module Alma
|
|
69
71
|
def digitization_validation(args)
|
70
72
|
args.fetch(:target_destination) do
|
71
73
|
raise ArgumentError.new(
|
72
|
-
|
74
|
+
":target_destination option must be specified when request_type is DIGITIZATION"
|
73
75
|
)
|
74
76
|
end
|
75
77
|
pd = args.fetch(:partial_digitization) do
|
76
78
|
raise ArgumentError.new(
|
77
|
-
|
79
|
+
":partial_digitization option must be specified when request_type is DIGITIZATION"
|
78
80
|
)
|
79
81
|
end
|
80
82
|
if pd == true
|
81
83
|
args.fetch(:comment) do
|
82
84
|
raise ArgumentError.new(
|
83
|
-
|
85
|
+
":comment option must be specified when :request_type is DIGITIZATION and :partial_digitization is true"
|
84
86
|
)
|
85
87
|
end
|
86
88
|
end
|
@@ -95,22 +97,22 @@ module Alma
|
|
95
97
|
def booking_validation(args)
|
96
98
|
args.fetch(:booking_start_date) do
|
97
99
|
raise ArgumentError.new(
|
98
|
-
|
100
|
+
":booking_start_date option must be specified when request_type is BOOKING"
|
99
101
|
)
|
100
102
|
end
|
101
103
|
args.fetch(:booking_end_date) do
|
102
104
|
raise ArgumentError.new(
|
103
|
-
|
105
|
+
":booking_end_date option must be specified when request_type is BOOKING"
|
104
106
|
)
|
105
107
|
end
|
106
108
|
args.fetch(:pickup_location_type) do
|
107
109
|
raise ArgumentError.new(
|
108
|
-
|
110
|
+
":pickup_location_type option must be specified when request_type is BOOKING"
|
109
111
|
)
|
110
112
|
end
|
111
113
|
args.fetch(:pickup_location_library) do
|
112
114
|
raise ArgumentError.new(
|
113
|
-
|
115
|
+
":pickup_location_library option must be specified when request_type is BOOKING"
|
114
116
|
)
|
115
117
|
end
|
116
118
|
end
|
@@ -124,12 +126,12 @@ module Alma
|
|
124
126
|
def hold_validation(args)
|
125
127
|
args.fetch(:pickup_location_type) do
|
126
128
|
raise ArgumentError.new(
|
127
|
-
|
129
|
+
":pickup_location_type option must be specified when request_type is HOLD"
|
128
130
|
)
|
129
131
|
end
|
130
132
|
args.fetch(:pickup_location_library) do
|
131
133
|
raise ArgumentError.new(
|
132
|
-
|
134
|
+
":pickup_location_library option must be specified when request_type is HOLD"
|
133
135
|
)
|
134
136
|
end
|
135
137
|
end
|
@@ -140,11 +142,11 @@ module Alma
|
|
140
142
|
request = new(args)
|
141
143
|
response = HTTParty.post(
|
142
144
|
"#{bibs_base_path}/#{request.mms_id}/holdings/#{request.holding_id}/items/#{request.item_pid}/requests",
|
143
|
-
query: {user_id: request.user_id},
|
145
|
+
query: { user_id: request.user_id },
|
144
146
|
headers: headers,
|
145
147
|
body: request.body.to_json
|
146
148
|
)
|
147
|
-
|
149
|
+
Alma::Response.new(response)
|
148
150
|
end
|
149
151
|
|
150
152
|
attr_reader :holding_id, :item_pid
|
@@ -157,7 +159,7 @@ module Alma
|
|
157
159
|
def additional_validation!(args)
|
158
160
|
args.fetch(:description) do
|
159
161
|
raise ArgumentError.new(
|
160
|
-
|
162
|
+
":description option must be specified when request_type is DIGITIZATION"
|
161
163
|
)
|
162
164
|
end
|
163
165
|
end
|
data/lib/alma/request_options.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Alma
|
2
4
|
class RequestOptions
|
3
5
|
class ResponseError < Alma::StandardError
|
@@ -18,9 +20,9 @@ module Alma
|
|
18
20
|
end
|
19
21
|
|
20
22
|
|
21
|
-
def self.get(mms_id, options={})
|
23
|
+
def self.get(mms_id, options = {})
|
22
24
|
url = "#{bibs_base_path}/#{mms_id}/request-options"
|
23
|
-
options.select! {|k,_| REQUEST_OPTIONS_PERMITTED_ARGS.include? k }
|
25
|
+
options.select! { |k, _| REQUEST_OPTIONS_PERMITTED_ARGS.include? k }
|
24
26
|
response = HTTParty.get(url, headers: headers, query: options, timeout: timeout)
|
25
27
|
new(response)
|
26
28
|
end
|
@@ -38,26 +40,26 @@ module Alma
|
|
38
40
|
|
39
41
|
def hold_allowed?
|
40
42
|
!request_options.nil? &&
|
41
|
-
!request_options.select {|option| option["type"]["value"] == "HOLD" }.empty?
|
43
|
+
!request_options.select { |option| option["type"]["value"] == "HOLD" }.empty?
|
42
44
|
end
|
43
45
|
|
44
46
|
def digitization_allowed?
|
45
47
|
!request_options.nil? &&
|
46
|
-
!request_options.select {|option| option["type"]["value"] == "DIGITIZATION" }.empty?
|
48
|
+
!request_options.select { |option| option["type"]["value"] == "DIGITIZATION" }.empty?
|
47
49
|
end
|
48
50
|
|
49
51
|
def booking_allowed?
|
50
52
|
!request_options.nil? &&
|
51
|
-
!request_options.select {|option| option["type"]["value"] == "BOOKING" }.empty?
|
53
|
+
!request_options.select { |option| option["type"]["value"] == "BOOKING" }.empty?
|
52
54
|
end
|
53
55
|
|
54
56
|
def resource_sharing_broker_allowed?
|
55
57
|
!request_options.nil? &&
|
56
|
-
!request_options.select {|option| option["type"]["value"] == "RS_BROKER" }.empty?
|
58
|
+
!request_options.select { |option| option["type"]["value"] == "RS_BROKER" }.empty?
|
57
59
|
end
|
58
60
|
|
59
61
|
def ez_borrow_link
|
60
|
-
broker = request_options.select {|option| option["type"]["value"] == "RS_BROKER" }
|
62
|
+
broker = request_options.select { |option| option["type"]["value"] == "RS_BROKER" }
|
61
63
|
broker.collect { |opt| opt["request_url"] }.first
|
62
64
|
end
|
63
65
|
end
|
data/lib/alma/request_set.rb
CHANGED
@@ -35,7 +35,7 @@ module Alma
|
|
35
35
|
Enumerator.new do |yielder|
|
36
36
|
offset = 0
|
37
37
|
loop do
|
38
|
-
r = (offset == 0) ? self : single_record_class.where_user(user_id, {limit: 100, offset: offset})
|
38
|
+
r = (offset == 0) ? self : single_record_class.where_user(user_id, { limit: 100, offset: offset })
|
39
39
|
unless r.empty?
|
40
40
|
r.map { |item| yielder << item }
|
41
41
|
offset += 100
|
data/lib/alma/user.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Alma
|
2
4
|
class User
|
3
5
|
class ResponseError < Alma::StandardError
|
@@ -5,24 +7,24 @@ module Alma
|
|
5
7
|
extend Forwardable
|
6
8
|
extend Alma::ApiDefaults
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
def self.find(user_id, args = {})
|
11
|
+
args[:expand] ||= "fees,requests,loans"
|
12
|
+
response = HTTParty.get("#{self.users_base_path}/#{user_id}", query: args, headers: headers, timeout: timeout)
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
Alma::User.new response
|
15
|
+
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
# Authenticates a Alma user with their Alma Password
|
18
|
+
# @param [Hash] args
|
19
|
+
# @option args [String] :user_id The unique id of the user
|
20
|
+
# @option args [String] :password The users local alma password
|
21
|
+
# @return [Boolean] Whether or not the user Successfully authenticated
|
22
|
+
def self.authenticate(args)
|
23
|
+
user_id = args.delete(:user_id) { raise ArgumentError }
|
24
|
+
args.merge!({ op: "auth" })
|
25
|
+
response = HTTParty.post("#{users_base_path}/#{user_id}", query: args, headers: headers, timeout: timeout)
|
26
|
+
response.code == 204
|
27
|
+
end
|
26
28
|
|
27
29
|
|
28
30
|
# The User object can respond directly to Hash like access of attributes
|
@@ -52,19 +54,19 @@ module Alma
|
|
52
54
|
end
|
53
55
|
|
54
56
|
def id
|
55
|
-
self[
|
57
|
+
self["primary_id"]
|
56
58
|
end
|
57
59
|
|
58
60
|
def total_fines
|
59
|
-
response.dig(
|
61
|
+
response.dig("fees", "value") || "0"
|
60
62
|
end
|
61
63
|
|
62
64
|
def total_requests
|
63
|
-
response.dig(
|
65
|
+
response.dig("requests", "value") || "0"
|
64
66
|
end
|
65
67
|
|
66
68
|
def total_loans
|
67
|
-
response.dig(
|
69
|
+
response.dig("loans", "value") || "0"
|
68
70
|
end
|
69
71
|
|
70
72
|
|
@@ -95,12 +97,12 @@ module Alma
|
|
95
97
|
end
|
96
98
|
|
97
99
|
|
98
|
-
def loans(args={})
|
99
|
-
|
100
|
+
def loans(args = {})
|
101
|
+
@loans ||= Alma::Loan.where_user(id, args)
|
100
102
|
end
|
101
103
|
|
102
104
|
def renew_loan(loan_id)
|
103
|
-
response = self.class.send_loan_renewal_request({user_id: id, loan_id: loan_id})
|
105
|
+
response = self.class.send_loan_renewal_request({ user_id: id, loan_id: loan_id })
|
104
106
|
if response.renewed?
|
105
107
|
@recheck_loans ||= true
|
106
108
|
end
|
@@ -130,7 +132,7 @@ module Alma
|
|
130
132
|
|
131
133
|
def preferred_middle_name
|
132
134
|
pref_middle = self["pref_middle_name"] unless self["pref_middle_name"] == ""
|
133
|
-
pref_middle
|
135
|
+
pref_middle || self["middle_name"] || ""
|
134
136
|
end
|
135
137
|
|
136
138
|
def preferred_last_name
|
@@ -150,46 +152,46 @@ module Alma
|
|
150
152
|
|
151
153
|
private
|
152
154
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
155
|
+
# Attempts to renew a single item for a user
|
156
|
+
# @param [Hash] args
|
157
|
+
# @option args [String] :user_id The unique id of the user
|
158
|
+
# @option args [String] :loan_id The unique id of the loan
|
159
|
+
# @option args [String] :user_id_type Type of identifier being used to search. OPTIONAL
|
160
|
+
# @return [RenewalResponse] Object indicating the renewal message
|
161
|
+
def self.send_loan_renewal_request(args)
|
162
|
+
loan_id = args.delete(:loan_id) { raise ArgumentError }
|
163
|
+
user_id = args.delete(:user_id) { raise ArgumentError }
|
164
|
+
params = { op: "renew" }
|
165
|
+
response = HTTParty.post("#{users_base_path}/#{user_id}/loans/#{loan_id}", query: params, headers: headers)
|
166
|
+
RenewalResponse.new(response)
|
167
|
+
end
|
166
168
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
169
|
+
# Attempts to renew multiple items for a user
|
170
|
+
# @param [Hash] args
|
171
|
+
# @option args [String] :user_id The unique id of the user
|
172
|
+
# @option args [Array<String>] :loan_ids The unique ids of the loans
|
173
|
+
# @option args [String] :user_id_type Type of identifier being used to search. OPTIONAL
|
174
|
+
# @return [Array<RenewalResponse>] Array of Objects indicating the renewal messages
|
175
|
+
def self.send_multiple_loan_renewal_requests(args)
|
176
|
+
loan_ids = args.delete(:loan_ids) { raise ArgumentError }
|
177
|
+
loan_ids.map { |id| Alma::User.send_loan_renewal_request(args.merge(loan_id: id)) }
|
178
|
+
end
|
177
179
|
|
178
|
-
|
179
|
-
|
180
|
-
|
180
|
+
def get_body_from(response)
|
181
|
+
JSON.parse(response.body)
|
182
|
+
end
|
181
183
|
|
182
184
|
|
183
|
-
|
184
|
-
|
185
|
-
|
185
|
+
def self.users_base_path
|
186
|
+
"https://api-na.hosted.exlibrisgroup.com/almaws/v1/users"
|
187
|
+
end
|
186
188
|
|
187
|
-
|
188
|
-
|
189
|
-
|
189
|
+
def users_base_path
|
190
|
+
self.class.users_base_path
|
191
|
+
end
|
190
192
|
|
191
|
-
|
192
|
-
|
193
|
-
|
193
|
+
def headers
|
194
|
+
self.class.headers
|
195
|
+
end
|
194
196
|
end
|
195
197
|
end
|