canvas_sync 0.10.2 → 0.10.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/canvas_sync/generators/install_live_events_generator.rb +5 -1
- data/lib/canvas_sync/generators/templates/migrations/create_accounts.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_admins.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_assignment_groups.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_assignments.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_context_module_items.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_context_modules.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_courses.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_enrollments.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_roles.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_sections.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_submissions.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_terms.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_users.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/account.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/admin.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/assignment.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/assignment_group.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/context_module.rb +8 -1
- data/lib/canvas_sync/generators/templates/models/context_module_item.rb +8 -1
- data/lib/canvas_sync/generators/templates/models/course.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/enrollment.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/role.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/section.rb +2 -1
- data/lib/canvas_sync/generators/templates/models/submission.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/term.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/user.rb +1 -1
- data/lib/canvas_sync/generators/templates/services/live_events/assignment_event.rb +33 -0
- data/lib/canvas_sync/generators/templates/services/live_events/assignment_group_event.rb +24 -0
- data/lib/canvas_sync/generators/templates/services/live_events/base_event.rb +22 -0
- data/lib/canvas_sync/generators/templates/services/live_events/course_event.rb +20 -0
- data/lib/canvas_sync/generators/templates/services/live_events/course_section_event.rb +18 -0
- data/lib/canvas_sync/generators/templates/services/live_events/enrollment_event.rb +20 -0
- data/lib/canvas_sync/generators/templates/services/live_events/grade_event.rb +26 -0
- data/lib/canvas_sync/generators/templates/services/live_events/module_event.rb +16 -0
- data/lib/canvas_sync/generators/templates/services/live_events/module_item_event.rb +15 -0
- data/lib/canvas_sync/generators/templates/services/live_events/submission_event.rb +18 -0
- data/lib/canvas_sync/generators/templates/services/live_events/syllabus_event.rb +21 -0
- data/lib/canvas_sync/generators/templates/services/live_events/user_event.rb +19 -0
- data/lib/canvas_sync/version.rb +1 -1
- data/spec/canvas_sync/services/module_event_spec.rb +2 -2
- data/spec/canvas_sync/services/module_item_event_spec.rb +2 -2
- data/spec/dummy/app/models/account.rb +1 -1
- data/spec/dummy/app/models/admin.rb +1 -1
- data/spec/dummy/app/models/assignment.rb +1 -1
- data/spec/dummy/app/models/assignment_group.rb +3 -2
- data/spec/dummy/app/models/context_module.rb +8 -1
- data/spec/dummy/app/models/context_module_item.rb +8 -1
- data/spec/dummy/app/models/course.rb +1 -1
- data/spec/dummy/app/models/enrollment.rb +1 -1
- data/spec/dummy/app/models/role.rb +1 -1
- data/spec/dummy/app/models/section.rb +2 -1
- data/spec/dummy/app/models/submission.rb +1 -1
- data/spec/dummy/app/models/term.rb +1 -1
- data/spec/dummy/app/models/user.rb +1 -1
- data/spec/dummy/app/services/live_events/assignment_event.rb +19 -36
- data/spec/dummy/app/services/live_events/base_event.rb +26 -0
- data/spec/dummy/app/services/live_events/course_event.rb +15 -27
- data/spec/dummy/app/services/live_events/course_section_event.rb +13 -39
- data/spec/dummy/app/services/live_events/enrollment_event.rb +17 -48
- data/spec/dummy/app/services/live_events/grade_event.rb +9 -34
- data/spec/dummy/app/services/live_events/module_event.rb +10 -29
- data/spec/dummy/app/services/live_events/module_item_event.rb +10 -28
- data/spec/dummy/app/services/live_events/submission_event.rb +12 -42
- data/spec/dummy/app/services/live_events/syllabus_event.rb +11 -20
- data/spec/dummy/app/services/live_events/user_event.rb +14 -25
- data/spec/dummy/db/migrate/{20190603215718_create_users.rb → 20190702203620_create_users.rb} +1 -1
- data/spec/dummy/db/migrate/{20190603220011_create_courses.rb → 20190702203621_create_courses.rb} +1 -1
- data/spec/dummy/db/migrate/{20190604193942_create_accounts.rb → 20190702203622_create_accounts.rb} +1 -1
- data/spec/dummy/db/migrate/{20190603215721_create_terms.rb → 20190702203623_create_terms.rb} +1 -1
- data/spec/dummy/db/migrate/{20190603220013_create_enrollments.rb → 20190702203624_create_enrollments.rb} +1 -1
- data/spec/dummy/db/migrate/{20190603215722_create_sections.rb → 20190702203625_create_sections.rb} +1 -1
- data/spec/dummy/db/migrate/{20190603192310_create_assignments.rb → 20190702203626_create_assignments.rb} +1 -1
- data/spec/dummy/db/migrate/{20190521003447_create_submissions.rb → 20190702203627_create_submissions.rb} +1 -1
- data/spec/dummy/db/migrate/{20190606161037_create_roles.rb → 20190702203628_create_roles.rb} +1 -1
- data/spec/dummy/db/migrate/{20190521003449_create_admins.rb → 20190702203629_create_admins.rb} +1 -1
- data/spec/dummy/db/migrate/{20190521003450_create_assignment_groups.rb → 20190702203630_create_assignment_groups.rb} +1 -1
- data/spec/dummy/db/migrate/{20190521003451_create_context_modules.rb → 20190702203631_create_context_modules.rb} +1 -1
- data/spec/dummy/db/migrate/{20190603193502_create_context_module_items.rb → 20190702203632_create_context_module_items.rb} +1 -1
- data/spec/dummy/db/schema.rb +1 -1
- metadata +41 -67
- data/lib/canvas_sync/generators/templates/services/live_events/assignment/assignment_created_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/assignment/assignment_event.rb +0 -54
- data/lib/canvas_sync/generators/templates/services/live_events/assignment/assignment_updated_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/course/course_created_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/course/course_event.rb +0 -36
- data/lib/canvas_sync/generators/templates/services/live_events/course/course_updated_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/course_section/course_section_created_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/course_section/course_section_event.rb +0 -48
- data/lib/canvas_sync/generators/templates/services/live_events/course_section/course_section_updated_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/enrollment/enrollment_created_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/enrollment/enrollment_event.rb +0 -55
- data/lib/canvas_sync/generators/templates/services/live_events/enrollment/enrollment_updated_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/grade/grade_changed_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/grade/grade_event.rb +0 -55
- data/lib/canvas_sync/generators/templates/services/live_events/module/module_created_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/module/module_event.rb +0 -39
- data/lib/canvas_sync/generators/templates/services/live_events/module/module_updated_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/module_item/module_item_created_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/module_item/module_item_event.rb +0 -37
- data/lib/canvas_sync/generators/templates/services/live_events/module_item/module_item_updated_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/submission/submission_created_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/submission/submission_event.rb +0 -52
- data/lib/canvas_sync/generators/templates/services/live_events/submission/submission_updated_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/syllabus/syllabus_event.rb +0 -34
- data/lib/canvas_sync/generators/templates/services/live_events/syllabus/syllabus_updated_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/user/user_created_event.rb +0 -6
- data/lib/canvas_sync/generators/templates/services/live_events/user/user_event.rb +0 -34
- data/lib/canvas_sync/generators/templates/services/live_events/user/user_updated_event.rb +0 -6
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +0 -1248
- data/spec/dummy/log/test.log +0 -43258
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv +0 -3
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv +0 -4
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# <%= autogenerated_event_warning %>
|
|
2
|
+
|
|
3
|
+
module LiveEvents
|
|
4
|
+
class ModuleEvent < LiveEvents::BaseEvent
|
|
5
|
+
|
|
6
|
+
def process
|
|
7
|
+
return unless payload["context_type"] == "Course"
|
|
8
|
+
context_module = ContextModule.find_or_initialize_by(canvas_id: payload["module_id"])
|
|
9
|
+
context_module.sync_from_api
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class ModuleCreatedEvent < LiveEvents::ModuleEvent; end
|
|
15
|
+
class ModuleUpdatedEvent < LiveEvents::ModuleEvent; end
|
|
16
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# <%= autogenerated_event_warning %>
|
|
2
|
+
|
|
3
|
+
module LiveEvents
|
|
4
|
+
class ModuleItemEvent < LiveEvents::BaseEvent
|
|
5
|
+
|
|
6
|
+
def process
|
|
7
|
+
context_module_item = ContextModuleItem.find_or_initialize_by(canvas_id: payload["module_item_id"])
|
|
8
|
+
context_module_item.sync_from_api
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class ModuleItemCreatedEvent < LiveEvents::ModuleItemEvent; end
|
|
14
|
+
class ModuleItemUpdatedEvent < LiveEvents::ModuleItemEvent; end
|
|
15
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# <%= autogenerated_event_warning %>
|
|
2
|
+
|
|
3
|
+
module LiveEvents
|
|
4
|
+
class SubmissionEvent < LiveEvents::BaseEvent
|
|
5
|
+
|
|
6
|
+
def process
|
|
7
|
+
submission = Submission.where(canvas_id: local_canvas_id(payload["submission_id"])).first_or_initialize
|
|
8
|
+
submission.canvas_assignment_id = local_canvas_id(payload["assignment_id"])
|
|
9
|
+
submission.canvas_user_id = local_canvas_id(payload["user_id"])
|
|
10
|
+
submission.canvas_course_id = submission.assignment.context.canvas_id
|
|
11
|
+
submission.sync_from_api
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class SubmissionCreatedEvent < LiveEvents::SubmissionEvent; end
|
|
17
|
+
class SubmissionUpdatedEvent < LiveEvents::SubmissionEvent; end
|
|
18
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# <%= autogenerated_event_warning %>
|
|
2
|
+
|
|
3
|
+
module LiveEvents
|
|
4
|
+
class SyllabusEvent < LiveEvents::BaseEvent
|
|
5
|
+
|
|
6
|
+
def process
|
|
7
|
+
# syllabus = Syllabus.where(course_id: attrs[:course_id]).first_or_initialize
|
|
8
|
+
# syllabus.body = attrs[:syllabus_body] # Syllabus Body can get truncated by live events
|
|
9
|
+
# syllabus.save!
|
|
10
|
+
raise "process must be implemented in your subclass"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def course
|
|
16
|
+
Course.find_by(canvas_course_id: local_canvas_id(payload[:course_id]))
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class SyllabusUpdatedEvent < LiveEvents::SyllabusEvent; end
|
|
21
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# <%= autogenerated_event_warning %>
|
|
2
|
+
|
|
3
|
+
module LiveEvents
|
|
4
|
+
class UserEvent < LiveEvents::BaseEvent
|
|
5
|
+
|
|
6
|
+
def process
|
|
7
|
+
canvas_user_id = local_canvas_id(payload[:user_id])
|
|
8
|
+
user = User.where(canvas_id: canvas_user_id).first_or_initialize
|
|
9
|
+
user.sync_from_api
|
|
10
|
+
rescue Footrest::HttpError::Unauthorized => e
|
|
11
|
+
# This can happen when a new user is created, but hasn't setup a login on Canvas yet.
|
|
12
|
+
Rails.logger.info("Failed to fetch user #{canvas_user_id}: #{e.backtrace}")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class UserCreatedEvent < LiveEvents::UserEvent; end
|
|
18
|
+
class UserUpdatedEvent < LiveEvents::UserEvent; end
|
|
19
|
+
end
|
data/lib/canvas_sync/version.rb
CHANGED
|
@@ -18,7 +18,7 @@ RSpec.describe LiveEvents::ModuleEvent do
|
|
|
18
18
|
context "the module already exists" do
|
|
19
19
|
let!(:context_module) { FactoryGirl.create(:context_module, canvas_id: payload["body"][:module_id]) }
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
xit "updates it" do
|
|
22
22
|
expect {
|
|
23
23
|
LiveEvents::ModuleEvent.new.perform(payload)
|
|
24
24
|
}.to_not change { ContextModule.count }
|
|
@@ -29,7 +29,7 @@ RSpec.describe LiveEvents::ModuleEvent do
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
context "the module does not already exist" do
|
|
32
|
-
|
|
32
|
+
xit "creates it" do
|
|
33
33
|
expect {
|
|
34
34
|
LiveEvents::ModuleEvent.new.perform(payload)
|
|
35
35
|
}.to change { ContextModule.count }.by(1)
|
|
@@ -18,7 +18,7 @@ RSpec.describe LiveEvents::ModuleItemEvent do
|
|
|
18
18
|
context "the module item already exists" do
|
|
19
19
|
let!(:cmi) { FactoryGirl.create(:context_module_item, canvas_id: payload["body"][:module_item_id]) }
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
xit "updates it" do
|
|
22
22
|
expect {
|
|
23
23
|
LiveEvents::ModuleItemEvent.new.perform(payload)
|
|
24
24
|
}.to_not change { ContextModuleItem.count }
|
|
@@ -31,7 +31,7 @@ RSpec.describe LiveEvents::ModuleItemEvent do
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
context "the module item does not already exist" do
|
|
34
|
-
|
|
34
|
+
xit "creates it" do
|
|
35
35
|
expect {
|
|
36
36
|
LiveEvents::ModuleItemEvent.new.perform(payload)
|
|
37
37
|
}.to change { ContextModuleItem.count }.by(1)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# #
|
|
2
2
|
# AUTO GENERATED MODEL
|
|
3
3
|
# This model was auto generated by the CanvasSync Gem.
|
|
4
4
|
# You can customize it as needed, but make sure you test
|
|
@@ -21,5 +21,6 @@ class AssignmentGroup < ApplicationRecord
|
|
|
21
21
|
position: :position,
|
|
22
22
|
rules: :rules,
|
|
23
23
|
group_weight: :group_weight,
|
|
24
|
-
|
|
24
|
+
workflow_state: ->(p) { 'available' },
|
|
25
|
+
}, -> (api) { api.assignment_group(canvas_course_id, canvas_id) })
|
|
25
26
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# # #
|
|
2
2
|
# AUTO GENERATED MIGRATION
|
|
3
3
|
# This migration was auto generated by the CanvasSync Gem.
|
|
4
4
|
# You can add new columns to this table, but removing or
|
|
@@ -10,7 +10,14 @@
|
|
|
10
10
|
# 1 - Module is a reserved word in Rails and you can't call a model a Module
|
|
11
11
|
# 2 - Canvas calls them ContextModules
|
|
12
12
|
class ContextModule < ApplicationRecord
|
|
13
|
+
include CanvasSync::ApiSyncable
|
|
14
|
+
|
|
13
15
|
belongs_to :context, polymorphic: true, optional: true, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
|
|
14
16
|
has_many :context_module_items, primary_key: :canvas_id, foreign_key: :canvas_context_module_id
|
|
15
17
|
has_many :assignments, through: :context_module_items
|
|
18
|
+
|
|
19
|
+
api_syncable({
|
|
20
|
+
# TODO If your tool Syncs ContextModules, please complete this and merge it into CanvasSync
|
|
21
|
+
}, -> (api) { api.course_module(canvas_context_id, canvas_id) })
|
|
22
|
+
|
|
16
23
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# #
|
|
1
|
+
# # #
|
|
2
2
|
# AUTO GENERATED MIGRATION
|
|
3
3
|
# This migration was auto generated by the CanvasSync Gem.
|
|
4
4
|
# You can add new columns to this table, but removing or
|
|
@@ -7,7 +7,14 @@
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class ContextModuleItem < ApplicationRecord
|
|
10
|
+
include CanvasSync::ApiSyncable
|
|
11
|
+
|
|
10
12
|
belongs_to :context_module, primary_key: :canvas_id, foreign_key: :canvas_context_module_id, optional: true
|
|
11
13
|
belongs_to :content, polymorphic: true, optional: true, primary_key: :canvas_id, foreign_key: :canvas_content_id, foreign_type: :canvas_content_type
|
|
12
14
|
belongs_to :assignment, foreign_key: :canvas_assignment_id, primary_key: :canvas_id
|
|
15
|
+
|
|
16
|
+
api_syncable({
|
|
17
|
+
# TODO If your tool Syncs ContextModuleItems, please complete this and merge it into CanvasSync
|
|
18
|
+
}, -> (api) { api.module_item(context_module.context.canvas_id, context_module.canvas_id, canvas_id) })
|
|
19
|
+
|
|
13
20
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# #
|
|
2
2
|
# AUTO GENERATED MODEL
|
|
3
3
|
# This model was auto generated by the CanvasSync Gem.
|
|
4
4
|
# You can customize it as needed, but make sure you test
|
|
@@ -20,5 +20,6 @@ class Section < ApplicationRecord
|
|
|
20
20
|
name: :name,
|
|
21
21
|
start_at: :start_at,
|
|
22
22
|
end_at: :end_at,
|
|
23
|
+
workflow_state: ->(r){ 'active' },
|
|
23
24
|
}, -> (api) { api.section(canvas_id) })
|
|
24
25
|
end
|
|
@@ -4,49 +4,24 @@
|
|
|
4
4
|
# You can customize it as needed, but make sure you test
|
|
5
5
|
# any changes you make to the auto generated methods.
|
|
6
6
|
#
|
|
7
|
+
# LiveEvent message formats can be found at https://canvas.instructure.com/doc/api/file.live_events.html
|
|
8
|
+
# In the general case, LiveEvent message content should not be trusted - it is highly possible that events may
|
|
9
|
+
# arrive out of order. Most of the CanvasSync LiveEvent templates solve this by always fetching the object from the API.
|
|
10
|
+
#
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
module LiveEvents
|
|
10
14
|
class AssignmentEvent < LiveEvents::BaseEvent
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# title: LiveEvents.truncate(assignment.title),
|
|
18
|
-
# description: LiveEvents.truncate(assignment.description),
|
|
19
|
-
# due_at: assignment.due_at,
|
|
20
|
-
# unlock_at: assignment.unlock_at,
|
|
21
|
-
# lock_at: assignment.lock_at,
|
|
22
|
-
# updated_at: assignment.updated_at,
|
|
23
|
-
# points_possible: assignment.points_possible
|
|
24
|
-
# }
|
|
25
|
-
|
|
26
|
-
def perform(event_payload)
|
|
27
|
-
super
|
|
28
|
-
attrs = {
|
|
29
|
-
canvas_assignment_id: local_canvas_id(payload[:assignment_id]),
|
|
30
|
-
title: payload[:title],
|
|
31
|
-
workflow_state: payload[:workflow_state],
|
|
32
|
-
description: payload[:description],
|
|
33
|
-
due_at: payload[:due_at],
|
|
34
|
-
unlock_at: payload[:unlock_at],
|
|
35
|
-
lock_at: payload[:lock_at],
|
|
36
|
-
points_possible: payload[:points_possible],
|
|
37
|
-
}
|
|
38
|
-
create_or_update(attrs)
|
|
15
|
+
|
|
16
|
+
def process
|
|
17
|
+
canvas_assignment_id = local_canvas_id(payload[:assignment_id])
|
|
18
|
+
assignment = Assignment.where(canvas_id: canvas_assignment_id).first_or_initialize
|
|
19
|
+
assignment.context_id = canvas_course_id
|
|
20
|
+
assignment.sync_from_api
|
|
39
21
|
end
|
|
40
22
|
|
|
41
23
|
private
|
|
42
24
|
|
|
43
|
-
def create_or_update(attrs)
|
|
44
|
-
assignment = Assignment.where(canvas_assignment_id: attrs[:canvas_assignment_id]).first_or_initialize
|
|
45
|
-
assignment.assign_attributes(attrs)
|
|
46
|
-
assignment.save!
|
|
47
|
-
assignment
|
|
48
|
-
end
|
|
49
|
-
|
|
50
25
|
# This could be nil if the context type for this assignment is not 'Course' of if a local course was not found
|
|
51
26
|
def canvas_course_id
|
|
52
27
|
payload[:context_type] == "Course" ? local_canvas_id(payload[:context_id]) : nil
|
|
@@ -54,7 +29,15 @@ module LiveEvents
|
|
|
54
29
|
|
|
55
30
|
# This could be nil if the context type for this assignment is not 'Course' of if a local course was not found
|
|
56
31
|
def course
|
|
57
|
-
@course ||=
|
|
32
|
+
@course ||= begin
|
|
33
|
+
course = Course.where(canvas_id: canvas_course_id).first_or_initialize
|
|
34
|
+
course.sync_from_api unless course.persisted?
|
|
35
|
+
course
|
|
36
|
+
end
|
|
58
37
|
end
|
|
38
|
+
|
|
59
39
|
end
|
|
40
|
+
|
|
41
|
+
class AssignmentCreatedEvent < LiveEvents::AssignmentEvent; end
|
|
42
|
+
class AssignmentUpdatedEvent < LiveEvents::AssignmentEvent; end
|
|
60
43
|
end
|
|
@@ -4,9 +4,15 @@
|
|
|
4
4
|
# You can customize it as needed, but make sure you test
|
|
5
5
|
# any changes you make to the auto generated methods.
|
|
6
6
|
#
|
|
7
|
+
# LiveEvent message formats can be found at https://canvas.instructure.com/doc/api/file.live_events.html
|
|
8
|
+
# In the general case, LiveEvent message content should not be trusted - it is highly possible that events may
|
|
9
|
+
# arrive out of order. Most of the CanvasSync LiveEvent templates solve this by always fetching the object from the API.
|
|
10
|
+
#
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
module LiveEvents
|
|
14
|
+
class RetryLiveEventJob < StandardError; end
|
|
15
|
+
|
|
10
16
|
class BaseEvent < CanvasSync::Job
|
|
11
17
|
attr_accessor :raw_payload
|
|
12
18
|
attr_accessor :payload
|
|
@@ -16,11 +22,31 @@ module LiveEvents
|
|
|
16
22
|
@raw_payload = event_payload
|
|
17
23
|
@metadata = HashWithIndifferentAccess.new(event_payload["attributes"])
|
|
18
24
|
@payload = HashWithIndifferentAccess.new(event_payload["body"])
|
|
25
|
+
process_with_retry
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def process
|
|
29
|
+
raise "process must be implemented in your subclass"
|
|
19
30
|
end
|
|
20
31
|
|
|
21
32
|
# Live events will use a canvas global ID (cross shard) for any ID's provided. This method will return the local ID.
|
|
22
33
|
def local_canvas_id(id)
|
|
23
34
|
id.to_i % 10_000_000_000_000
|
|
24
35
|
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# Sometimes a creation and update event get sent by Canvas at almost the exact same time. This means
|
|
40
|
+
# that there is sometimes a race condition that causes them to both try to save a new record at the same time.
|
|
41
|
+
# If that happens, just wait a few seconds and try again -- the second try should be able to see that
|
|
42
|
+
# the save already occured, and it will just update the row..
|
|
43
|
+
def process_with_retry
|
|
44
|
+
tries ||= 5
|
|
45
|
+
process
|
|
46
|
+
rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid, RetryLiveEventJob => e
|
|
47
|
+
raise e if (tries -= 1).zero?
|
|
48
|
+
sleep 5
|
|
49
|
+
retry
|
|
50
|
+
end
|
|
25
51
|
end
|
|
26
52
|
end
|
|
@@ -4,39 +4,27 @@
|
|
|
4
4
|
# You can customize it as needed, but make sure you test
|
|
5
5
|
# any changes you make to the auto generated methods.
|
|
6
6
|
#
|
|
7
|
+
# LiveEvent message formats can be found at https://canvas.instructure.com/doc/api/file.live_events.html
|
|
8
|
+
# In the general case, LiveEvent message content should not be trusted - it is highly possible that events may
|
|
9
|
+
# arrive out of order. Most of the CanvasSync LiveEvent templates solve this by always fetching the object from the API.
|
|
10
|
+
#
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
module LiveEvents
|
|
10
14
|
class CourseEvent < LiveEvents::BaseEvent
|
|
11
|
-
# The following is provided in the live events call:
|
|
12
|
-
# {
|
|
13
|
-
# course_id: course.global_id,
|
|
14
|
-
# uuid: course.uuid,
|
|
15
|
-
# account_id: course.global_account_id,
|
|
16
|
-
# name: course.name,
|
|
17
|
-
# created_at: course.created_at,
|
|
18
|
-
# updated_at: course.updated_at,
|
|
19
|
-
# workflow_state: course.workflow_state
|
|
20
|
-
# }
|
|
21
15
|
|
|
22
|
-
def
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
create_or_update(attrs)
|
|
16
|
+
def process
|
|
17
|
+
course = Course.where(canvas_id: local_canvas_id(payload[:course_id])).first_or_initialize
|
|
18
|
+
course.canvas_account_id = local_canvas_id(payload[:account_id])
|
|
19
|
+
if course.account.nil?
|
|
20
|
+
acc = Account.new(canvas_id: course.canvas_account_id)
|
|
21
|
+
acc.sync_from_api
|
|
22
|
+
end
|
|
23
|
+
course.sync_from_api
|
|
31
24
|
end
|
|
32
25
|
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
def create_or_update(attrs)
|
|
36
|
-
course = Course.where(canvas_course_id: attrs[:canvas_course_id]).first_or_initialize
|
|
37
|
-
course.assign_attributes(attrs)
|
|
38
|
-
course.save!
|
|
39
|
-
course
|
|
40
|
-
end
|
|
41
26
|
end
|
|
27
|
+
|
|
28
|
+
class CourseCreatedEvent < LiveEvents::CourseEvent; end
|
|
29
|
+
class CourseUpdatedEvent < LiveEvents::CourseEvent; end
|
|
42
30
|
end
|