manabu 0.0.1 → 0.0.3
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 +5 -5
- data/lib/manabu.rb +5 -0
- data/lib/manabu/class_group.rb +93 -0
- data/lib/manabu/class_groups.rb +0 -0
- data/lib/manabu/client.rb +96 -0
- data/lib/manabu/connection/auth.rb +56 -0
- data/lib/manabu/connection/error.rb +10 -0
- data/lib/manabu/connection/transactor.rb +149 -0
- data/lib/manabu/course.rb +105 -0
- data/lib/manabu/courses.rb +35 -0
- data/lib/manabu/guardian.rb +20 -0
- data/lib/manabu/resource.rb +24 -0
- data/lib/manabu/student.rb +49 -0
- data/lib/manabu/students.rb +89 -0
- data/lib/manabu/syllabuses.rb +19 -0
- data/manabu.gemspec +21 -14
- metadata +125 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a9e858021472f03b2d532caf72061380aeabe89a644faae4471492496604ac48
|
4
|
+
data.tar.gz: 176b6bdba3acfb636ecd2c6d71b67e16ae6e833bc759d5b8cd2742b812171643
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 306735afa0cf37124823c0feb56e445822667423e6c2ad460d6a3781ce266944b840b5b9c2ec5eaaeb1fc639cdd8b6c0eed4fea400a894b8e79edf9dad962b14
|
7
|
+
data.tar.gz: 31653b603f44ed4a2c69cc4545eb4002f81e956cb2874b1f165710d8d9a3b5aa108fbd1c1ebf55730c6f78f55ca3076bfa7436aa9f04c500cd9e32e333161f9f
|
data/lib/manabu.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
module Manabu
|
2
|
+
class ClassGroup < Resource
|
3
|
+
|
4
|
+
class Enrollment
|
5
|
+
|
6
|
+
def initialize(client, attributes = {})
|
7
|
+
@client = client
|
8
|
+
@id = attributes.fetch(:id, @id)
|
9
|
+
@class_group_id = attributes.fetch(:class_group_id, @class_group_id)
|
10
|
+
@student_id = attributes.fetch(:student_id, @student_id)
|
11
|
+
@student = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def student
|
15
|
+
if @student
|
16
|
+
@student
|
17
|
+
else
|
18
|
+
@student = _fetch_student
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def _fetch_student
|
25
|
+
response = @client.get("students/#{@student_id}")
|
26
|
+
Manabu::Student.new(@client, response)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :id, :name, :grade, :homeroom, :notes_count,
|
31
|
+
:enrollments_count, :facility_id
|
32
|
+
|
33
|
+
def initialize(client, **info)
|
34
|
+
super
|
35
|
+
@students = []
|
36
|
+
@enrollments = []
|
37
|
+
end
|
38
|
+
|
39
|
+
def fill(**info)
|
40
|
+
@id = info.fetch(:id, @id)
|
41
|
+
@name = info.fetch(:name, @name)
|
42
|
+
@grade = info.fetch(:grade, @grade)
|
43
|
+
@homeroom = info.fetch(:homeroom, @homeroom)
|
44
|
+
@notes_count = info.fetch(:notes_count, @notes_count)
|
45
|
+
@enrollments_count = info.fetch(:enrollments_count, @enrollments_count)
|
46
|
+
@facility_id = info.fetch(:facility_id, @facility_id)
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
def students
|
51
|
+
if @students.any?
|
52
|
+
@students
|
53
|
+
else
|
54
|
+
@students = _fetch_students
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def enrollments
|
59
|
+
if @enrollments.any?
|
60
|
+
@enrollments
|
61
|
+
else
|
62
|
+
@enrollments = _fetch_enrollments
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_student(student, args = {})
|
67
|
+
response = @client.post("class_groups/#{id}/enrollments",
|
68
|
+
student_id: student.id
|
69
|
+
)
|
70
|
+
|
71
|
+
Enrollment.new(@client, response).tap do |enrollment|
|
72
|
+
@enrollments << enrollment
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def _fetch_students
|
79
|
+
response = @client.get("class_groups/#{id}/students")
|
80
|
+
response[:students].map do |student|
|
81
|
+
Manabu::Student.new(@client, student)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def _fetch_enrollments
|
86
|
+
response = @client.get("class_groups/#{id}/enrollments")
|
87
|
+
response[:enrollments].map do |enrollment|
|
88
|
+
Enrollment.new(@client, enrollment)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
File without changes
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require_relative 'connection/auth'
|
2
|
+
require_relative 'connection/transactor'
|
3
|
+
|
4
|
+
module Manabu
|
5
|
+
# General client interface which bundles together most client functionality
|
6
|
+
class Client
|
7
|
+
attr_accessor :auth, :transactor, :status
|
8
|
+
|
9
|
+
# Initializes with login details and passes options to all linked instances.
|
10
|
+
#
|
11
|
+
# == Parameters:
|
12
|
+
# username::
|
13
|
+
# The User Name or e-mail address
|
14
|
+
# password::
|
15
|
+
# The password for the given user
|
16
|
+
# host::
|
17
|
+
# The host URL
|
18
|
+
# port::
|
19
|
+
# The host port (default 80)
|
20
|
+
# options::
|
21
|
+
# A hash of options, such as:
|
22
|
+
# * force_secure_connection - (default true), set to false to disable HTTPS/SSL
|
23
|
+
# * transport_type - (default :msgpack), sets transport data type [:msgpack, :json]
|
24
|
+
def initialize(username, password, host, port = 80, **options)
|
25
|
+
@status = :initializing
|
26
|
+
@auth = Manabu::Connection::Auth.new(username, password, host, port, options)
|
27
|
+
if @auth.success?
|
28
|
+
@transactor = @auth.transactor
|
29
|
+
@status = :connected
|
30
|
+
else
|
31
|
+
@status = :failed
|
32
|
+
raise Error::Connection::Unauthorized
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Performs a GET against the API
|
37
|
+
#
|
38
|
+
# == Parameters:
|
39
|
+
# path::
|
40
|
+
# The API endpoint path
|
41
|
+
# args::
|
42
|
+
# An argument hash
|
43
|
+
#
|
44
|
+
# == Returns:
|
45
|
+
# The returned data as an object
|
46
|
+
def get(path, **args)
|
47
|
+
@transactor.get(path, args)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Performs a POST against the API
|
51
|
+
#
|
52
|
+
# == Parameters:
|
53
|
+
# path::
|
54
|
+
# The API endpoint path
|
55
|
+
# args::
|
56
|
+
# An argument hash
|
57
|
+
#
|
58
|
+
# == Returns:
|
59
|
+
# The returned data as an object
|
60
|
+
def post(path, **args)
|
61
|
+
@transactor.post(path, args)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Performs a PATCH against the API
|
65
|
+
#
|
66
|
+
# == Parameters:
|
67
|
+
# path::
|
68
|
+
# The API endpoint path
|
69
|
+
# args::
|
70
|
+
# An argument hash
|
71
|
+
#
|
72
|
+
# == Returns:
|
73
|
+
# The returned data as an object
|
74
|
+
def patch(path, **args)
|
75
|
+
@transactor.patch(path, args)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Performs a DELETE against the API
|
79
|
+
#
|
80
|
+
# == Parameters:
|
81
|
+
# path::
|
82
|
+
# The API endpoint path
|
83
|
+
# args::
|
84
|
+
# An argument hash
|
85
|
+
#
|
86
|
+
# == Returns:
|
87
|
+
# The returned data as an object
|
88
|
+
def delete(path, **args)
|
89
|
+
@transactor.delete(path, args)
|
90
|
+
end
|
91
|
+
|
92
|
+
# def inspect
|
93
|
+
# "#<Manabu::Client:#{object_id}>"
|
94
|
+
# end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative 'transactor'
|
2
|
+
|
3
|
+
module Manabu
|
4
|
+
module Connection
|
5
|
+
class Auth
|
6
|
+
attr_accessor :username, :host, :port, :connection, :transactor, :token, :refresh_token
|
7
|
+
|
8
|
+
def initialize(username, password, host, port, **options)
|
9
|
+
@username = username
|
10
|
+
@host = host
|
11
|
+
@port = port
|
12
|
+
@transactor = Transactor.new(host, port,
|
13
|
+
options.fetch(:force_secure_connection, true),
|
14
|
+
options.fetch(:transport_type, :msgpack),
|
15
|
+
options)
|
16
|
+
@connection = false
|
17
|
+
_authenticate(username, password)
|
18
|
+
|
19
|
+
ObjectSpace.define_finalizer(self, -> { @connection = false })
|
20
|
+
end
|
21
|
+
|
22
|
+
def success?()
|
23
|
+
@connection
|
24
|
+
end
|
25
|
+
|
26
|
+
def stop()
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def _authenticate(username, password)
|
31
|
+
response = @transactor.post("authenticate", username: username, password: password)
|
32
|
+
@connection = true
|
33
|
+
|
34
|
+
@token = response[:tokens][:auth_token]
|
35
|
+
@transactor.authorization = @token
|
36
|
+
|
37
|
+
_refresh(response[:tokens])
|
38
|
+
end
|
39
|
+
|
40
|
+
def _refresh(tokens)
|
41
|
+
@refresh_token = tokens[:refresh_token]
|
42
|
+
thread = Thread.new do
|
43
|
+
loop do
|
44
|
+
break unless @connection
|
45
|
+
sleep(120)
|
46
|
+
refresh_response = transactor.post("authenticate/refresh",
|
47
|
+
refresh_token: @refresh_token
|
48
|
+
)
|
49
|
+
@transactor.authorization = refresh_response[:tokens][:auth_token]
|
50
|
+
@refresh_token = refresh_response[:tokens][:refresh_token]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
require 'typhoeus'
|
4
|
+
require 'typhoeus/adapters/faraday'
|
5
|
+
require 'json'
|
6
|
+
require 'msgpack'
|
7
|
+
require_relative 'error'
|
8
|
+
|
9
|
+
module Manabu
|
10
|
+
module Connection
|
11
|
+
# Handles transactions between server, abstracting the transport protocol and returning objects
|
12
|
+
class Transactor
|
13
|
+
attr_accessor :server_url, :server_port, :transport_type, :force_secure_connection, :status,
|
14
|
+
:api_version, :authorization
|
15
|
+
|
16
|
+
def initialize(server_url, server_port = 80, force_secure_connection = true,
|
17
|
+
transport_type = :msgpack, **options)
|
18
|
+
@server_url = server_url
|
19
|
+
@server_port = server_port
|
20
|
+
@transport_type = transport_type
|
21
|
+
@status = :unknown
|
22
|
+
@force_secure_connection = force_secure_connection
|
23
|
+
@options = options
|
24
|
+
@api_version = options[:api_version] || 1
|
25
|
+
connect
|
26
|
+
_check_server_status
|
27
|
+
end
|
28
|
+
|
29
|
+
def connect()
|
30
|
+
return @connection if @connection
|
31
|
+
@connection = Faraday.new do |conn|
|
32
|
+
conn.request :url_encoded
|
33
|
+
|
34
|
+
case @transport_type
|
35
|
+
when :msgpack
|
36
|
+
conn.headers['Accept'] = 'application/msgpack'
|
37
|
+
when :json
|
38
|
+
conn.headers['Accept'] = 'application/json'
|
39
|
+
else # someone messed up, defaulting to msgpack
|
40
|
+
@transport_type = :msgpack
|
41
|
+
conn.headers['Accept'] = 'application/msgpack'
|
42
|
+
end
|
43
|
+
|
44
|
+
conn.use FaradayMiddleware::FollowRedirects, limit: 5
|
45
|
+
conn.adapter :typhoeus
|
46
|
+
end
|
47
|
+
|
48
|
+
_kludge_windows if Gem.win_platform?
|
49
|
+
|
50
|
+
_check_server_status
|
51
|
+
end
|
52
|
+
|
53
|
+
# Gets data from the server
|
54
|
+
def get(endpoint, **args)
|
55
|
+
_define_action(:get, endpoint, args)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Sets data from the server
|
59
|
+
def post(endpoint, **args)
|
60
|
+
_define_action(:post, endpoint, args)
|
61
|
+
end
|
62
|
+
|
63
|
+
def patch(endpoint, **args)
|
64
|
+
_define_action(:patch, endpoint, args)
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete(endpoint, **args)
|
68
|
+
_define_action(:delete, endpoint, args)
|
69
|
+
end
|
70
|
+
|
71
|
+
def _define_action(action, endpoint, args)
|
72
|
+
response = connect.send(
|
73
|
+
action,
|
74
|
+
URI.encode(
|
75
|
+
"#{@protocol}://#{@server_url}:#{@server_port}/api/v#{@api_version}/#{endpoint}"),
|
76
|
+
args,
|
77
|
+
_header_hash
|
78
|
+
)
|
79
|
+
_status_raiser(response)
|
80
|
+
_datafy_response(response.body)
|
81
|
+
end
|
82
|
+
|
83
|
+
def _header_hash
|
84
|
+
Hash.new.tap do |h|
|
85
|
+
h['Authorization'] = authorization if authorization
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def _status_raiser(response)
|
91
|
+
case response.status
|
92
|
+
when 200..299
|
93
|
+
return # don't raise
|
94
|
+
else
|
95
|
+
case @transport_type
|
96
|
+
when :msgpack
|
97
|
+
raise Error::UnprocessableEntity, _datafy_msgpack(response.body)
|
98
|
+
when :json
|
99
|
+
raise Error::UnprocessableEntity, _datafy_json(response.body)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def _datafy_response(body)
|
105
|
+
case @transport_type
|
106
|
+
when :msgpack
|
107
|
+
return _datafy_msgpack(body)
|
108
|
+
when :json
|
109
|
+
return _datafy_json(body)
|
110
|
+
end
|
111
|
+
|
112
|
+
body # Just return raw data if no transport type was specified...
|
113
|
+
end
|
114
|
+
|
115
|
+
def _datafy_msgpack(body)
|
116
|
+
MessagePack::DefaultFactory.register_type(0x00, Symbol)
|
117
|
+
MessagePack.unpack(body)
|
118
|
+
rescue
|
119
|
+
raise Manabu::Connection::Error::InvalidMsgPack, 'Malformed data from server!'
|
120
|
+
end
|
121
|
+
|
122
|
+
def _datafy_json(body)
|
123
|
+
JSON.parse(body, symbolize_names: true)
|
124
|
+
rescue JSON::ParseError
|
125
|
+
raise Manabu::Connection::Error::InvalidJSON, 'Malformed data from server!'
|
126
|
+
end
|
127
|
+
|
128
|
+
def _check_server_status
|
129
|
+
@protocol = 'https'
|
130
|
+
@status = get('status')[:status]
|
131
|
+
rescue Faraday::ConnectionFailed
|
132
|
+
unless @force_secure_connection
|
133
|
+
@protocol = 'http'
|
134
|
+
@status = get('status')[:status]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Windows doesn't supply us with the correct cacert.pem, so we force it
|
139
|
+
def _kludge_windows
|
140
|
+
cert_loc = "#{__dir__}/cacert.pem"
|
141
|
+
unless File.exist? cert_loc
|
142
|
+
response = @connection.get('http://curl.haxx.se/ca/cacert.pem')
|
143
|
+
File.open(cert_loc, 'wb') { |fp| fp.write(response.body) }
|
144
|
+
end
|
145
|
+
ENV['SSL_CERT_FILE'] = cert_loc
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Manabu
|
2
|
+
class Course < Resource
|
3
|
+
|
4
|
+
class Enrollment
|
5
|
+
|
6
|
+
attr_reader :seat_number
|
7
|
+
|
8
|
+
def initialize(client, attributes = {})
|
9
|
+
@client = client
|
10
|
+
@id = attributes.fetch(:id, @id)
|
11
|
+
@course_id = attributes.fetch(:course_id, @course_id)
|
12
|
+
@student_id = attributes.fetch(:student_id, @student_id)
|
13
|
+
@seat_number = attributes.fetch(:seat_number, @seat_number)
|
14
|
+
@student = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def student
|
18
|
+
if @student
|
19
|
+
@student
|
20
|
+
else
|
21
|
+
@student = _fetch_student
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def seat_number=(value)
|
26
|
+
# TODO: handle when seat is occupied by another student
|
27
|
+
# TODO: handle other errors (EG request was invalid, request timed out)
|
28
|
+
response = @client.patch("courses/#{@course_id}/enrollments/#{@id}", seat_number: value)
|
29
|
+
@seat_number = value
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def _fetch_student
|
35
|
+
response = @client.get("students/#{@student_id}")
|
36
|
+
Manabu::Student.new(@client, response)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :id, :name, :code, :notes_count, :students_count,
|
41
|
+
:enrollments_count, :facility_id, :syllbaus_id
|
42
|
+
|
43
|
+
def initialize(client, **info)
|
44
|
+
super
|
45
|
+
@students = []
|
46
|
+
@enrollments = []
|
47
|
+
end
|
48
|
+
|
49
|
+
def fill(**info)
|
50
|
+
@id = info.fetch(:id, @id)
|
51
|
+
@name = info.fetch(:name, @name)
|
52
|
+
@code = info.fetch(:code, @code)
|
53
|
+
@notes_count = info.fetch(:notes_count, @notes_count)
|
54
|
+
@students_count = info.fetch(:students_count, @students_count)
|
55
|
+
@enrollments_count = info.fetch(:enrollments_count, @enrollments_count)
|
56
|
+
@facility_id = info.fetch(:facility_id, @facility_id)
|
57
|
+
@syllabus_id = info.fetch(:syllabus_id, @syllabus_id)
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def students
|
62
|
+
if @students.any?
|
63
|
+
@students
|
64
|
+
else
|
65
|
+
@students = _fetch_students
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def enrollments
|
70
|
+
if @enrollments.any?
|
71
|
+
@enrollments
|
72
|
+
else
|
73
|
+
@enrollments = _fetch_enrollments
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_student(student, args = {})
|
78
|
+
response = @client.post("courses/#{id}/enrollments",
|
79
|
+
student_id: student.id,
|
80
|
+
seat_number: args[:seat_number]
|
81
|
+
)
|
82
|
+
|
83
|
+
Enrollment.new(@client, response).tap do |enrollment|
|
84
|
+
@enrollments << enrollment
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def _fetch_students
|
91
|
+
response = @client.get("courses/#{id}/students")
|
92
|
+
response[:students].map do |student|
|
93
|
+
Manabu::Student.new(@client, student)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def _fetch_enrollments
|
98
|
+
response = @client.get("courses/#{id}/enrollments")
|
99
|
+
response[:enrollments].map do |enrollment|
|
100
|
+
Enrollment.new(@client, enrollment)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'client'
|
2
|
+
|
3
|
+
module Manabu
|
4
|
+
class Courses
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
end
|
8
|
+
|
9
|
+
def index
|
10
|
+
# TODO format object
|
11
|
+
@client.get('courses')
|
12
|
+
end
|
13
|
+
|
14
|
+
def register(course)
|
15
|
+
case course
|
16
|
+
when Manabu::Course
|
17
|
+
return register_course_by_object(course)
|
18
|
+
when Hash
|
19
|
+
return register_course_by_hash(course)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def register_course_by_object(course)
|
24
|
+
res = @client.post('courses', course.to_hash)
|
25
|
+
# TODO: handle errors
|
26
|
+
course.fill(res)
|
27
|
+
end
|
28
|
+
|
29
|
+
def register_course_by_hash(course)
|
30
|
+
res = @client.post('courses', course)
|
31
|
+
# TODO: handle errors
|
32
|
+
Manabu::Course.new(@client, res)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative './resource'
|
2
|
+
|
3
|
+
module Manabu
|
4
|
+
class Guardian < Resource
|
5
|
+
attr_accessor :id, :surname, :name, :name_reading, :surname_reading, :birth_date, :gender
|
6
|
+
|
7
|
+
def fill(**info)
|
8
|
+
@id = info.fetch(:id, @id)
|
9
|
+
@surname = info.fetch(:surname, @surname)
|
10
|
+
@name = info.fetch(:name, @name)
|
11
|
+
@name_reading = info.fetch(:name_reading, @name_reading)
|
12
|
+
@surname_reading = info.fetch(:surname_reading, @surname_reading)
|
13
|
+
@birth_date = info.fetch(:birth_date, @birth_date)
|
14
|
+
@gender = info.fetch(:gender, @gender)
|
15
|
+
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Manabu
|
2
|
+
class Resource
|
3
|
+
def initialize(client, **info)
|
4
|
+
@client = client
|
5
|
+
fill(info)
|
6
|
+
end
|
7
|
+
|
8
|
+
def fill(**info)
|
9
|
+
end
|
10
|
+
|
11
|
+
def _fill(var, sym, hash)
|
12
|
+
var = hash[sym] if (hash.include?(sym) && !hash[sym].nil?)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_hash
|
16
|
+
hash = {}
|
17
|
+
instance_variables.each do |var|
|
18
|
+
iv = instance_variable_get(var)
|
19
|
+
hash[(var.to_s.delete("@")).to_sym] = iv if !iv.nil?
|
20
|
+
end
|
21
|
+
hash
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative './resource'
|
2
|
+
require_relative './guardian'
|
3
|
+
|
4
|
+
module Manabu
|
5
|
+
class Student < Resource
|
6
|
+
class GuardianNotAdded < StandardError; end
|
7
|
+
attr_accessor :id, :surname, :name, :name_reading,
|
8
|
+
:surname_reading, :birth_date, :gender
|
9
|
+
|
10
|
+
def fill(**info)
|
11
|
+
@id = info.fetch(:id, @id)
|
12
|
+
@surname = info.fetch(:surname, @surname)
|
13
|
+
@name = info.fetch(:name, @name)
|
14
|
+
@name_reading = info.fetch(:name_reading, @name_reading)
|
15
|
+
@surname_reading = info.fetch(:surname_reading, @surname_reading)
|
16
|
+
@birth_date = info.fetch(:birth_date, @birth_date)
|
17
|
+
@gender = info.fetch(:gender, @gender)
|
18
|
+
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def set(**info)
|
23
|
+
response = @client.patch("students/#{@id}", info)
|
24
|
+
fill(response)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_guardian(guardian)
|
28
|
+
# NOTE: detect when guardian is already added to student
|
29
|
+
response = @client.post("students/#{id}/student_guardians", guardian_id: guardian.id)
|
30
|
+
self
|
31
|
+
rescue StandardError
|
32
|
+
raise GuardianNotAdded, 'Guardian is not added to student'
|
33
|
+
end
|
34
|
+
|
35
|
+
def guardians
|
36
|
+
response = @client.get("students/#{id}/guardians")
|
37
|
+
response[:guardians].map do |guardian|
|
38
|
+
Manabu::Guardian.new(@client, guardian)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def courses
|
43
|
+
response = @client.get("students/#{id}/courses")
|
44
|
+
response[:courses].map do |course|
|
45
|
+
Manabu::Course.new(@client, course)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative 'client'
|
2
|
+
require_relative 'student'
|
3
|
+
|
4
|
+
module Manabu
|
5
|
+
# Handles the student index for the given client
|
6
|
+
class Students
|
7
|
+
# Initializes against the passed client instance. If the client instance does not
|
8
|
+
# contain a client with a valid authorization all methods will return nil.
|
9
|
+
#
|
10
|
+
# == Parameters:
|
11
|
+
# client::
|
12
|
+
# A Manabu::Client instance (with a valid authorization)
|
13
|
+
def initialize(client)
|
14
|
+
@client = client
|
15
|
+
@students = []
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a roster of all students which the client user has access to.
|
19
|
+
#
|
20
|
+
# == Parameters:
|
21
|
+
# filters:
|
22
|
+
# A hash of filters to narrow down results. Available filters include:
|
23
|
+
# * enrollment_status - [] TODO fill in enrollment statuses
|
24
|
+
def roster(**filters)
|
25
|
+
# TODO: handle errors
|
26
|
+
# TODO: handle filters in API endpoint
|
27
|
+
# NOTE: cache results
|
28
|
+
return students if filters.empty?
|
29
|
+
|
30
|
+
students.select do |student|
|
31
|
+
filters.slice(*whitelist_filter_attributes).all? do |filter, value|
|
32
|
+
student.send(filter) == value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def register(student)
|
38
|
+
new_student = case student
|
39
|
+
when Manabu::Student
|
40
|
+
register_student_by_object(student)
|
41
|
+
when Hash
|
42
|
+
register_student_by_hash(student)
|
43
|
+
end
|
44
|
+
new_student.tap { |object| @students << object }
|
45
|
+
end
|
46
|
+
|
47
|
+
def register_student_by_object(student)
|
48
|
+
res = @client.post('students', student.to_hash)
|
49
|
+
# TODO: handle errors
|
50
|
+
student.fill(res)
|
51
|
+
end
|
52
|
+
|
53
|
+
def register_student_by_hash(student)
|
54
|
+
res = @client.post('students', student)
|
55
|
+
# TODO: handle errors
|
56
|
+
Manabu::Student.new(@client, res)
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete(student)
|
60
|
+
@client.delete("students/#{student.id}")
|
61
|
+
@students.reject! { |object| object.id == student.id }
|
62
|
+
# NOTE: check in response when implement error object
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def students()
|
69
|
+
if @students.any?
|
70
|
+
@students
|
71
|
+
else
|
72
|
+
@students = _fetch_students
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def whitelist_filter_attributes()
|
77
|
+
[:name, :surname]
|
78
|
+
end
|
79
|
+
|
80
|
+
def _fetch_students()
|
81
|
+
# TODO raise error if @client is nil
|
82
|
+
response = @client.get('students')
|
83
|
+
response[:students].map do |student|
|
84
|
+
Manabu::Student.new(@client, student)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'client'
|
2
|
+
|
3
|
+
module Manabu
|
4
|
+
class Syllabuses
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
end
|
8
|
+
|
9
|
+
def index
|
10
|
+
# TODO format object
|
11
|
+
@client.get('syllabuses')
|
12
|
+
end
|
13
|
+
|
14
|
+
def register(attributes = {})
|
15
|
+
@client.post('syllabuses', attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/manabu.gemspec
CHANGED
@@ -1,22 +1,29 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.name
|
3
|
-
s.version
|
4
|
-
s.licenses
|
5
|
-
s.summary
|
6
|
-
s.description
|
7
|
-
' Engine is a highly customizable Open Source School Management System. ' +
|
2
|
+
s.name = 'manabu'
|
3
|
+
s.version = '0.0.3'
|
4
|
+
s.licenses = ['AGPL-3.0', 'GPL-3.0']
|
5
|
+
s.summary = 'API client for GAKU Engine'
|
6
|
+
s.description = 'Manabu is an API client module used to access the GAKU Engine API'
|
8
7
|
s.post_install_message = \
|
9
8
|
'╔═════════════════════════╼' +
|
10
|
-
"║Manabu for ⚙学 GAKU Engine [学エンジン] " +
|
9
|
+
"║Manabu API Client for ⚙学 GAKU Engine [学エンジン] " +
|
11
10
|
'╟─────────────────────────╼' +
|
12
|
-
'║©2015
|
11
|
+
'║©2015 (株)幻創社 [Phantom Creation Inc.]' +
|
13
12
|
'║http://www.gakuengine.com' +
|
14
13
|
'╟─────────────────────────╼' +
|
15
|
-
'║Manabu is Open Sourced under the
|
14
|
+
'║Manabu is Open Sourced under the AGPLv3/GPLv3.' +
|
16
15
|
'╚═════════════════════════╼'
|
17
|
-
s.
|
18
|
-
s.
|
19
|
-
s.
|
20
|
-
|
21
|
-
s.
|
16
|
+
s.authors = ['Rei Kagetsuki']
|
17
|
+
s.email = 'info@gakuengine.com'
|
18
|
+
s.homepage = 'http://www.gakuengine.com'
|
19
|
+
|
20
|
+
s.files = Dir.glob('lib/**/*.rb') +
|
21
|
+
['manabu.gemspec']
|
22
|
+
s.require_paths = ['lib']
|
23
|
+
|
24
|
+
s.add_dependency 'faraday', '~> 0.13', '~> 0.13.1'
|
25
|
+
s.add_dependency 'faraday_middleware', '~> 0.12', '~> 0.12.2'
|
26
|
+
s.add_dependency 'typhoeus', '~> 1.3', '~> 1.3.0'
|
27
|
+
s.add_dependency 'msgpack', '~> 1.2', '~> 1.2.2'
|
28
|
+
s.add_development_dependency 'gaku', '~> 0.3.0', '~> 0.3.0.pre.4'
|
22
29
|
end
|
metadata
CHANGED
@@ -1,32 +1,144 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manabu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rei Kagetsuki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
date: 2018-02-21 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.13'
|
20
|
+
- - "~>"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.13.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.13'
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.13.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: faraday_middleware
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.12'
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.12.2
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.12'
|
50
|
+
- - "~>"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.12.2
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: typhoeus
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.3'
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.3.0
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.3'
|
70
|
+
- - "~>"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.3.0
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: msgpack
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '1.2'
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.2.2
|
83
|
+
type: :runtime
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.2'
|
90
|
+
- - "~>"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.2.2
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: gaku
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 0.3.0
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 0.3.0.pre.4
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.3.0
|
110
|
+
- - "~>"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 0.3.0.pre.4
|
113
|
+
description: Manabu is an API client module used to access the GAKU Engine API
|
17
114
|
email: info@gakuengine.com
|
18
115
|
executables: []
|
19
116
|
extensions: []
|
20
117
|
extra_rdoc_files: []
|
21
118
|
files:
|
119
|
+
- lib/manabu.rb
|
120
|
+
- lib/manabu/class_group.rb
|
121
|
+
- lib/manabu/class_groups.rb
|
122
|
+
- lib/manabu/client.rb
|
123
|
+
- lib/manabu/connection/auth.rb
|
124
|
+
- lib/manabu/connection/error.rb
|
125
|
+
- lib/manabu/connection/transactor.rb
|
126
|
+
- lib/manabu/course.rb
|
127
|
+
- lib/manabu/courses.rb
|
128
|
+
- lib/manabu/guardian.rb
|
129
|
+
- lib/manabu/resource.rb
|
130
|
+
- lib/manabu/student.rb
|
131
|
+
- lib/manabu/students.rb
|
132
|
+
- lib/manabu/syllabuses.rb
|
22
133
|
- manabu.gemspec
|
23
134
|
homepage: http://www.gakuengine.com
|
24
135
|
licenses:
|
25
|
-
-
|
136
|
+
- AGPL-3.0
|
137
|
+
- GPL-3.0
|
26
138
|
metadata: {}
|
27
|
-
post_install_message: "╔═════════════════════════╼║Manabu for ⚙学 GAKU Engine
|
28
|
-
╟─────────────────────────╼║©2015
|
29
|
-
is Open Sourced under the
|
139
|
+
post_install_message: "╔═════════════════════════╼║Manabu API Client for ⚙学 GAKU Engine
|
140
|
+
[学エンジン] ╟─────────────────────────╼║©2015 (株)幻創社 [Phantom Creation Inc.]║http://www.gakuengine.com╟─────────────────────────╼║Manabu
|
141
|
+
is Open Sourced under the AGPLv3/GPLv3.╚═════════════════════════╼"
|
30
142
|
rdoc_options: []
|
31
143
|
require_paths:
|
32
144
|
- lib
|
@@ -42,8 +154,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
42
154
|
version: '0'
|
43
155
|
requirements: []
|
44
156
|
rubyforge_project:
|
45
|
-
rubygems_version: 2.
|
157
|
+
rubygems_version: 2.7.3
|
46
158
|
signing_key:
|
47
159
|
specification_version: 4
|
48
|
-
summary:
|
160
|
+
summary: API client for GAKU Engine
|
49
161
|
test_files: []
|