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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 913868034039ed594b3f1808512d6346887d1a0a5935fe13d250ea2a9a109df5
4
- data.tar.gz: e6fc6a923d7f298926312ece015a94df39c9a543954e4c38197eaf7abdadfbd3
3
+ metadata.gz: de18757d9f34a2b87abf23c01b530ec430c9b062076807fdfc0a7998275f32fd
4
+ data.tar.gz: 23d760b8d2321535b13f54bd180127da73b850208b9fe8c290c3df104c8bd87c
5
5
  SHA512:
6
- metadata.gz: 2616055d4f7fad53ff118b9f5ec0cb1948f316e8f8c9a40df8cbea780c4992aa1c6d7545c4149e46f5aec230e892227b543b664407f044a799e66deb248aea75
7
- data.tar.gz: cb9ec962cda4fc4561c98fa96c4443e8bd745156c28ff99c5d45ddebc4e6e82582d551c649cc90c6b11c333e11f522d9da40d9bf5cc38afa72217609285448ea
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
- record = model.find_or_fetch(canvas_id, save: true) if model.respond_to?(:find_or_fetch)
50
- record ||= model.find_by(canvas_id: canvas_id)
51
- record
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, batch, options)
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
- # }, -> (api) { api.course(canvas_id, { include: ['public_description'] }) })
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
 
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.26.0.beta2".freeze
2
+ VERSION = "0.26.0".freeze
3
3
  end
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.beta2
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