canvas_sync 0.26.0.beta2 → 0.26.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 +4 -4
- data/README.md +20 -0
- data/lib/canvas_sync/concerns/ability_helper.rb +17 -3
- data/lib/canvas_sync/concerns/api_syncable.rb +5 -5
- data/lib/canvas_sync/concerns/jit_syncing.rb +59 -0
- data/lib/canvas_sync/generators/templates/models/course.rb +5 -1
- data/lib/canvas_sync/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: de18757d9f34a2b87abf23c01b530ec430c9b062076807fdfc0a7998275f32fd
|
|
4
|
+
data.tar.gz: 23d760b8d2321535b13f54bd180127da73b850208b9fe8c290c3df104c8bd87c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7550620a27aaf21ef46781f6aa1f13019b5fca01740e1042a84f382617d4ebe685663a3351ddb3672dc4ec04b0690a313a7d0ffa797a3346f80cee36c0f87a4d
|
|
7
|
+
data.tar.gz: 2ddf86c553495b781a7023ad6171f1594c19def1bdfee9fe17dbd1160741f06c229b75d728c3161a4d36bbd34ce1bfc86a6d1ab91e4b2f0b15f5f382e10be2c0
|
data/README.md
CHANGED
|
@@ -302,6 +302,26 @@ class CanvasSyncModel < ApplicationRecord
|
|
|
302
302
|
end
|
|
303
303
|
```
|
|
304
304
|
|
|
305
|
+
### AbilityHelper + JIT Sync
|
|
306
|
+
`CanvasSync` includes the `CanvasSync::Concerns::AbilityHelper` Concern. It provides helper methods to access `User` `Role`s and permissions, as well as to map LTI launch parameters to `CanvasSync`-synced records. (See the Concern for all available methods).
|
|
307
|
+
|
|
308
|
+
The built-in implementation assumes the use of `PandaPal` and our the CustomDev-typical launch_param naming:
|
|
309
|
+
- `custom_canvas_user_id`
|
|
310
|
+
- `custom_canvas_course_id`
|
|
311
|
+
- `custom_canvas_account_id`
|
|
312
|
+
|
|
313
|
+
Additionally, if and `_id` is present but the record can't be found, CanvasSync will attempt to perform Just-in-Time syncing via the Canvas API and `api_syncable`.
|
|
314
|
+
|
|
315
|
+
If you need to sync some extra data after the sync of the record itself (eg the Sections w/i a Course), a callback is provided:
|
|
316
|
+
```ruby
|
|
317
|
+
after_jit_sync do
|
|
318
|
+
sections_response = canvas_sync_client.course_sections(canvas_id)
|
|
319
|
+
Section.bulk_sync_from_api_result(sections_response)
|
|
320
|
+
end
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
`before_jit_sync` is provided as well, but it's use case in niche. It can `throw :jit_found, record` to abort the rest of the JIT process and instead return a specific record. Again, should be quite niche.
|
|
324
|
+
|
|
305
325
|
### Job Batching
|
|
306
326
|
CanvasSync adds a `CanvasSync::JobBatches` module. It adds Sidekiq/sidekiq-batch like support for Job Batches.
|
|
307
327
|
It integrates automatically with both Sidekiq and ActiveJob. The API is highly similar to the Sidekiq-batch implementation,
|
|
@@ -18,7 +18,17 @@ module CanvasSync::Concerns
|
|
|
18
18
|
|
|
19
19
|
# Middle Domain
|
|
20
20
|
|
|
21
|
+
def user
|
|
22
|
+
return @user if defined?(@user)
|
|
23
|
+
|
|
24
|
+
canvas_user_id = panda_pal_session.get_lti_cust_param('custom_canvas_user_id')
|
|
25
|
+
@user = load_canvas_model(::User, canvas_user_id) if canvas_user_id.present?
|
|
26
|
+
@user
|
|
27
|
+
end
|
|
28
|
+
|
|
21
29
|
def launch_context
|
|
30
|
+
return nil unless panda_pal_session.present?
|
|
31
|
+
|
|
22
32
|
@launch_context ||= begin
|
|
23
33
|
if panda_pal_session.lti_launch_placement == "global_navigation"
|
|
24
34
|
:global
|
|
@@ -46,9 +56,13 @@ module CanvasSync::Concerns
|
|
|
46
56
|
# CanvasSync Domain
|
|
47
57
|
|
|
48
58
|
def load_canvas_model(model, canvas_id)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
return nil unless model < CanvasSync::Record
|
|
60
|
+
|
|
61
|
+
if model.respond_to?(:find_or_jit_sync)
|
|
62
|
+
model.find_or_jit_sync(canvas_id)
|
|
63
|
+
else
|
|
64
|
+
model.find_by(canvas_id: canvas_id)
|
|
65
|
+
end
|
|
52
66
|
end
|
|
53
67
|
|
|
54
68
|
def canvas_permissions
|
|
@@ -30,7 +30,7 @@ module CanvasSync::Concerns
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def bulk_sync_from_api_result(api_array, conflict_target: :canvas_id, import_args: {}, all_pages: true, batch_size: 1000)
|
|
33
|
-
columns = api_sync_options[:field_map].keys
|
|
33
|
+
columns = api_sync_options[:field_map].keys + [:canvas_id]
|
|
34
34
|
|
|
35
35
|
update_conditions = {
|
|
36
36
|
condition: CanvasSync::Importers::BulkImporter.condition_sql(self, columns),
|
|
@@ -39,12 +39,12 @@ module CanvasSync::Concerns
|
|
|
39
39
|
update_conditions[:conflict_target] = conflict_target if conflict_target.present?
|
|
40
40
|
options = { validate: false, on_duplicate_key_update: update_conditions }.merge(import_args)
|
|
41
41
|
|
|
42
|
-
if all_pages
|
|
42
|
+
if all_pages && api_array.respond_to?(:all_pages_each)
|
|
43
43
|
enumer = api_array.all_pages_each.lazy
|
|
44
44
|
|
|
45
45
|
# Map the API response to instances of this model
|
|
46
46
|
enumer = enumer.map do |api_item|
|
|
47
|
-
new.assign_from_api_params(api_item)
|
|
47
|
+
new(canvas_id: api_item[:id]).assign_from_api_params(api_item)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
# Import in batches
|
|
@@ -53,9 +53,9 @@ module CanvasSync::Concerns
|
|
|
53
53
|
end
|
|
54
54
|
else
|
|
55
55
|
items = api_array.map do |api_item|
|
|
56
|
-
new.assign_from_api_params(api_item)
|
|
56
|
+
new(canvas_id: api_item[:id]).assign_from_api_params(api_item)
|
|
57
57
|
end
|
|
58
|
-
import(columns,
|
|
58
|
+
import(columns, items, options)
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module CanvasSync::Concerns
|
|
2
|
+
module JitSyncing
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
CanvasSync::Record.define_feature self, default: true
|
|
6
|
+
|
|
7
|
+
class_methods do
|
|
8
|
+
def find_or_jit_sync(canvas_id)
|
|
9
|
+
transaction do
|
|
10
|
+
rec = find_or_initialize_by(canvas_id: canvas_id)
|
|
11
|
+
return rec if rec.persisted?
|
|
12
|
+
|
|
13
|
+
catch :jit_found do
|
|
14
|
+
context = JitContext.new
|
|
15
|
+
rec.instance_variable_set(:@_canvas_sync_jit_context, context)
|
|
16
|
+
|
|
17
|
+
rec.run_callbacks(:jit_sync) do
|
|
18
|
+
api_response = rec.request_from_api(retries: 1)
|
|
19
|
+
context.instance_variable_set(:@api_response, api_response)
|
|
20
|
+
|
|
21
|
+
api_sync_race_create!(rec, save: true) do |inst2|
|
|
22
|
+
# Some other thread ended up creating the record before us, so assume that it handled
|
|
23
|
+
# everything beyond this point, including the after_jit_sync hooks
|
|
24
|
+
throw :jit_found, inst2 unless inst2 === rec
|
|
25
|
+
|
|
26
|
+
inst2.assign_from_api_params(api_response)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
ActiveSupport::Notifications.instrument("record_jit_sync.canvas_sync", {
|
|
30
|
+
record: rec,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
rec
|
|
34
|
+
end
|
|
35
|
+
ensure
|
|
36
|
+
rec.instance_variable_set(:@_canvas_sync_jit_context, nil)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
included do
|
|
43
|
+
define_model_callbacks :jit_sync
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
protected
|
|
47
|
+
|
|
48
|
+
def jit_context
|
|
49
|
+
@_canvas_sync_jit_context
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class JitContext
|
|
53
|
+
attr_reader :api_response
|
|
54
|
+
|
|
55
|
+
def initialize
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -36,8 +36,12 @@ class Course < ApplicationRecord
|
|
|
36
36
|
end_at: :end_at,
|
|
37
37
|
# If opting in the public_description, make sure to also add the 'include' array in the api call
|
|
38
38
|
# public_description: :public_description,
|
|
39
|
+
# }, -> (api) { api.course(canvas_id, { include: ['public_description'] }) })
|
|
39
40
|
}, -> (api) { api.course(canvas_id) })
|
|
40
|
-
|
|
41
|
+
|
|
42
|
+
# after_jit_sync do
|
|
43
|
+
# Section.bulk_sync_from_api_result(canvas_sync_client.course_sections(canvas_id))
|
|
44
|
+
# end
|
|
41
45
|
|
|
42
46
|
scope :active, -> { where(workflow_state: 'active') }
|
|
43
47
|
|
data/lib/canvas_sync/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: canvas_sync
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.26.0
|
|
4
|
+
version: 0.26.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Instructure CustomDev
|
|
@@ -450,6 +450,7 @@ files:
|
|
|
450
450
|
- lib/canvas_sync/concerns/api_syncable.rb
|
|
451
451
|
- lib/canvas_sync/concerns/canvas_id_as_primary.rb
|
|
452
452
|
- lib/canvas_sync/concerns/deleted_scoping.rb
|
|
453
|
+
- lib/canvas_sync/concerns/jit_syncing.rb
|
|
453
454
|
- lib/canvas_sync/concerns/legacy_columns.rb
|
|
454
455
|
- lib/canvas_sync/concerns/live_event_sync.rb
|
|
455
456
|
- lib/canvas_sync/concerns/role/base.rb
|