academical-api-client 0.1.0
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 +7 -0
- data/lib/academical-api-client.rb +8 -0
- data/lib/academical/api/schools.rb +135 -0
- data/lib/academical/api/sections.rb +121 -0
- data/lib/academical/api/teachers.rb +68 -0
- data/lib/academical/client.rb +33 -0
- data/lib/academical/error.rb +9 -0
- data/lib/academical/error/client_error.rb +18 -0
- data/lib/academical/http_client.rb +122 -0
- data/lib/academical/http_client/auth_handler.rb +73 -0
- data/lib/academical/http_client/error_handler.rb +51 -0
- data/lib/academical/http_client/request_handler.rb +32 -0
- data/lib/academical/http_client/response.rb +20 -0
- data/lib/academical/http_client/response_handler.rb +24 -0
- metadata +84 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9f12096992031836a22c3e9f50a22ab4f3b93235
|
4
|
+
data.tar.gz: 44b0dd7aca9efa9a9f3b3957a5e8e0bc851ebe01
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0d0bbfcee9b30be69eac31dfcadba5f29365a020767e136b593196168e83fa697ff497396635e211db68182fbfc4b3e8b6da83f5a83375b9fe7b107b2fdc9cd9
|
7
|
+
data.tar.gz: b951d46ee97b50c9628d1249821f76eb09dfae5d6c4a80b0465e0fed5247677c137965f037e3bf029c3a581d47fe5e03b4899e153805d58750b689625f447666
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module Academical
|
2
|
+
|
3
|
+
module Api
|
4
|
+
|
5
|
+
# All schools that are using Academical
|
6
|
+
class Schools
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns a school object given its ID
|
13
|
+
#
|
14
|
+
# '/schools/:id' GET
|
15
|
+
#
|
16
|
+
# id - ID of the school
|
17
|
+
def get(id, options = {})
|
18
|
+
body = options.fetch(:query, {})
|
19
|
+
|
20
|
+
@client.get("/schools/#{id}", body, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Delete a school from the API given its ID
|
24
|
+
#
|
25
|
+
# '/schools/:id' DELETE
|
26
|
+
#
|
27
|
+
# id - ID of the school
|
28
|
+
def delete(id, options = {})
|
29
|
+
body = options.fetch(:body, {})
|
30
|
+
|
31
|
+
@client.delete("/schools/#{id}", body, options)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns a list of schedules that have been created in a given school
|
35
|
+
#
|
36
|
+
# '/schools/:id/schedules' GET
|
37
|
+
#
|
38
|
+
# id - ID of the school
|
39
|
+
def schedules(id, options = {})
|
40
|
+
body = options.fetch(:query, {})
|
41
|
+
|
42
|
+
@client.get("/schools/#{id}/schedules", body, options)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns a list of students for a given school
|
46
|
+
#
|
47
|
+
# '/schools/:id/students' GET
|
48
|
+
#
|
49
|
+
# id - ID of the school
|
50
|
+
def students(id, options = {})
|
51
|
+
body = options.fetch(:query, {})
|
52
|
+
|
53
|
+
@client.get("/schools/#{id}/students", body, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns a list of sections for a given school
|
57
|
+
#
|
58
|
+
# '/schools/:id/sections' GET
|
59
|
+
#
|
60
|
+
# id - ID of the school
|
61
|
+
def sections(id, options = {})
|
62
|
+
body = options.fetch(:query, {})
|
63
|
+
|
64
|
+
@client.get("/schools/#{id}/sections", body, options)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return a list of teachers for a given school
|
68
|
+
#
|
69
|
+
# '/schools/:id/teachers' GET
|
70
|
+
#
|
71
|
+
# id - ID of the school
|
72
|
+
def teachers(id, options = {})
|
73
|
+
body = options.fetch(:query, {})
|
74
|
+
|
75
|
+
@client.get("/schools/#{id}/teachers", body, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Creates a new school object in Academical. All required parameters must be provided
|
79
|
+
#
|
80
|
+
# '/schools/' POST
|
81
|
+
#
|
82
|
+
# name - Name of the school
|
83
|
+
# nickname - Nickname of the school
|
84
|
+
# locale - Locale of the school
|
85
|
+
# timezone - Timezone of the school
|
86
|
+
# departments - A list of Department objects. Each department should specify a name and faculty_name
|
87
|
+
# identity_providers - A list of Identify Providers to use with this school
|
88
|
+
# app_ui - Object describing UI specific parameters for our planner app
|
89
|
+
# terms - A list containing Term objects. Each term should define a name, a start date and end date.
|
90
|
+
def create(name, nickname, locale, timezone, departments, identity_providers, app_ui, terms, options = {})
|
91
|
+
body = options.fetch(:body, {})
|
92
|
+
body[:name] = name
|
93
|
+
body[:nickname] = nickname
|
94
|
+
body[:locale] = locale
|
95
|
+
body[:timezone] = timezone
|
96
|
+
body[:departments] = departments
|
97
|
+
body[:identity_providers] = identity_providers
|
98
|
+
body[:app_ui] = app_ui
|
99
|
+
body[:terms] = terms
|
100
|
+
|
101
|
+
@client.post("/schools/", body, options)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Update a new school in Academical. You must provide all of the required parameters
|
105
|
+
#
|
106
|
+
# '/schools/:id/' PUT
|
107
|
+
#
|
108
|
+
# id - Generated ID for the school
|
109
|
+
# name - Name of the school
|
110
|
+
# nickname - Nickname of the school
|
111
|
+
# locale - Locale of the school
|
112
|
+
# timezone - Timezone of the school
|
113
|
+
# departments - A list of Department objects. Each department should specify a name and faculty_name
|
114
|
+
# identity_providers - A list of Identify Providers to use with this school
|
115
|
+
# app_ui - Object describing UI specific parameters for our planner app
|
116
|
+
# terms - A list containing Term objects. Each term should define a name, a start date and end date.
|
117
|
+
def update(id, name, nickname, locale, timezone, departments, identity_providers, app_ui, terms, options = {})
|
118
|
+
body = options.fetch(:body, {})
|
119
|
+
body[:name] = name
|
120
|
+
body[:nickname] = nickname
|
121
|
+
body[:locale] = locale
|
122
|
+
body[:timezone] = timezone
|
123
|
+
body[:departments] = departments
|
124
|
+
body[:identity_providers] = identity_providers
|
125
|
+
body[:app_ui] = app_ui
|
126
|
+
body[:terms] = terms
|
127
|
+
|
128
|
+
@client.put("/schools/#{id}/", body, options)
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Academical
|
2
|
+
|
3
|
+
module Api
|
4
|
+
|
5
|
+
# Represents the section of a course in a school
|
6
|
+
class Sections
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns a section object given its ID
|
13
|
+
#
|
14
|
+
# '/sections/:id' GET
|
15
|
+
#
|
16
|
+
# id - ID of the section
|
17
|
+
def get(id, options = {})
|
18
|
+
body = options.fetch(:query, {})
|
19
|
+
|
20
|
+
@client.get("/sections/#{id}", body, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Delete a section given its ID
|
24
|
+
#
|
25
|
+
# '/sections/:id' DELETE
|
26
|
+
#
|
27
|
+
# id - ID of the section
|
28
|
+
def delete(id, options = {})
|
29
|
+
body = options.fetch(:body, {})
|
30
|
+
|
31
|
+
@client.delete("/sections/#{id}", body, options)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Creates a new section object in Academical. All required parameters must be provided.
|
35
|
+
#
|
36
|
+
# '/sections/' POST
|
37
|
+
#
|
38
|
+
# course_name - Name of the course
|
39
|
+
# course_code - The code of the course which this section belongs to
|
40
|
+
# section_number - Section number of the course. This is X of Y sections for course K
|
41
|
+
# section_id - Unique identifier for the section
|
42
|
+
# term - The term object this section will be taking place in
|
43
|
+
# seats - Object describing the number of available, taken and total seats for the section
|
44
|
+
# school_id - ID of the school this section belongs to
|
45
|
+
# events - A list of events this section takes place on
|
46
|
+
# departments - List of departments this section belongs to.
|
47
|
+
# credits - Number of credits this course is worth
|
48
|
+
def create(course_name, course_code, section_number, section_id, term, seats, school_id, events, departments, credits, options = {})
|
49
|
+
body = options.fetch(:body, {})
|
50
|
+
body[:course_name] = course_name
|
51
|
+
body[:course_code] = course_code
|
52
|
+
body[:section_number] = section_number
|
53
|
+
body[:section_id] = section_id
|
54
|
+
body[:term] = term
|
55
|
+
body[:seats] = seats
|
56
|
+
body[:school_id] = school_id
|
57
|
+
body[:events] = events
|
58
|
+
body[:departments] = departments
|
59
|
+
body[:credits] = credits
|
60
|
+
|
61
|
+
@client.post("/sections/", body, options)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Update the attributes of a section given its ID as a part of the body of the request
|
65
|
+
#
|
66
|
+
# '/sections/:id' PUT
|
67
|
+
#
|
68
|
+
# id - ID of the section
|
69
|
+
# course_name - Name of the course
|
70
|
+
# course_code - The code of the course which this section belongs to
|
71
|
+
# section_number - Section number of the course. This is X of Y sections for course K
|
72
|
+
# section_id - Unique identifier for the section
|
73
|
+
# term - The term object this section will be taking place in
|
74
|
+
# seats - Object describing the number of available, taken and total seats for the section
|
75
|
+
# school_id - ID of the school this section belongs to
|
76
|
+
# events - A list of events this section takes place on
|
77
|
+
# departments - List of departments this section belongs to.
|
78
|
+
# credits - Number of credits this course is worth
|
79
|
+
def update(id, course_name, course_code, section_number, section_id, term, seats, school_id, events, departments, credits, options = {})
|
80
|
+
body = options.fetch(:body, {})
|
81
|
+
body[:course_name] = course_name
|
82
|
+
body[:course_code] = course_code
|
83
|
+
body[:section_number] = section_number
|
84
|
+
body[:section_id] = section_id
|
85
|
+
body[:term] = term
|
86
|
+
body[:seats] = seats
|
87
|
+
body[:school_id] = school_id
|
88
|
+
body[:events] = events
|
89
|
+
body[:departments] = departments
|
90
|
+
body[:credits] = credits
|
91
|
+
|
92
|
+
@client.put("/sections/#{id}", body, options)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns the list of teachers given a section ID
|
96
|
+
#
|
97
|
+
# '/sections/:id/teachers' GET
|
98
|
+
#
|
99
|
+
# id - ID of the section
|
100
|
+
def teachers(id, options = {})
|
101
|
+
body = options.fetch(:query, {})
|
102
|
+
|
103
|
+
@client.get("/sections/#{id}/teachers", body, options)
|
104
|
+
end
|
105
|
+
|
106
|
+
# List of all the schedules with a given section
|
107
|
+
#
|
108
|
+
# '/sections/:id/schedules' GET
|
109
|
+
#
|
110
|
+
# id - ID of the section
|
111
|
+
def schedules(id, options = {})
|
112
|
+
body = options.fetch(:query, {})
|
113
|
+
|
114
|
+
@client.get("/sections/#{id}/schedules", body, options)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Academical
|
2
|
+
|
3
|
+
module Api
|
4
|
+
|
5
|
+
# A teacher in a school.
|
6
|
+
class Teachers
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
# Get a teacher given its ID
|
13
|
+
#
|
14
|
+
# '/teachers/:id' GET
|
15
|
+
#
|
16
|
+
# id - ID of the teacher
|
17
|
+
def get(id, options = {})
|
18
|
+
body = options.fetch(:query, {})
|
19
|
+
|
20
|
+
@client.get("/teachers/#{id}", body, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Delete a teacher given its ID
|
24
|
+
#
|
25
|
+
# '/teachers/:id' DELETE
|
26
|
+
#
|
27
|
+
# id - ID of the teacher
|
28
|
+
def delete(id, options = {})
|
29
|
+
body = options.fetch(:body, {})
|
30
|
+
|
31
|
+
@client.delete("/teachers/#{id}", body, options)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create a new teacher in Academical. You must provide all of the required values
|
35
|
+
#
|
36
|
+
# '/teachers/' POST
|
37
|
+
#
|
38
|
+
# name - Object with the name of the teacher
|
39
|
+
# school_id - ID of the school which this teacher belongs to
|
40
|
+
def create(name, school_id, options = {})
|
41
|
+
body = options.fetch(:body, {})
|
42
|
+
body[:name] = name
|
43
|
+
body[:school_id] = school_id
|
44
|
+
|
45
|
+
@client.post("/teachers/", body, options)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Update a teacher in Academical. You must provide all of the required parameters
|
49
|
+
#
|
50
|
+
# '/teachers/:id' PUT
|
51
|
+
#
|
52
|
+
# id - ID of the teacher
|
53
|
+
# name - Object with the name of the teacher
|
54
|
+
# school_id - ID of the school which this teacher belongs to
|
55
|
+
def update(id, name, school_id, options = {})
|
56
|
+
body = options.fetch(:body, {})
|
57
|
+
body[:id] = id
|
58
|
+
body[:name] = name
|
59
|
+
body[:school_id] = school_id
|
60
|
+
|
61
|
+
@client.put("/teachers/#{id}", body, options)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
require "academical/api/schools"
|
5
|
+
require "academical/api/sections"
|
6
|
+
require "academical/api/teachers"
|
7
|
+
|
8
|
+
module Academical
|
9
|
+
|
10
|
+
class Client
|
11
|
+
|
12
|
+
def initialize(auth = {}, options = {})
|
13
|
+
@http_client = Academical::HttpClient::HttpClient.new(auth, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
# All schools that are using Academical
|
17
|
+
def schools()
|
18
|
+
Academical::Api::Schools.new(@http_client)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Represents the section of a course in a school
|
22
|
+
def sections()
|
23
|
+
Academical::Api::Sections.new(@http_client)
|
24
|
+
end
|
25
|
+
|
26
|
+
# A teacher in a school.
|
27
|
+
def teachers()
|
28
|
+
Academical::Api::Teachers.new(@http_client)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require "academical/http_client/auth_handler"
|
2
|
+
require "academical/http_client/error_handler"
|
3
|
+
require "academical/http_client/request_handler"
|
4
|
+
require "academical/http_client/response"
|
5
|
+
require "academical/http_client/response_handler"
|
6
|
+
|
7
|
+
module Academical
|
8
|
+
|
9
|
+
module HttpClient
|
10
|
+
|
11
|
+
# Main HttpClient which is used by Api classes
|
12
|
+
class HttpClient
|
13
|
+
|
14
|
+
attr_accessor :options, :headers
|
15
|
+
|
16
|
+
def initialize(auth = {}, options = {})
|
17
|
+
|
18
|
+
if auth.is_a?(String)
|
19
|
+
auth = { :http_header => auth }
|
20
|
+
end
|
21
|
+
|
22
|
+
@options = {
|
23
|
+
:base => "https://api.academical.co",
|
24
|
+
:user_agent => "alpaca/0.2.1 (https://github.com/pksunkara/alpaca)"
|
25
|
+
}
|
26
|
+
|
27
|
+
@options.update(options)
|
28
|
+
|
29
|
+
@headers = {
|
30
|
+
"user-agent" => @options[:user_agent]
|
31
|
+
}
|
32
|
+
|
33
|
+
if @options.has_key?(:headers)
|
34
|
+
@headers.update(Hash[@options[:headers].map { |k, v| [k.downcase, v] }])
|
35
|
+
@options.delete(:headers)
|
36
|
+
end
|
37
|
+
|
38
|
+
@client = Faraday.new(@options[:base]) do |conn|
|
39
|
+
conn.use(Academical::HttpClient::AuthHandler, auth)
|
40
|
+
conn.use(Academical::HttpClient::ErrorHandler)
|
41
|
+
|
42
|
+
conn.adapter(Faraday.default_adapter)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def get(path, params = {}, options = {})
|
47
|
+
request(path, nil, "get", options.merge({ :query => params }))
|
48
|
+
end
|
49
|
+
|
50
|
+
def post(path, body = {}, options = {})
|
51
|
+
request(path, body, "post", options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def patch(path, body = {}, options = {})
|
55
|
+
request(path, body, "patch", options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def delete(path, body = {}, options = {})
|
59
|
+
request(path, body, "delete", options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def put(path, body = {}, options = {})
|
63
|
+
request(path, body, "put", options)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Intermediate function which does three main things
|
67
|
+
#
|
68
|
+
# - Transforms the body of request into correct format
|
69
|
+
# - Creates the requests with give parameters
|
70
|
+
# - Returns response body after parsing it into correct format
|
71
|
+
def request(path, body, method, options)
|
72
|
+
options = @options.merge(options)
|
73
|
+
|
74
|
+
options[:headers] = options[:headers] || {}
|
75
|
+
options[:headers] = @headers.merge(Hash[options[:headers].map { |k, v| [k.downcase, v] }])
|
76
|
+
|
77
|
+
options[:body] = body
|
78
|
+
|
79
|
+
if method != "get"
|
80
|
+
options[:body] = options[:body] || {}
|
81
|
+
options = set_body(options)
|
82
|
+
end
|
83
|
+
|
84
|
+
response = create_request(method, path, options)
|
85
|
+
|
86
|
+
body = get_body(response)
|
87
|
+
|
88
|
+
Academical::HttpClient::Response.new(body, response.status, response.headers)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Creating a request with the given arguments
|
92
|
+
#
|
93
|
+
# If api_version is set, appends it immediately after host
|
94
|
+
def create_request(method, path, options)
|
95
|
+
version = options.has_key?(:api_version) ? "/#{options[:api_version]}" : ""
|
96
|
+
|
97
|
+
path = "#{version}#{path}"
|
98
|
+
|
99
|
+
instance_eval <<-RUBY, __FILE__, __LINE__ + 1
|
100
|
+
@client.#{method}(path) do |req|
|
101
|
+
req.body = options[:body]
|
102
|
+
req.headers.update(options[:headers])
|
103
|
+
req.params.update(options[:query]) if options[:query]
|
104
|
+
end
|
105
|
+
RUBY
|
106
|
+
end
|
107
|
+
|
108
|
+
# Get response body in correct format
|
109
|
+
def get_body(response)
|
110
|
+
Academical::HttpClient::ResponseHandler.get_body(response)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Set request body in correct format
|
114
|
+
def set_body(options)
|
115
|
+
Academical::HttpClient::RequestHandler.set_body(options)
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "base64"
|
2
|
+
|
3
|
+
module Academical
|
4
|
+
|
5
|
+
module HttpClient
|
6
|
+
|
7
|
+
# AuthHandler takes care of devising the auth type and using it
|
8
|
+
class AuthHandler < Faraday::Middleware
|
9
|
+
|
10
|
+
HTTP_HEADER = 1
|
11
|
+
|
12
|
+
def initialize(app, auth = {}, options = {})
|
13
|
+
@auth = auth
|
14
|
+
super(app)
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
if !@auth.empty?
|
19
|
+
auth = get_auth_type
|
20
|
+
flag = false
|
21
|
+
|
22
|
+
if auth == HTTP_HEADER
|
23
|
+
env = http_header(env)
|
24
|
+
flag = true
|
25
|
+
end
|
26
|
+
|
27
|
+
if !flag
|
28
|
+
raise StandardError.new "Unable to calculate authorization method. Please check"
|
29
|
+
end
|
30
|
+
else
|
31
|
+
raise StandardError.new "Server requires authentication to proceed further. Please check"
|
32
|
+
end
|
33
|
+
|
34
|
+
@app.call(env)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Calculating the Authentication Type
|
38
|
+
def get_auth_type()
|
39
|
+
|
40
|
+
if @auth.has_key?(:http_header)
|
41
|
+
return HTTP_HEADER
|
42
|
+
end
|
43
|
+
|
44
|
+
return -1
|
45
|
+
end
|
46
|
+
|
47
|
+
# Authorization with HTTP header
|
48
|
+
def http_header(env)
|
49
|
+
env[:request_headers]["Authorization"] = "Bearer #{@auth[:http_header]}"
|
50
|
+
|
51
|
+
return env
|
52
|
+
end
|
53
|
+
|
54
|
+
def query_params(url)
|
55
|
+
if url.query.nil? or url.query.empty?
|
56
|
+
{}
|
57
|
+
else
|
58
|
+
Faraday::Utils.parse_query(url.query)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def merge_query(env, query)
|
63
|
+
query = query.update query_params(env[:url])
|
64
|
+
|
65
|
+
env[:url].query = Faraday::Utils.build_query(query)
|
66
|
+
|
67
|
+
return env
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Academical
|
2
|
+
|
3
|
+
module HttpClient
|
4
|
+
|
5
|
+
# ErrorHanlder takes care of selecting the error message from response body
|
6
|
+
class ErrorHandler < Faraday::Middleware
|
7
|
+
|
8
|
+
def initialize(app)
|
9
|
+
super(app)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
@app.call(env).on_complete do |env|
|
14
|
+
code = env[:response].status
|
15
|
+
type = env[:response].headers["content-type"]
|
16
|
+
|
17
|
+
case code
|
18
|
+
when 500...599
|
19
|
+
raise Academical::Error::ClientError.new("Error #{code}", code)
|
20
|
+
when 400...499
|
21
|
+
body = Academical::HttpClient::ResponseHandler.get_body(env[:response])
|
22
|
+
message = ""
|
23
|
+
|
24
|
+
# If HTML, whole body is taken
|
25
|
+
if body.is_a?(String)
|
26
|
+
message = body
|
27
|
+
end
|
28
|
+
|
29
|
+
# If JSON, a particular field is taken and used
|
30
|
+
if type.include?("json") and body.is_a?(Hash)
|
31
|
+
if body.has_key?("message")
|
32
|
+
message = body["message"]
|
33
|
+
else
|
34
|
+
message = "Unable to select error message from json returned by request responsible for error"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if message == ""
|
39
|
+
message = "Unable to understand the content type of response returned by request responsible for error"
|
40
|
+
end
|
41
|
+
|
42
|
+
raise Academical::Error::ClientError.new message, code
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Academical
|
2
|
+
|
3
|
+
module HttpClient
|
4
|
+
|
5
|
+
# RequestHandler takes care of encoding the request body into format given by options
|
6
|
+
class RequestHandler
|
7
|
+
|
8
|
+
def self.set_body(options)
|
9
|
+
type = options.fetch(:request_type, "json")
|
10
|
+
|
11
|
+
# Encoding request body into JSON format
|
12
|
+
if type == "json"
|
13
|
+
request_wrapper = {}
|
14
|
+
request_wrapper[:data] = options[:body]
|
15
|
+
options[:body] = request_wrapper.to_json
|
16
|
+
options[:headers]["content-type"] = "application/json"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Raw body
|
20
|
+
if type == "raw"
|
21
|
+
options[:body] = options[:body].is_a?(Hash) ? "" : options[:body]
|
22
|
+
options[:headers].delete("content-type")
|
23
|
+
end
|
24
|
+
|
25
|
+
return options
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Academical
|
2
|
+
|
3
|
+
module HttpClient
|
4
|
+
|
5
|
+
# Response object contains the response returned by the client
|
6
|
+
class Response
|
7
|
+
|
8
|
+
attr_accessor :body, :code, :headers
|
9
|
+
|
10
|
+
def initialize(body, code, headers)
|
11
|
+
@body = body
|
12
|
+
@code = code
|
13
|
+
@headers = headers
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Academical
|
2
|
+
|
3
|
+
module HttpClient
|
4
|
+
|
5
|
+
# ResponseHandler takes care of decoding the response body into suitable type
|
6
|
+
class ResponseHandler
|
7
|
+
|
8
|
+
def self.get_body(response)
|
9
|
+
type = response.headers["content-type"]
|
10
|
+
body = response.body
|
11
|
+
|
12
|
+
# Response body is in JSON
|
13
|
+
if type.include?("json")
|
14
|
+
body = JSON.parse body
|
15
|
+
end
|
16
|
+
|
17
|
+
return body
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: academical-api-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Academical
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.8
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.8.8
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.7.7
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.7.7
|
41
|
+
description: Official Academical API library client for ruby
|
42
|
+
email: support+developers@academical.co
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- lib/academical-api-client.rb
|
48
|
+
- lib/academical/api/schools.rb
|
49
|
+
- lib/academical/api/sections.rb
|
50
|
+
- lib/academical/api/teachers.rb
|
51
|
+
- lib/academical/client.rb
|
52
|
+
- lib/academical/error.rb
|
53
|
+
- lib/academical/error/client_error.rb
|
54
|
+
- lib/academical/http_client.rb
|
55
|
+
- lib/academical/http_client/auth_handler.rb
|
56
|
+
- lib/academical/http_client/error_handler.rb
|
57
|
+
- lib/academical/http_client/request_handler.rb
|
58
|
+
- lib/academical/http_client/response.rb
|
59
|
+
- lib/academical/http_client/response_handler.rb
|
60
|
+
homepage: https://api.academical.co
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 2.2.2
|
81
|
+
signing_key:
|
82
|
+
specification_version: 4
|
83
|
+
summary: Official Academical API library client for ruby
|
84
|
+
test_files: []
|