bearcat 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +8 -0
- data/bearcat.gemspec +27 -0
- data/lib/bearcat.rb +2 -0
- data/lib/bearcat/api_array.rb +118 -0
- data/lib/bearcat/client.rb +20 -0
- data/lib/bearcat/client/assignments.rb +18 -0
- data/lib/bearcat/client/courses.rb +19 -0
- data/lib/bearcat/client/enrollments.rb +19 -0
- data/lib/bearcat/client/outcome_groups.rb +81 -0
- data/lib/bearcat/client/outcomes.rb +15 -0
- data/lib/bearcat/client/sections.rb +27 -0
- data/lib/bearcat/version.rb +3 -0
- data/spec/bearcat/client/assignments_spec.rb +39 -0
- data/spec/bearcat/client/courses_spec.rb +31 -0
- data/spec/bearcat/client/enrollments_spec.rb +42 -0
- data/spec/bearcat/client/outcome_groups_spec.rb +104 -0
- data/spec/bearcat/client/outcomes_spec.rb +27 -0
- data/spec/bearcat/client/sections_spec.rb +51 -0
- data/spec/bearcat/client_spec.rb +16 -0
- data/spec/bearcat_spec.rb +8 -0
- data/spec/fixtures/assignment_section_override.json +9 -0
- data/spec/fixtures/assignments.json +86 -0
- data/spec/fixtures/conclude_enrollment.json +20 -0
- data/spec/fixtures/course.json +46 -0
- data/spec/fixtures/course_sections.json +20 -0
- data/spec/fixtures/course_students.json +6 -0
- data/spec/fixtures/create_outcome_in_group.json +23 -0
- data/spec/fixtures/create_section.json +1 -0
- data/spec/fixtures/created_assignment.json +25 -0
- data/spec/fixtures/created_course.json +27 -0
- data/spec/fixtures/delete_section.json +1 -0
- data/spec/fixtures/enroll_student.json +20 -0
- data/spec/fixtures/link_unlink_outcome.json +23 -0
- data/spec/fixtures/outcome_group_import.json +22 -0
- data/spec/fixtures/outcome_groups.json +29 -0
- data/spec/fixtures/outcome_subgroup.json +22 -0
- data/spec/fixtures/outcome_subgroups.json +20 -0
- data/spec/fixtures/outcomes.json +33 -0
- data/spec/fixtures/paged_body.json +92 -0
- data/spec/fixtures/section.json +1 -0
- data/spec/fixtures/update_outcome.json +1 -0
- data/spec/fixtures/update_outcome_group.json +22 -0
- data/spec/fixtures/update_section.json +1 -0
- data/spec/fixtures/user_enrollments.json +23 -0
- data/spec/helper.rb +43 -0
- metadata +220 -0
data/Rakefile
ADDED
data/bearcat.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bearcat/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.authors = ["Nathan Mills"]
|
8
|
+
gem.email = ["nathanm@instructure.com"]
|
9
|
+
gem.description = %q{Ruby interface for interacting with the canvas API}
|
10
|
+
gem.summary = %q{Canvas API}
|
11
|
+
|
12
|
+
gem.files = %w[Rakefile bearcat.gemspec]
|
13
|
+
gem.files += Dir.glob("lib/**/*.rb")
|
14
|
+
gem.files += Dir.glob("spec/**/*")
|
15
|
+
gem.test_files = Dir.glob("spec/**/*")
|
16
|
+
gem.name = "bearcat"
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
gem.version = Bearcat::VERSION
|
19
|
+
|
20
|
+
gem.add_development_dependency "rake"
|
21
|
+
gem.add_development_dependency "bundler", ">= 1.0.0"
|
22
|
+
gem.add_development_dependency "rspec", "~> 2.6"
|
23
|
+
gem.add_development_dependency "webmock"
|
24
|
+
gem.add_development_dependency "debugger"
|
25
|
+
|
26
|
+
gem.add_dependency "footrest", ">= 0.1.2"
|
27
|
+
end
|
data/lib/bearcat.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
module Bearcat
|
2
|
+
class ApiArray
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :status, :headers, :members
|
6
|
+
|
7
|
+
def self.process_response(response, api_client)
|
8
|
+
if response.body.is_a? Array
|
9
|
+
ApiArray.new response, api_client
|
10
|
+
else
|
11
|
+
response.body
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(response, api_client)
|
16
|
+
@api_client = api_client
|
17
|
+
case response.status
|
18
|
+
when 200..206
|
19
|
+
if response.body.is_a?(Array)
|
20
|
+
@members = response.body
|
21
|
+
@status = response.status
|
22
|
+
@headers = response.headers
|
23
|
+
@method = response.env[:method]
|
24
|
+
init_pages(@headers['Link'])
|
25
|
+
end
|
26
|
+
else
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def [](i)
|
31
|
+
@members[i]
|
32
|
+
end
|
33
|
+
|
34
|
+
def last
|
35
|
+
@members.last
|
36
|
+
end
|
37
|
+
|
38
|
+
def each(&block)
|
39
|
+
@members.each { |member| block.call(member) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def pages?
|
43
|
+
!@link_hash.empty?
|
44
|
+
end
|
45
|
+
|
46
|
+
def next_page
|
47
|
+
load_page('next')
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
def prev_page
|
52
|
+
load_page('prev')
|
53
|
+
end
|
54
|
+
|
55
|
+
def first_page
|
56
|
+
load_page('first')
|
57
|
+
end
|
58
|
+
|
59
|
+
def last_page
|
60
|
+
load_page('last')
|
61
|
+
end
|
62
|
+
|
63
|
+
def all_pages!(page_count = 50)
|
64
|
+
if pages?
|
65
|
+
@page_count = page_count
|
66
|
+
response = get_page(@link_hash['first'])
|
67
|
+
@headers = response.headers
|
68
|
+
@status = response.status
|
69
|
+
@method = response.env[:method]
|
70
|
+
init_pages(@headers[:link])
|
71
|
+
@members = response.body
|
72
|
+
while @link_hash['next']
|
73
|
+
response = get_page(@link_hash['next'])
|
74
|
+
@headers = response.headers
|
75
|
+
@status = response.status
|
76
|
+
@method = response.env[:method]
|
77
|
+
@members.concat(response.body)
|
78
|
+
init_pages(@headers[:link])
|
79
|
+
end
|
80
|
+
@link_hash = {}
|
81
|
+
self
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def init_pages(link_header)
|
88
|
+
@link_hash = {}
|
89
|
+
if @headers.has_key? 'Link'
|
90
|
+
links = link_header.split(/,\s?/)
|
91
|
+
|
92
|
+
links.each do |link|
|
93
|
+
link_parts = link.split(/;\s?/)
|
94
|
+
url = link_parts.shift.strip.gsub(/^<|>$/, '')
|
95
|
+
rel = link_parts.find { |part| part.gsub('"', '').split('=').first == 'rel' }
|
96
|
+
@link_hash[rel.gsub('"', '').split('=').last] = url
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_page(url, params = {})
|
102
|
+
params['per_page'] = @page_count unless params.has_key? 'per_page' || !@page_count
|
103
|
+
query = URI.parse(url).query
|
104
|
+
p = CGI.parse(query).merge(params)
|
105
|
+
u = url.gsub("?#{query}", '')
|
106
|
+
p.each { |k, v| p[k] = v.first if v.is_a?(Array) }
|
107
|
+
@api_client.request(:get, u, p)
|
108
|
+
end
|
109
|
+
|
110
|
+
def load_page(rel)
|
111
|
+
if @link_hash.has_key? rel
|
112
|
+
response = get_page(@link_hash[rel])
|
113
|
+
ApiArray.process_response(response, @api_client)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'footrest/client'
|
2
|
+
require 'bearcat/client/assignments'
|
3
|
+
require 'bearcat/client/courses'
|
4
|
+
require 'bearcat/client/enrollments'
|
5
|
+
require 'bearcat/client/outcome_groups'
|
6
|
+
require 'bearcat/client/outcomes'
|
7
|
+
require 'bearcat/client/sections'
|
8
|
+
|
9
|
+
module Bearcat
|
10
|
+
class Client < Footrest::Client
|
11
|
+
|
12
|
+
include Assignments
|
13
|
+
include Courses
|
14
|
+
include Enrollments
|
15
|
+
include OutcomeGroups
|
16
|
+
include Outcomes
|
17
|
+
include Sections
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Bearcat
|
2
|
+
class Client < Footrest::Client
|
3
|
+
module Assignments
|
4
|
+
|
5
|
+
def assignments(course, params={})
|
6
|
+
get("/api/v1/courses/#{course}/assignments", params)
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_assignment_override(course, assignment, params)
|
10
|
+
post("api/v1/courses/#{course}/assignments/#{assignment}/overrides", params)
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_assignment(course, params={})
|
14
|
+
post("/api/v1/courses/#{course}/assignments", params)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Bearcat
|
2
|
+
class Client < Footrest::Client
|
3
|
+
module Courses
|
4
|
+
|
5
|
+
def course(course)
|
6
|
+
get("/api/v1/courses/#{course}")
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_course(account_id, params={})
|
10
|
+
post("/api/v1/accounts/#{account_id}/courses", params)
|
11
|
+
end
|
12
|
+
|
13
|
+
def list_users(course, params={})
|
14
|
+
get("/api/v1/courses/#{course}/users", params)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Bearcat
|
2
|
+
class Client < Footrest::Client
|
3
|
+
module Enrollments
|
4
|
+
|
5
|
+
def user_enrollments(user, params={})
|
6
|
+
get("/api/v1/users/#{user.to_s}/enrollments", params)
|
7
|
+
end
|
8
|
+
|
9
|
+
def enroll_in_section(section, params={})
|
10
|
+
post("/api/v1/sections/#{section.to_s}/enrollments", params)
|
11
|
+
end
|
12
|
+
|
13
|
+
def conclude_enrollment(course, enrollment, params={})
|
14
|
+
delete("/api/v1/courses/#{course}/enrollments/#{enrollment}", params)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Bearcat
|
2
|
+
class Client < Footrest::Client
|
3
|
+
module OutcomeGroups
|
4
|
+
|
5
|
+
def show_outcome_group(outcome_group_id, params={})
|
6
|
+
get("#{outcomes_context_slug(params)}#{outcome_group_id}")
|
7
|
+
end
|
8
|
+
|
9
|
+
def update_outcome_group(outcome_group_id, params={})
|
10
|
+
put("#{outcomes_context_slug(params)}#{outcome_group_id}", params)
|
11
|
+
end
|
12
|
+
|
13
|
+
def delete_outcome_group(outcome_group_id, params={})
|
14
|
+
delete("#{outcomes_context_slug(params)}#{outcome_group_id}")
|
15
|
+
end
|
16
|
+
|
17
|
+
def list_linked_outcomes(outcome_group_id, params={})
|
18
|
+
get("#{outcomes_context_slug(params)}#{outcome_group_id}/outcomes")
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_outcome_in_group(outcome_group_id, params={})
|
22
|
+
post("#{outcomes_context_slug(params)}#{outcome_group_id}/outcomes", params)
|
23
|
+
end
|
24
|
+
|
25
|
+
def link_outcome(outcome_group_id, outcome_id, params={})
|
26
|
+
put("#{outcomes_context_slug(params)}#{outcome_group_id}/outcomes/#{outcome_id}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def unlink_outcome(outcome_group_id, outcome_id, params={})
|
30
|
+
delete("#{outcomes_context_slug(params)}#{outcome_group_id}/outcomes/#{outcome_id}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def list_subgroups(outcome_group_id, params={})
|
34
|
+
get("#{outcomes_context_slug(params)}#{outcome_group_id}/subgroups")
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_subgroup(outcome_group_id, params={})
|
38
|
+
post("#{outcomes_context_slug(params)}#{outcome_group_id}/subgroups", params)
|
39
|
+
end
|
40
|
+
|
41
|
+
def import_outcome_group(outcome_group_id, params={})
|
42
|
+
post("#{outcomes_context_slug(params)}#{outcome_group_id}/import", params)
|
43
|
+
end
|
44
|
+
|
45
|
+
def outcomes_context_slug(params)
|
46
|
+
context_hash = params.select { |k, _| k == "account" || k == "course" }
|
47
|
+
|
48
|
+
if context_hash.keys.count > 1
|
49
|
+
raise ArgumentError, "cannot have account and course in params"
|
50
|
+
elsif context_hash.empty?
|
51
|
+
return "#{config.prefix}#{global_slug}"
|
52
|
+
else
|
53
|
+
context_hash_key = context_hash.keys.first
|
54
|
+
case context_hash_key
|
55
|
+
when 'account'
|
56
|
+
"#{config.prefix}#{account_slug(context_hash[context_hash_key])}"
|
57
|
+
when 'course'
|
58
|
+
"#{config.prefix}#{course_slug(context_hash[context_hash_key])}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def account_slug(account_id)
|
65
|
+
"accounts/#{account_id}/outcome_groups/"
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
private
|
70
|
+
def course_slug(course_id)
|
71
|
+
"courses/#{course_id}/outcome_groups/"
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def global_slug
|
76
|
+
"global/outcome_groups/"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Bearcat
|
2
|
+
class Client < Footrest::Client
|
3
|
+
module Sections
|
4
|
+
|
5
|
+
def course_sections(course, params={})
|
6
|
+
get("/api/v1/courses/#{course.to_s}/sections", params)
|
7
|
+
end
|
8
|
+
|
9
|
+
def section(section)
|
10
|
+
get("/api/v1/sections/#{section.to_s}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_section(course, params)
|
14
|
+
post("/api/v1/courses/#{course.to_s}/sections", params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def update_section(section, params)
|
18
|
+
put("/api/v1/sections/#{section.to_s}", params)
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete_section(section)
|
22
|
+
delete("/api/v1/sections/#{section.to_s}")
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Bearcat::Client::Assignments do
|
4
|
+
before do
|
5
|
+
@client = Bearcat::Client.new(prefix: "http://canvas.instructure.com", token: "test_token")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "returns all assignments for a course" do
|
9
|
+
stub_get(@client, "/api/v1/courses/3/assignments").to_return(json_response("assignments.json"))
|
10
|
+
assignments = @client.assignments(3)
|
11
|
+
expect(assignments.count).to eq(2)
|
12
|
+
expect(assignments.first["assignment_group_id"]).to eq(53)
|
13
|
+
expect(assignments.first["id"]).to eq(123)
|
14
|
+
expect(assignments.first["due_at"]).to eq(nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "creates an assignment override for a section" do
|
18
|
+
stub_post(@client, "/api/v1/courses/310/assignments/123/overrides")
|
19
|
+
.with(:body => {"assignment_override"=>{"course_section_id"=>"74", "due_at"=>"2013-06-27T21:08:46Z"}})
|
20
|
+
.to_return(json_response("assignment_section_override.json"))
|
21
|
+
override = @client.create_assignment_override(310, 123, {
|
22
|
+
"assignment_override[course_section_id]" => 74,
|
23
|
+
"assignment_override[due_at]" => "2013-06-27T21:08:46Z"
|
24
|
+
})
|
25
|
+
expect(override["all_day"]).to eq(false)
|
26
|
+
expect(override["due_at"]).to eq("2013-06-27T15:08:46-06:00")
|
27
|
+
expect(override["id"]).to eq(1)
|
28
|
+
expect(override["course_section_id"]).to eq(74)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "creates a new assignment" do
|
32
|
+
name = "new assignment"
|
33
|
+
stub_post(@client, "/api/v1/courses/1/assignments").with(body: {"assignment" => {"name" => name}}).to_return(json_response("created_assignment.json"))
|
34
|
+
assignment = @client.create_assignment(1, {"assignment" => {"name" => name}})
|
35
|
+
expect(assignment["name"]).to eq(name)
|
36
|
+
expect(assignment["id"]).to eq(1)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Bearcat::Client::Sections do
|
4
|
+
before do
|
5
|
+
@client = Bearcat::Client.new(prefix: "http://canvas.instructure.com", token: "test_token")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "returns a section" do
|
9
|
+
stub_get(@client, "/api/v1/courses/3").to_return(json_response("course.json"))
|
10
|
+
course = @client.course(3)
|
11
|
+
expect(course['name']).to eq('Course 3')
|
12
|
+
expect(course['id']).to eq(3)
|
13
|
+
expect(course['start_at']).to eq('2012-06-01T00:00:00-06:00')
|
14
|
+
end
|
15
|
+
|
16
|
+
it "creates a new course" do
|
17
|
+
name = "new course"
|
18
|
+
stub_post(@client, "/api/v1/accounts/1/courses").with(body: {"course" => {"name" => name}}).to_return(json_response("created_course.json"))
|
19
|
+
course = @client.create_course(1, {"course[name]" => name})
|
20
|
+
expect(course['name']).to eq(name)
|
21
|
+
expect(course['id']).to eq(1)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "lists all of the students in a course" do
|
25
|
+
stub_get(@client, "/api/v1/courses/1/users?enrollment_type=student").to_return(json_response("course_students.json"))
|
26
|
+
students = @client.list_users(1, {"enrollment_type" => "student"})
|
27
|
+
expect(students['name']).to eq('test@student.com')
|
28
|
+
expect(students['id']).to eq(2)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|