canvas_sync 0.22.6 → 0.22.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/canvas_sync/concerns/api_syncable.rb +9 -6
- data/lib/canvas_sync/concerns/sync_mapping.rb +11 -1
- data/lib/canvas_sync/generators/templates/migrations/create_enrollments.rb +1 -0
- data/lib/canvas_sync/importers/bulk_importer.rb +39 -69
- data/lib/canvas_sync/job.rb +0 -0
- data/lib/canvas_sync/job_batches/batch.rb +1 -1
- data/lib/canvas_sync/job_batches/chain_builder.rb +3 -24
- data/lib/canvas_sync/job_batches/jobs/managed_batch_job.rb +0 -4
- data/lib/canvas_sync/job_batches/status.rb +0 -1
- data/lib/canvas_sync/job_uniqueness/lock_context.rb +3 -15
- data/lib/canvas_sync/jobs/term_batches_job.rb +1 -4
- data/lib/canvas_sync/processors/model_mappings.yml +3 -0
- data/lib/canvas_sync/version.rb +1 -1
- data/spec/canvas_sync/canvas_sync_spec.rb +41 -59
- data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +4 -0
- data/spec/dummy/app/models/learning_outcome_result.rb +0 -0
- data/spec/dummy/app/models/rubric.rb +0 -0
- data/spec/dummy/app/models/rubric_assessment.rb +0 -0
- data/spec/dummy/app/models/rubric_association.rb +0 -0
- data/spec/dummy/app/models/user.rb +0 -0
- data/spec/dummy/db/migrate/20190702203624_create_enrollments.rb +1 -0
- data/spec/dummy/db/migrate/20240408223326_create_course_nicknames.rb +0 -0
- data/spec/dummy/db/migrate/20240509105100_create_rubrics.rb +0 -0
- data/spec/dummy/db/schema.rb +1 -0
- metadata +194 -209
- data/lib/canvas_sync/concerns/auto_relations.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0882011929080b4e55e1798ae3639c4431a583dd2a31634b2b9c2ba5f450fcb4'
|
4
|
+
data.tar.gz: 7a339eef193de9b640b3d68d5474a7771d363f7dee723be49da33cf319afe610
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a54b1779112dce3d106a503cc720b74d5b54ed2688c95c9d2c3523024813a0ac34d144417a8959bc81561dc4f78a7cf9914dd124037c85376a8a35b455bd5be1
|
7
|
+
data.tar.gz: 74e8b3e7d9317bbc2bbd7f902cfbedeabfd826ddbfd70aa4c8bf57c6f05dc2f4176f7bf2c0cc0352adae4ecaa4978f57f02fc3dcbbed8d1d8130df58bbaea51d
|
@@ -40,14 +40,17 @@ module CanvasSync::Concerns
|
|
40
40
|
options = { validate: false, on_duplicate_key_update: update_conditions }.merge(import_args)
|
41
41
|
|
42
42
|
if all_pages
|
43
|
-
|
44
|
-
|
43
|
+
enumer = api_array.all_pages_each.lazy
|
44
|
+
|
45
|
+
# Map the API response to instances of this model
|
46
|
+
enumer = enumer.map do |api_item|
|
47
|
+
new.assign_from_api_params(api_item)
|
45
48
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
+
|
50
|
+
# Import in batches
|
51
|
+
enumer.each_slice(batch_size) do |batch|
|
52
|
+
import(columns, batch, options)
|
49
53
|
end
|
50
|
-
batcher.flush
|
51
54
|
else
|
52
55
|
items = api_array.map do |api_item|
|
53
56
|
new.assign_from_api_params(api_item)
|
@@ -51,10 +51,11 @@ module CanvasSync::Concerns
|
|
51
51
|
m = maps[mname] = {}
|
52
52
|
|
53
53
|
m[:conflict_target] = Array(legacy[:conflict_target]).map(&:to_sym).map do |lct|
|
54
|
-
legacy[:report_columns][lct]
|
54
|
+
legacy[:report_columns]&.[](lct)&.[](:database_column_name)
|
55
55
|
end
|
56
56
|
|
57
57
|
m[:columns] = {}
|
58
|
+
|
58
59
|
legacy[:report_columns].each do |rcol, opts|
|
59
60
|
m[:columns][opts[:database_column_name]] = opts.except(:database_column_name).merge!(
|
60
61
|
report_column: rcol,
|
@@ -68,6 +69,15 @@ module CanvasSync::Concerns
|
|
68
69
|
def self.default_v1_mappings
|
69
70
|
@legacy_mappings ||= begin
|
70
71
|
mapping = YAML.load_file(File.join(__dir__, '../processors', "model_mappings.yml")).deep_symbolize_keys!
|
72
|
+
# Default columns can be excluded if the table has not been migrated to accept them
|
73
|
+
mapping.each do |mname, legacy|
|
74
|
+
legacy[:report_columns].select! do |rcol, opts|
|
75
|
+
model = mname.to_s&.classify&.safe_constantize
|
76
|
+
# we need to make sure this is a model otherwise they will be systematically removed - some mappings are not models (e.g xlists)
|
77
|
+
model.present? && !model.column_names.include?(opts[:database_column_name].to_s) ? false : true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
71
81
|
override_filepath = Rails.root.join("config/canvas_sync_provisioning_mapping.yml")
|
72
82
|
|
73
83
|
if File.file?(override_filepath)
|
@@ -23,7 +23,7 @@ module CanvasSync
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def self.perform_in_batches(report_file_path, raw_mapping, klass, conflict_target, import_args: {})
|
26
|
+
def self.perform_in_batches(report_file_path, raw_mapping, klass, conflict_target, import_args: {}, &block)
|
27
27
|
mapping = {}.with_indifferent_access
|
28
28
|
raw_mapping.each do |db_col, opts|
|
29
29
|
next if opts[:deprecated] && !klass.column_names.include?(db_col.to_s)
|
@@ -37,14 +37,27 @@ module CanvasSync
|
|
37
37
|
conflict_target = Array(conflict_target).map(&:to_s)
|
38
38
|
conflict_target_indices = conflict_target.map{|ct| database_column_names.index(ct) }
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
enumer = CSV.foreach(report_file_path, headers: true, header_converters: :symbol).lazy
|
41
|
+
|
42
|
+
# Optionally filter rows by a passed block
|
43
|
+
if block
|
44
|
+
enumer = enumer.filter_map do |row|
|
45
|
+
catch :skip do
|
46
|
+
block.call(row)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Optionally chunk by a computed value. Mainly so we can group duplicate rows and choose one
|
52
|
+
chunker = nil
|
53
|
+
chunker = UserChunker.new if defined?(User) && klass == User && csv_column_names.include?('user_id')
|
54
|
+
if chunker
|
55
|
+
enumer = enumer.chunk{|row| chunker.key(row) }.flat_map{|key, rows| chunker.choose(key, rows) }
|
44
56
|
end
|
45
57
|
|
46
|
-
|
47
|
-
|
58
|
+
# Prepare the rows for import
|
59
|
+
enumer = enumer.map do |row|
|
60
|
+
mapping.map do |db_col, col_def|
|
48
61
|
value = nil
|
49
62
|
value = row[col_def[:report_column]] if col_def[:report_column]
|
50
63
|
|
@@ -63,33 +76,25 @@ module CanvasSync
|
|
63
76
|
|
64
77
|
value
|
65
78
|
end
|
79
|
+
end
|
66
80
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
81
|
+
# Reject rows within a single batch that have the same ID
|
82
|
+
row_ids = nil
|
83
|
+
if conflict_target.present?
|
84
|
+
enumer = enumer.reject do |row|
|
85
|
+
key = conflict_target_indices.map{|ct| row[ct] }
|
86
|
+
skip = row_ids[key]
|
71
87
|
row_ids[key] = true
|
88
|
+
skip
|
72
89
|
end
|
73
|
-
|
74
|
-
batcher << formatted_row
|
75
|
-
}
|
76
|
-
|
77
|
-
row_buffer = nil
|
78
|
-
if defined?(User) && klass == User && csv_column_names.include?('user_id')
|
79
|
-
row_buffer = UserRowBuffer.new(&row_buffer_out)
|
80
|
-
else
|
81
|
-
row_buffer = NullRowBuffer.new(&row_buffer_out)
|
82
90
|
end
|
83
91
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
92
|
+
# Start importing
|
93
|
+
row_ids = {}
|
94
|
+
enumer.each_slice(batch_size) do |batch|
|
95
|
+
perform_import(klass, database_column_names, batch, conflict_target, import_args)
|
96
|
+
row_ids = {}
|
89
97
|
end
|
90
|
-
|
91
|
-
row_buffer.flush
|
92
|
-
batcher.flush
|
93
98
|
end
|
94
99
|
|
95
100
|
def self.perform_import(klass, columns, rows, conflict_target, import_args={})
|
@@ -157,52 +162,17 @@ module CanvasSync
|
|
157
162
|
batch_size > 0 ? batch_size : DEFAULT_BATCH_SIZE
|
158
163
|
end
|
159
164
|
|
160
|
-
class RowBuffer
|
161
|
-
def initialize(&block)
|
162
|
-
@flush_out = block
|
163
|
-
@buffered_rows = []
|
164
|
-
end
|
165
|
-
|
166
|
-
def <<(v)
|
167
|
-
@buffered_rows << v
|
168
|
-
end
|
169
|
-
|
170
|
-
def flush(value = @buffered_rows)
|
171
|
-
if value.is_a?(Array)
|
172
|
-
value.each do |v|
|
173
|
-
@flush_out.call(v)
|
174
|
-
end
|
175
|
-
else
|
176
|
-
@flush_out.call(value)
|
177
|
-
end
|
178
|
-
@buffered_rows = []
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
class NullRowBuffer
|
183
|
-
def initialize(&block)
|
184
|
-
@flush_out = block
|
185
|
-
end
|
186
|
-
|
187
|
-
def <<(v)
|
188
|
-
@flush_out.call(v)
|
189
|
-
end
|
190
|
-
|
191
|
-
def flush; end
|
192
|
-
end
|
193
|
-
|
194
165
|
# Ensures that, if a User has multiple rows, one with a SIS ID is preferred.
|
195
166
|
# This is mainly to fix issues in legacy apps - the suggested approach for new apps
|
196
167
|
# is to sync and use the Pseudonymes table
|
197
|
-
class
|
198
|
-
def
|
199
|
-
|
200
|
-
super
|
168
|
+
class UserChunker
|
169
|
+
def key(row)
|
170
|
+
row[:canvas_user_id]
|
201
171
|
end
|
202
172
|
|
203
|
-
def
|
204
|
-
row =
|
205
|
-
|
173
|
+
def choose(key, rows)
|
174
|
+
row = rows.find{|r| r[:user_id].present? } || rows.last
|
175
|
+
row.present? ? [row] : []
|
206
176
|
end
|
207
177
|
end
|
208
178
|
end
|
data/lib/canvas_sync/job.rb
CHANGED
File without changes
|
@@ -337,7 +337,7 @@ module CanvasSync::JobBatches
|
|
337
337
|
trigger_callback.call(:complete)
|
338
338
|
end
|
339
339
|
|
340
|
-
if all_successful # All
|
340
|
+
if all_successful # All Successful
|
341
341
|
trigger_callback.call(:success)
|
342
342
|
elsif pending_jobs == dead_jobs && pending_batches == stagnated_batches # Stagnated
|
343
343
|
trigger_callback.call(:stagnated)
|
@@ -4,9 +4,7 @@ module CanvasSync::JobBatches
|
|
4
4
|
|
5
5
|
attr_reader :base_job
|
6
6
|
|
7
|
-
def initialize(base_type = SerialBatchJob
|
8
|
-
@chain_id = chain_id || SecureRandom.urlsafe_base64(10)
|
9
|
-
|
7
|
+
def initialize(base_type = SerialBatchJob)
|
10
8
|
if base_type.is_a?(Hash)
|
11
9
|
@base_job = base_type
|
12
10
|
@base_job[:args] ||= @base_job[:parameters] || []
|
@@ -111,7 +109,7 @@ module CanvasSync::JobBatches
|
|
111
109
|
return nil if matching_jobs.count == 0
|
112
110
|
|
113
111
|
job = matching_jobs[0][0]
|
114
|
-
job = self.class.new(job
|
112
|
+
job = self.class.new(job) unless job.is_a?(ChainBuilder)
|
115
113
|
job
|
116
114
|
end
|
117
115
|
|
@@ -120,7 +118,6 @@ module CanvasSync::JobBatches
|
|
120
118
|
job_def.normalize!
|
121
119
|
else
|
122
120
|
job_def[:job] = job_def[:job].to_s
|
123
|
-
job_def[:chain_link] ||= "#{@chain_id}-#{SecureRandom.urlsafe_base64(10)}"
|
124
121
|
if (chain = self.class.get_chain_parameter(job_def, raise_error: false)).present?
|
125
122
|
chain.map! { |sub_job| normalize!(sub_job) }
|
126
123
|
end
|
@@ -141,7 +138,7 @@ module CanvasSync::JobBatches
|
|
141
138
|
args: args,
|
142
139
|
kwargs: kwargs,
|
143
140
|
}
|
144
|
-
self.class.new(hsh
|
141
|
+
self.class.new(hsh).apply_block(&blk) if blk.present?
|
145
142
|
hsh
|
146
143
|
end
|
147
144
|
|
@@ -242,24 +239,6 @@ module CanvasSync::JobBatches
|
|
242
239
|
job_class.perform_later(*job_args, **job_kwargs)
|
243
240
|
end
|
244
241
|
end
|
245
|
-
|
246
|
-
def link_to_batch!(chain_link, batch)
|
247
|
-
# Or make chains a separate entity - Chains show batches, but batches don't show chain?
|
248
|
-
# Or "Annotate" a Batch with chain data - could extract chain id from any job entry
|
249
|
-
end
|
250
|
-
|
251
|
-
def annotate_batch!(batch, chain)
|
252
|
-
|
253
|
-
end
|
254
|
-
|
255
|
-
def handle_step_complete(status, opts)
|
256
|
-
chain_link = opts[:chain_link]
|
257
|
-
chain_id, chain_step_id = chain_link.split('-')
|
258
|
-
|
259
|
-
CanvasSync::JobBatches::Batch.redis.multi do |r|
|
260
|
-
r.hset("CHAIN-#{chain_id}-steps", chain_step_id, "complete")
|
261
|
-
end
|
262
|
-
end
|
263
242
|
end
|
264
243
|
end
|
265
244
|
|
@@ -144,10 +144,6 @@ module CanvasSync::JobBatches
|
|
144
144
|
if next_job[:chain_link].present?
|
145
145
|
# Annotate Batch with chain-step info
|
146
146
|
batch.context["csb:chain_link"] = next_job[:chain_link]
|
147
|
-
# TODO Add Fiber Batch to chain-link
|
148
|
-
# With the exception of the top of the Chain, all nested ManagedBatch Roots should be within a Fiber,
|
149
|
-
# so we shouldn't really need to make the Root checkin with the chain
|
150
|
-
# ...except to cleanup the chain
|
151
147
|
batch.on(:complete, "#{ChainBuilder.to_s}.chain_step_complete", chain_link: next_job[:chain_link])
|
152
148
|
end
|
153
149
|
|
@@ -6,6 +6,8 @@ module CanvasSync::JobUniqueness
|
|
6
6
|
context_class.new(data, **kwargs)
|
7
7
|
end
|
8
8
|
|
9
|
+
attr_reader :lock_id
|
10
|
+
|
9
11
|
# { job_clazz, jid, queue, args?, kwargs?, base_key? }
|
10
12
|
def initialize(data, job_instance: nil, config: nil)
|
11
13
|
@base_key = data[:base_key]
|
@@ -14,9 +16,7 @@ module CanvasSync::JobUniqueness
|
|
14
16
|
@config = config || @context_data[:config]
|
15
17
|
|
16
18
|
# TODO Consider (somewhere) updating the lock_id to the BID of the wrapping Batch (when applicable)
|
17
|
-
@lock_id ||= data[:lid] || Thread.current[:unique_jobs_previous_context]&.lock_id
|
18
|
-
@lock_id_locked = @lock_id.present?
|
19
|
-
@lock_id ||= job_id
|
19
|
+
@lock_id ||= data[:lid] || Thread.current[:unique_jobs_previous_context]&.lock_id || job_id
|
20
20
|
end
|
21
21
|
|
22
22
|
# This is primarily for rehydrating in a Batch Callback, so it is unlikely that args and kwargs are needed.
|
@@ -84,18 +84,6 @@ module CanvasSync::JobUniqueness
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
-
def lock_id
|
88
|
-
@lock_id_locked = true
|
89
|
-
@lock_id
|
90
|
-
end
|
91
|
-
|
92
|
-
def lock_id=(new_id)
|
93
|
-
raise "Lock ID already set" if @lock_id_locked
|
94
|
-
return unless new_id.present?
|
95
|
-
@lock_id = new_id
|
96
|
-
@lock_id_locked = true
|
97
|
-
end
|
98
|
-
|
99
87
|
def job_id
|
100
88
|
@context_data[:jid]
|
101
89
|
end
|
@@ -12,17 +12,14 @@ module CanvasSync
|
|
12
12
|
# Override the delta-syncing date if:
|
13
13
|
# 1. the Term hasn't been synced before or
|
14
14
|
# 2. the Term underwent a period of not syncing
|
15
|
+
term_last_sync = CanvasSync.redis.get(self.class.last_sync_key(term_id))
|
15
16
|
if batch_context[:updated_after]
|
16
|
-
term_last_sync = CanvasSync.redis.get(self.class.last_sync_key(term_id))
|
17
17
|
if !term_last_sync.present? || batch_context[:updated_after] > term_last_sync
|
18
18
|
local_context[:updated_after] = term_last_sync.presence
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
JobBatches::ManagedBatchJob.make_batch(jobs, ordered: false, concurrency: true) do |b|
|
23
|
-
# TODO If we do a Chain UI, this will need to checkin somehow to indicate that the chain forked
|
24
|
-
# Or chain steps just show a summary - eg "Started", "X Jobs Running", "Done" or "X Jobs Running, Y Jobs Done" - and not individual forks
|
25
|
-
# For a step to be considered done, all previous sibling-level steps must be done and no batches pending
|
26
23
|
b.description = "TermBatchJob(#{term_id}) Root"
|
27
24
|
b.context = local_context
|
28
25
|
b.on(:success, "#{self.class.to_s}.batch_finished") unless options[:mark_synced] == false
|
data/lib/canvas_sync/version.rb
CHANGED
@@ -2,6 +2,18 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
RSpec.describe CanvasSync do
|
4
4
|
describe '.provisioning_sync' do
|
5
|
+
it 'invokes the first job in the queue and passes on the rest of the job chain' do
|
6
|
+
expected_job_chain = CanvasSync.default_provisioning_report_chain(['courses'], term_scope: nil).normalize![:args][0]
|
7
|
+
|
8
|
+
expect(CanvasSync::Jobs::BeginSyncChainJob).to receive(:perform_later)
|
9
|
+
.with(
|
10
|
+
expected_job_chain,
|
11
|
+
anything
|
12
|
+
)
|
13
|
+
|
14
|
+
CanvasSync.provisioning_sync(['courses'])
|
15
|
+
end
|
16
|
+
|
5
17
|
context 'an invalid model is passed in' do
|
6
18
|
it 'raises a helpful exception' do
|
7
19
|
expect {
|
@@ -18,25 +30,22 @@ RSpec.describe CanvasSync do
|
|
18
30
|
provisioning: { c: 3 },
|
19
31
|
global: { d: 4 },
|
20
32
|
})
|
21
|
-
expect(chain.normalize!).to
|
33
|
+
expect(chain.normalize!).to eq({
|
22
34
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
23
|
-
:chain_link=>String,
|
24
35
|
:args => [
|
25
36
|
[
|
26
37
|
{
|
27
38
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
28
|
-
:chain_link=>String,
|
29
39
|
:args=>[
|
30
40
|
[
|
31
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
41
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"], :b=>2}},
|
32
42
|
{
|
33
43
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
34
|
-
:chain_link=>String,
|
35
44
|
:args=>[],
|
36
45
|
:kwargs=>{
|
37
46
|
:term_scope=>"active",
|
38
47
|
:sub_jobs=>[
|
39
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
48
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"], :c=>3}},
|
40
49
|
],
|
41
50
|
},
|
42
51
|
},
|
@@ -53,23 +62,20 @@ RSpec.describe CanvasSync do
|
|
53
62
|
context 'we are syncing users with a term scope' do
|
54
63
|
it 'syncs the users in a separate job that runs first' do
|
55
64
|
chain = CanvasSync.default_provisioning_report_chain(['users', 'courses'], term_scope: :active)
|
56
|
-
expect(chain.normalize!).to
|
65
|
+
expect(chain.normalize!).to eq({
|
57
66
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
58
|
-
:chain_link=>String,
|
59
67
|
:args => [[
|
60
68
|
{
|
61
69
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
62
|
-
:chain_link=>String,
|
63
70
|
:args=>[
|
64
71
|
[
|
65
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
72
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users"]}},
|
66
73
|
{
|
67
74
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
68
|
-
:chain_link=>String,
|
69
75
|
:args=>[],
|
70
76
|
:kwargs=>{
|
71
77
|
:sub_jobs=>[
|
72
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
78
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}
|
73
79
|
],
|
74
80
|
:term_scope=>"active",
|
75
81
|
}
|
@@ -87,20 +93,17 @@ RSpec.describe CanvasSync do
|
|
87
93
|
context 'we are syncing users without a term scope' do
|
88
94
|
it 'syncs users along with the rest of the provisioning report' do
|
89
95
|
chain = CanvasSync.default_provisioning_report_chain(['users', 'courses'])
|
90
|
-
expect(chain.normalize!).to
|
96
|
+
expect(chain.normalize!).to eq({
|
91
97
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
92
|
-
:chain_link=>String,
|
93
98
|
:args => [[
|
94
99
|
{
|
95
100
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
96
|
-
:chain_link=>String,
|
97
101
|
:args=>[[
|
98
102
|
{
|
99
103
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
100
|
-
:chain_link=>String,
|
101
104
|
:args=>[],
|
102
105
|
:kwargs=>{
|
103
|
-
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
106
|
+
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "courses"]}}],
|
104
107
|
:term_scope=>nil,
|
105
108
|
}
|
106
109
|
}
|
@@ -116,21 +119,18 @@ RSpec.describe CanvasSync do
|
|
116
119
|
context 'we are syncing roles with a term scope' do
|
117
120
|
it 'syncs the roles in a separate job that runs first' do
|
118
121
|
chain = CanvasSync.default_provisioning_report_chain(['roles', 'courses'], term_scope: :active)
|
119
|
-
expect(chain.normalize!).to
|
122
|
+
expect(chain.normalize!).to eq({
|
120
123
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
121
|
-
:chain_link=>String,
|
122
124
|
:args => [[
|
123
125
|
{
|
124
126
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
125
|
-
:chain_link=>String,
|
126
127
|
:args=>[[
|
127
|
-
{:job=>"CanvasSync::Jobs::SyncRolesJob", :
|
128
|
+
{:job=>"CanvasSync::Jobs::SyncRolesJob", :options=>{}},
|
128
129
|
{
|
129
130
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
130
|
-
:chain_link=>String,
|
131
131
|
:args=>[],
|
132
132
|
:kwargs=>{
|
133
|
-
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
133
|
+
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}],
|
134
134
|
:term_scope=>"active",
|
135
135
|
}
|
136
136
|
},
|
@@ -146,21 +146,18 @@ RSpec.describe CanvasSync do
|
|
146
146
|
context 'we are syncing roles without a term scope' do
|
147
147
|
it 'syncs roles separately even with no term scope' do
|
148
148
|
chain = CanvasSync.default_provisioning_report_chain(['roles', 'courses'])
|
149
|
-
expect(chain.normalize!).to
|
149
|
+
expect(chain.normalize!).to eq({
|
150
150
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
151
|
-
:chain_link=>String,
|
152
151
|
:args => [[
|
153
152
|
{
|
154
153
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
155
|
-
:chain_link=>String,
|
156
154
|
:args=>[[
|
157
|
-
{:job=>"CanvasSync::Jobs::SyncRolesJob", :
|
155
|
+
{:job=>"CanvasSync::Jobs::SyncRolesJob", :options=>{}},
|
158
156
|
{
|
159
157
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
160
|
-
:chain_link=>String,
|
161
158
|
:args=>[],
|
162
159
|
:kwargs=>{
|
163
|
-
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
160
|
+
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}],
|
164
161
|
:term_scope=>nil,
|
165
162
|
}
|
166
163
|
}
|
@@ -176,21 +173,18 @@ RSpec.describe CanvasSync do
|
|
176
173
|
context 'we are syncing admins with a term scope' do
|
177
174
|
it 'syncs the admins in a separate job that runs first' do
|
178
175
|
chain = CanvasSync.default_provisioning_report_chain(['admins', 'courses'], term_scope: :active)
|
179
|
-
expect(chain.normalize!).to
|
176
|
+
expect(chain.normalize!).to eq({
|
180
177
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
181
|
-
:chain_link=>String,
|
182
178
|
:args => [[
|
183
179
|
{
|
184
180
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
185
|
-
:chain_link=>String,
|
186
181
|
:args=>[[
|
187
|
-
{:job=>"CanvasSync::Jobs::SyncAdminsJob", :
|
182
|
+
{:job=>"CanvasSync::Jobs::SyncAdminsJob", :options=>{}},
|
188
183
|
{
|
189
184
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
190
|
-
:chain_link=>String,
|
191
185
|
:args=>[],
|
192
186
|
:kwargs=>{
|
193
|
-
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
187
|
+
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}],
|
194
188
|
:term_scope=>"active"
|
195
189
|
}
|
196
190
|
}
|
@@ -206,21 +200,18 @@ RSpec.describe CanvasSync do
|
|
206
200
|
context 'we are syncing admins without a term scope' do
|
207
201
|
it 'syncs admins separately even with no term scope' do
|
208
202
|
chain = CanvasSync.default_provisioning_report_chain(['admins', 'courses'])
|
209
|
-
expect(chain.normalize!).to
|
203
|
+
expect(chain.normalize!).to eq({
|
210
204
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
211
|
-
:chain_link=>String,
|
212
205
|
:args => [[
|
213
206
|
{
|
214
207
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
215
|
-
:chain_link=>String,
|
216
208
|
:args=>[[
|
217
|
-
{:job=>"CanvasSync::Jobs::SyncAdminsJob", :
|
209
|
+
{:job=>"CanvasSync::Jobs::SyncAdminsJob", :options=>{}},
|
218
210
|
{
|
219
211
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
220
|
-
:chain_link=>String,
|
221
212
|
:args=>[],
|
222
213
|
:kwargs=>{
|
223
|
-
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
214
|
+
:sub_jobs=>[{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["courses"]}}],
|
224
215
|
:term_scope=>nil
|
225
216
|
}
|
226
217
|
}
|
@@ -237,22 +228,19 @@ RSpec.describe CanvasSync do
|
|
237
228
|
it "appends the SyncAssignmentsJob" do
|
238
229
|
chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments assignments])
|
239
230
|
|
240
|
-
expect(chain.normalize!).to
|
231
|
+
expect(chain.normalize!).to eq({
|
241
232
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
242
|
-
:chain_link=>String,
|
243
233
|
:args => [[
|
244
234
|
{
|
245
235
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
246
|
-
:chain_link=>String,
|
247
236
|
:args=>[[
|
248
237
|
{
|
249
238
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
250
|
-
:chain_link=>String,
|
251
239
|
:args=>[],
|
252
240
|
:kwargs=>{
|
253
241
|
:sub_jobs=>[
|
254
|
-
{:job=>"CanvasSync::Jobs::SyncAssignmentsJob", :
|
255
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
242
|
+
{:job=>"CanvasSync::Jobs::SyncAssignmentsJob", :options=>{}},
|
243
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "enrollments"]}}
|
256
244
|
],
|
257
245
|
:term_scope=>nil
|
258
246
|
}
|
@@ -270,22 +258,19 @@ RSpec.describe CanvasSync do
|
|
270
258
|
it "appends the SyncSubmissionsJob" do
|
271
259
|
chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments submissions])
|
272
260
|
|
273
|
-
expect(chain.normalize!).to
|
261
|
+
expect(chain.normalize!).to eq({
|
274
262
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
275
|
-
:chain_link=>String,
|
276
263
|
:args => [[
|
277
264
|
{
|
278
265
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
279
|
-
:chain_link=>String,
|
280
266
|
:args=>[[
|
281
267
|
{
|
282
268
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
283
|
-
:chain_link=>String,
|
284
269
|
:args=>[],
|
285
270
|
:kwargs=>{
|
286
271
|
:sub_jobs=>[
|
287
|
-
{:job=>"CanvasSync::Jobs::SyncSubmissionsJob", :
|
288
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
272
|
+
{:job=>"CanvasSync::Jobs::SyncSubmissionsJob", :options=>{}},
|
273
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "enrollments"]}}
|
289
274
|
],
|
290
275
|
:term_scope=>nil
|
291
276
|
}
|
@@ -303,22 +288,19 @@ RSpec.describe CanvasSync do
|
|
303
288
|
it "appends the SyncAssignmentGroupsJob" do
|
304
289
|
chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments assignment_groups])
|
305
290
|
|
306
|
-
expect(chain.normalize!).to
|
291
|
+
expect(chain.normalize!).to eq({
|
307
292
|
:job => "CanvasSync::Jobs::BeginSyncChainJob",
|
308
|
-
:chain_link=>String,
|
309
293
|
:args => [[
|
310
294
|
{
|
311
295
|
:job=>"CanvasSync::JobBatches::ConcurrentBatchJob",
|
312
|
-
:chain_link=>String,
|
313
296
|
:args=>[[
|
314
297
|
{
|
315
298
|
:job=>"CanvasSync::Jobs::SyncTermsJob",
|
316
|
-
:chain_link=>String,
|
317
299
|
:args=>[],
|
318
300
|
:kwargs=>{
|
319
301
|
:sub_jobs=>[
|
320
|
-
{:job=>"CanvasSync::Jobs::SyncAssignmentGroupsJob", :
|
321
|
-
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :
|
302
|
+
{:job=>"CanvasSync::Jobs::SyncAssignmentGroupsJob", :options=>{}},
|
303
|
+
{:job=>"CanvasSync::Jobs::SyncProvisioningReportJob", :options=>{:models=>["users", "enrollments"]}}
|
322
304
|
],
|
323
305
|
:term_scope=>nil
|
324
306
|
}
|
@@ -12,6 +12,10 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
|
|
12
12
|
|
13
13
|
context "with User#sis_id column" do
|
14
14
|
before do
|
15
|
+
# this could be refactored into a method that prevents caching the variables unless the environment is prod
|
16
|
+
CanvasSync::Concerns::SyncMapping::Mapping.instance_variable_set(:@mappings, nil)
|
17
|
+
CanvasSync::Concerns::SyncMapping::Mapping.instance_variable_set(:@legacy_mappings, nil)
|
18
|
+
|
15
19
|
self.use_transactional_tests = false
|
16
20
|
ActiveRecord::Migration.add_column :users, :sis_id, :string
|
17
21
|
User.reset_column_information
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -210,6 +210,7 @@ ActiveRecord::Schema.define(version: 2024_05_23_101010) do
|
|
210
210
|
t.bigint "canvas_section_id"
|
211
211
|
t.string "workflow_state"
|
212
212
|
t.string "base_role_type"
|
213
|
+
t.datetime "completed_at"
|
213
214
|
t.datetime "created_at", null: false
|
214
215
|
t.datetime "updated_at", null: false
|
215
216
|
t.index ["canvas_course_id"], name: "index_enrollments_on_canvas_course_id"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: canvas_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.22.
|
4
|
+
version: 0.22.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Instructure CustomDev
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 7.1.0
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 7.1.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -220,20 +220,6 @@ dependencies:
|
|
220
220
|
- - ">="
|
221
221
|
- !ruby/object:Gem::Version
|
222
222
|
version: '0'
|
223
|
-
- !ruby/object:Gem::Dependency
|
224
|
-
name: apartment
|
225
|
-
requirement: !ruby/object:Gem::Requirement
|
226
|
-
requirements:
|
227
|
-
- - ">="
|
228
|
-
- !ruby/object:Gem::Version
|
229
|
-
version: '0'
|
230
|
-
type: :development
|
231
|
-
prerelease: false
|
232
|
-
version_requirements: !ruby/object:Gem::Requirement
|
233
|
-
requirements:
|
234
|
-
- - ">="
|
235
|
-
- !ruby/object:Gem::Version
|
236
|
-
version: '0'
|
237
223
|
- !ruby/object:Gem::Dependency
|
238
224
|
name: with_model
|
239
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -266,14 +252,14 @@ dependencies:
|
|
266
252
|
name: sidekiq
|
267
253
|
requirement: !ruby/object:Gem::Requirement
|
268
254
|
requirements:
|
269
|
-
- - "
|
255
|
+
- - "~>"
|
270
256
|
- !ruby/object:Gem::Version
|
271
257
|
version: '7.0'
|
272
258
|
type: :development
|
273
259
|
prerelease: false
|
274
260
|
version_requirements: !ruby/object:Gem::Requirement
|
275
261
|
requirements:
|
276
|
-
- - "
|
262
|
+
- - "~>"
|
277
263
|
- !ruby/object:Gem::Version
|
278
264
|
version: '7.0'
|
279
265
|
- !ruby/object:Gem::Dependency
|
@@ -430,7 +416,7 @@ dependencies:
|
|
430
416
|
- - ">="
|
431
417
|
- !ruby/object:Gem::Version
|
432
418
|
version: '0'
|
433
|
-
description:
|
419
|
+
description:
|
434
420
|
email:
|
435
421
|
- pseng@instructure.com
|
436
422
|
executables: []
|
@@ -458,7 +444,6 @@ files:
|
|
458
444
|
- lib/canvas_sync/concerns/account/ancestry.rb
|
459
445
|
- lib/canvas_sync/concerns/account/base.rb
|
460
446
|
- lib/canvas_sync/concerns/api_syncable.rb
|
461
|
-
- lib/canvas_sync/concerns/auto_relations.rb
|
462
447
|
- lib/canvas_sync/concerns/legacy_columns.rb
|
463
448
|
- lib/canvas_sync/concerns/live_event_sync.rb
|
464
449
|
- lib/canvas_sync/concerns/role/base.rb
|
@@ -868,7 +853,7 @@ files:
|
|
868
853
|
homepage: https://instructure.com
|
869
854
|
licenses: []
|
870
855
|
metadata: {}
|
871
|
-
post_install_message:
|
856
|
+
post_install_message:
|
872
857
|
rdoc_options: []
|
873
858
|
require_paths:
|
874
859
|
- lib
|
@@ -883,241 +868,241 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
883
868
|
- !ruby/object:Gem::Version
|
884
869
|
version: '0'
|
885
870
|
requirements: []
|
886
|
-
rubygems_version: 3.
|
887
|
-
signing_key:
|
871
|
+
rubygems_version: 3.5.16
|
872
|
+
signing_key:
|
888
873
|
specification_version: 4
|
889
874
|
summary: Gem for generating Canvas models and migrations and syncing data from Canvas
|
890
875
|
test_files:
|
891
|
-
- spec/
|
876
|
+
- spec/canvas_sync/canvas_sync_spec.rb
|
877
|
+
- spec/canvas_sync/jobs/canvas_process_waiter_spec.rb
|
878
|
+
- spec/canvas_sync/jobs/job_spec.rb
|
879
|
+
- spec/canvas_sync/jobs/report_checker_spec.rb
|
880
|
+
- spec/canvas_sync/jobs/report_processor_job_spec.rb
|
881
|
+
- spec/canvas_sync/jobs/report_starter_spec.rb
|
882
|
+
- spec/canvas_sync/jobs/sync_admins_job_spec.rb
|
883
|
+
- spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb
|
884
|
+
- spec/canvas_sync/jobs/sync_assignments_job_spec.rb
|
885
|
+
- spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb
|
886
|
+
- spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb
|
887
|
+
- spec/canvas_sync/jobs/sync_context_modules_job_spec.rb
|
888
|
+
- spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb
|
889
|
+
- spec/canvas_sync/jobs/sync_roles_job_spec.rb
|
890
|
+
- spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
|
891
|
+
- spec/canvas_sync/jobs/sync_submissions_job_spec.rb
|
892
|
+
- spec/canvas_sync/jobs/sync_terms_job_spec.rb
|
893
|
+
- spec/canvas_sync/live_events/live_event_sync_spec.rb
|
894
|
+
- spec/canvas_sync/live_events/live_events_controller_spec.rb
|
895
|
+
- spec/canvas_sync/live_events/process_event_job_spec.rb
|
896
|
+
- spec/canvas_sync/misc_helper_spec.rb
|
897
|
+
- spec/canvas_sync/models/accounts_spec.rb
|
898
|
+
- spec/canvas_sync/models/admins_spec.rb
|
899
|
+
- spec/canvas_sync/models/assignment_group_spec.rb
|
900
|
+
- spec/canvas_sync/models/assignment_spec.rb
|
901
|
+
- spec/canvas_sync/models/context_module_item_spec.rb
|
902
|
+
- spec/canvas_sync/models/context_module_spec.rb
|
903
|
+
- spec/canvas_sync/models/course_spec.rb
|
904
|
+
- spec/canvas_sync/models/enrollment_spec.rb
|
905
|
+
- spec/canvas_sync/models/group_membership_spec.rb
|
906
|
+
- spec/canvas_sync/models/group_spec.rb
|
907
|
+
- spec/canvas_sync/models/roles_spec.rb
|
908
|
+
- spec/canvas_sync/models/section_spec.rb
|
909
|
+
- spec/canvas_sync/models/submission_spec.rb
|
910
|
+
- spec/canvas_sync/models/term_spec.rb
|
911
|
+
- spec/canvas_sync/models/user_spec.rb
|
912
|
+
- spec/canvas_sync/processors/assignment_groups_processor_spec.rb
|
913
|
+
- spec/canvas_sync/processors/assignments_processor_spec.rb
|
914
|
+
- spec/canvas_sync/processors/content_migrations_processor_spec.rb
|
915
|
+
- spec/canvas_sync/processors/context_module_items_processor_spec.rb
|
916
|
+
- spec/canvas_sync/processors/context_modules_processor_spec.rb
|
917
|
+
- spec/canvas_sync/processors/course_completion_report_processor_spec.rb
|
918
|
+
- spec/canvas_sync/processors/normal_processor_spec.rb
|
919
|
+
- spec/canvas_sync/processors/provisioning_report_processor_spec.rb
|
920
|
+
- spec/canvas_sync/processors/rubric_assessments_spec.rb
|
921
|
+
- spec/canvas_sync/processors/rubric_associations_spec.rb
|
922
|
+
- spec/canvas_sync/processors/rubrics_processor_spec.rb
|
923
|
+
- spec/canvas_sync/processors/submissions_processor_spec.rb
|
924
|
+
- spec/canvas_sync/services/module_event_spec.rb
|
925
|
+
- spec/canvas_sync/services/module_item_event_spec.rb
|
926
|
+
- spec/dummy/README.rdoc
|
927
|
+
- spec/dummy/Rakefile
|
928
|
+
- spec/dummy/app/models/account.rb
|
929
|
+
- spec/dummy/app/models/admin.rb
|
930
|
+
- spec/dummy/app/models/application_record.rb
|
931
|
+
- spec/dummy/app/models/assignment.rb
|
892
932
|
- spec/dummy/app/models/assignment_group.rb
|
893
|
-
- spec/dummy/app/models/
|
933
|
+
- spec/dummy/app/models/content_migration.rb
|
894
934
|
- spec/dummy/app/models/context_module.rb
|
895
|
-
- spec/dummy/app/models/
|
896
|
-
- spec/dummy/app/models/
|
897
|
-
- spec/dummy/app/models/
|
898
|
-
- spec/dummy/app/models/grading_period.rb
|
935
|
+
- spec/dummy/app/models/context_module_item.rb
|
936
|
+
- spec/dummy/app/models/course.rb
|
937
|
+
- spec/dummy/app/models/course_nickname.rb
|
899
938
|
- spec/dummy/app/models/course_progress.rb
|
900
|
-
- spec/dummy/app/models/rubric_association.rb
|
901
|
-
- spec/dummy/app/models/content_migration.rb
|
902
939
|
- spec/dummy/app/models/enrollment.rb
|
903
|
-
- spec/dummy/app/models/
|
940
|
+
- spec/dummy/app/models/grading_period.rb
|
941
|
+
- spec/dummy/app/models/grading_period_group.rb
|
904
942
|
- spec/dummy/app/models/group.rb
|
905
|
-
- spec/dummy/app/models/
|
906
|
-
- spec/dummy/app/models/admin.rb
|
907
|
-
- spec/dummy/app/models/course_nickname.rb
|
908
|
-
- spec/dummy/app/models/section.rb
|
943
|
+
- spec/dummy/app/models/group_membership.rb
|
909
944
|
- spec/dummy/app/models/learning_outcome.rb
|
945
|
+
- spec/dummy/app/models/learning_outcome_result.rb
|
946
|
+
- spec/dummy/app/models/pseudonym.rb
|
910
947
|
- spec/dummy/app/models/role.rb
|
911
|
-
- spec/dummy/app/models/grading_period_group.rb
|
912
|
-
- spec/dummy/app/models/term.rb
|
913
|
-
- spec/dummy/app/models/submission.rb
|
914
|
-
- spec/dummy/app/models/context_module_item.rb
|
915
|
-
- spec/dummy/app/models/rubric_assessment.rb
|
916
|
-
- spec/dummy/app/models/course.rb
|
917
|
-
- spec/dummy/app/models/application_record.rb
|
918
948
|
- spec/dummy/app/models/rubric.rb
|
949
|
+
- spec/dummy/app/models/rubric_assessment.rb
|
950
|
+
- spec/dummy/app/models/rubric_association.rb
|
951
|
+
- spec/dummy/app/models/section.rb
|
952
|
+
- spec/dummy/app/models/submission.rb
|
953
|
+
- spec/dummy/app/models/term.rb
|
919
954
|
- spec/dummy/app/models/user.rb
|
920
|
-
- spec/dummy/app/
|
921
|
-
- spec/dummy/app/services/live_events/
|
922
|
-
- spec/dummy/app/services/live_events/
|
923
|
-
- spec/dummy/app/services/live_events/
|
955
|
+
- spec/dummy/app/models/user_observer.rb
|
956
|
+
- spec/dummy/app/services/live_events/assignment_created_event.rb
|
957
|
+
- spec/dummy/app/services/live_events/assignment_event.rb
|
958
|
+
- spec/dummy/app/services/live_events/assignment_updated_event.rb
|
924
959
|
- spec/dummy/app/services/live_events/base_event.rb
|
925
|
-
- spec/dummy/app/services/live_events/grade_changed_event.rb
|
926
|
-
- spec/dummy/app/services/live_events/user_updated_event.rb
|
927
|
-
- spec/dummy/app/services/live_events/enrollment_event.rb
|
928
|
-
- spec/dummy/app/services/live_events/module_item_updated_event.rb
|
929
960
|
- spec/dummy/app/services/live_events/course_created_event.rb
|
930
|
-
- spec/dummy/app/services/live_events/syllabus_updated_event.rb
|
931
961
|
- spec/dummy/app/services/live_events/course_event.rb
|
932
|
-
- spec/dummy/app/services/live_events/user_event.rb
|
933
|
-
- spec/dummy/app/services/live_events/user_created_event.rb
|
934
|
-
- spec/dummy/app/services/live_events/course_updated_event.rb
|
935
|
-
- spec/dummy/app/services/live_events/module_item_created_event.rb
|
936
962
|
- spec/dummy/app/services/live_events/course_section_created_event.rb
|
937
|
-
- spec/dummy/app/services/live_events/syllabus_event.rb
|
938
|
-
- spec/dummy/app/services/live_events/submission_updated_event.rb
|
939
963
|
- spec/dummy/app/services/live_events/course_section_event.rb
|
940
|
-
- spec/dummy/app/services/live_events/
|
964
|
+
- spec/dummy/app/services/live_events/course_section_updated_event.rb
|
965
|
+
- spec/dummy/app/services/live_events/course_updated_event.rb
|
941
966
|
- spec/dummy/app/services/live_events/enrollment_created_event.rb
|
942
|
-
- spec/dummy/app/services/live_events/
|
943
|
-
- spec/dummy/app/services/live_events/assignment_event.rb
|
944
|
-
- spec/dummy/app/services/live_events/module_event.rb
|
967
|
+
- spec/dummy/app/services/live_events/enrollment_event.rb
|
945
968
|
- spec/dummy/app/services/live_events/enrollment_updated_event.rb
|
946
|
-
- spec/dummy/app/services/live_events/
|
947
|
-
- spec/dummy/app/services/live_events/
|
969
|
+
- spec/dummy/app/services/live_events/grade_changed_event.rb
|
970
|
+
- spec/dummy/app/services/live_events/grade_event.rb
|
948
971
|
- spec/dummy/app/services/live_events/module_created_event.rb
|
972
|
+
- spec/dummy/app/services/live_events/module_event.rb
|
973
|
+
- spec/dummy/app/services/live_events/module_item_created_event.rb
|
974
|
+
- spec/dummy/app/services/live_events/module_item_event.rb
|
975
|
+
- spec/dummy/app/services/live_events/module_item_updated_event.rb
|
976
|
+
- spec/dummy/app/services/live_events/module_updated_event.rb
|
977
|
+
- spec/dummy/app/services/live_events/submission_created_event.rb
|
978
|
+
- spec/dummy/app/services/live_events/submission_event.rb
|
979
|
+
- spec/dummy/app/services/live_events/submission_updated_event.rb
|
980
|
+
- spec/dummy/app/services/live_events/syllabus_event.rb
|
981
|
+
- spec/dummy/app/services/live_events/syllabus_updated_event.rb
|
982
|
+
- spec/dummy/app/services/live_events/user_created_event.rb
|
983
|
+
- spec/dummy/app/services/live_events/user_event.rb
|
984
|
+
- spec/dummy/app/services/live_events/user_updated_event.rb
|
949
985
|
- spec/dummy/bin/rails
|
950
|
-
- spec/dummy/config/secrets.yml
|
951
|
-
- spec/dummy/config/routes.rb
|
952
|
-
- spec/dummy/config/environments/development.rb
|
953
|
-
- spec/dummy/config/environments/test.rb
|
954
|
-
- spec/dummy/config/environment.rb
|
955
986
|
- spec/dummy/config/application.rb
|
956
|
-
- spec/dummy/config/database.yml
|
957
987
|
- spec/dummy/config/boot.rb
|
988
|
+
- spec/dummy/config/database.yml
|
989
|
+
- spec/dummy/config/environment.rb
|
990
|
+
- spec/dummy/config/environments/development.rb
|
991
|
+
- spec/dummy/config/environments/test.rb
|
992
|
+
- spec/dummy/config/initializers/assets.rb
|
958
993
|
- spec/dummy/config/initializers/session_store.rb
|
959
994
|
- spec/dummy/config/initializers/wrap_parameters.rb
|
960
|
-
- spec/dummy/config/
|
995
|
+
- spec/dummy/config/routes.rb
|
996
|
+
- spec/dummy/config/secrets.yml
|
961
997
|
- spec/dummy/config.ru
|
962
|
-
- spec/dummy/
|
963
|
-
- spec/dummy/db/
|
964
|
-
- spec/dummy/db/migrate/
|
965
|
-
- spec/dummy/db/migrate/20190702203627_create_submissions.rb
|
998
|
+
- spec/dummy/db/migrate/20190702203621_create_courses.rb
|
999
|
+
- spec/dummy/db/migrate/20190702203622_create_accounts.rb
|
1000
|
+
- spec/dummy/db/migrate/20190702203623_create_terms.rb
|
966
1001
|
- spec/dummy/db/migrate/20190702203624_create_enrollments.rb
|
1002
|
+
- spec/dummy/db/migrate/20190702203625_create_sections.rb
|
1003
|
+
- spec/dummy/db/migrate/20190702203626_create_assignments.rb
|
1004
|
+
- spec/dummy/db/migrate/20190702203627_create_submissions.rb
|
967
1005
|
- spec/dummy/db/migrate/20190702203630_create_assignment_groups.rb
|
968
|
-
- spec/dummy/db/migrate/
|
1006
|
+
- spec/dummy/db/migrate/20190702203631_create_context_modules.rb
|
969
1007
|
- spec/dummy/db/migrate/20190702203632_create_context_module_items.rb
|
970
|
-
- spec/dummy/db/migrate/
|
971
|
-
- spec/dummy/db/migrate/
|
1008
|
+
- spec/dummy/db/migrate/20190927204545_create_roles.rb
|
1009
|
+
- spec/dummy/db/migrate/20190927204546_create_admins.rb
|
1010
|
+
- spec/dummy/db/migrate/20200415171620_create_groups.rb
|
1011
|
+
- spec/dummy/db/migrate/20200416214248_create_group_memberships.rb
|
1012
|
+
- spec/dummy/db/migrate/20201016181346_create_pseudonyms.rb
|
972
1013
|
- spec/dummy/db/migrate/20210907233329_create_user_observers.rb
|
973
|
-
- spec/dummy/db/migrate/20220712210559_create_learning_outcomes.rb
|
974
1014
|
- spec/dummy/db/migrate/20210907233330_create_grading_periods.rb
|
975
|
-
- spec/dummy/db/migrate/
|
976
|
-
- spec/dummy/db/migrate/20240523101010_create_learning_outcome_results.rb
|
977
|
-
- spec/dummy/db/migrate/20240510094100_create_rubric_associations.rb
|
1015
|
+
- spec/dummy/db/migrate/20211001184920_create_grading_period_groups.rb
|
978
1016
|
- spec/dummy/db/migrate/20220308072643_create_content_migrations.rb
|
979
|
-
- spec/dummy/db/migrate/
|
980
|
-
- spec/dummy/db/migrate/20190927204546_create_admins.rb
|
981
|
-
- spec/dummy/db/migrate/20190702203623_create_terms.rb
|
982
|
-
- spec/dummy/db/migrate/20190927204545_create_roles.rb
|
1017
|
+
- spec/dummy/db/migrate/20220712210559_create_learning_outcomes.rb
|
983
1018
|
- spec/dummy/db/migrate/20220926221926_create_users.rb
|
984
|
-
- spec/dummy/db/migrate/
|
985
|
-
- spec/dummy/db/migrate/
|
986
|
-
- spec/dummy/db/migrate/
|
1019
|
+
- spec/dummy/db/migrate/20240408223326_create_course_nicknames.rb
|
1020
|
+
- spec/dummy/db/migrate/20240509105100_create_rubrics.rb
|
1021
|
+
- spec/dummy/db/migrate/20240510094100_create_rubric_associations.rb
|
987
1022
|
- spec/dummy/db/migrate/20240510101100_create_rubric_assessments.rb
|
988
|
-
- spec/dummy/db/migrate/
|
989
|
-
- spec/dummy/db/migrate/
|
990
|
-
- spec/dummy/db/
|
991
|
-
- spec/
|
992
|
-
- spec/
|
993
|
-
- spec/
|
994
|
-
- spec/
|
995
|
-
- spec/
|
996
|
-
- spec/
|
997
|
-
- spec/
|
998
|
-
- spec/
|
999
|
-
- spec/
|
1000
|
-
- spec/
|
1001
|
-
- spec/
|
1002
|
-
- spec/
|
1003
|
-
- spec/
|
1004
|
-
- spec/
|
1005
|
-
- spec/
|
1006
|
-
- spec/canvas_sync/models/course_spec.rb
|
1007
|
-
- spec/canvas_sync/misc_helper_spec.rb
|
1008
|
-
- spec/canvas_sync/processors/context_module_items_processor_spec.rb
|
1009
|
-
- spec/canvas_sync/processors/context_modules_processor_spec.rb
|
1010
|
-
- spec/canvas_sync/processors/rubric_assessments_spec.rb
|
1011
|
-
- spec/canvas_sync/processors/rubric_associations_spec.rb
|
1012
|
-
- spec/canvas_sync/processors/normal_processor_spec.rb
|
1013
|
-
- spec/canvas_sync/processors/provisioning_report_processor_spec.rb
|
1014
|
-
- spec/canvas_sync/processors/course_completion_report_processor_spec.rb
|
1015
|
-
- spec/canvas_sync/processors/content_migrations_processor_spec.rb
|
1016
|
-
- spec/canvas_sync/processors/submissions_processor_spec.rb
|
1017
|
-
- spec/canvas_sync/processors/assignments_processor_spec.rb
|
1018
|
-
- spec/canvas_sync/processors/rubrics_processor_spec.rb
|
1019
|
-
- spec/canvas_sync/processors/assignment_groups_processor_spec.rb
|
1020
|
-
- spec/canvas_sync/jobs/report_checker_spec.rb
|
1021
|
-
- spec/canvas_sync/jobs/canvas_process_waiter_spec.rb
|
1022
|
-
- spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
|
1023
|
-
- spec/canvas_sync/jobs/job_spec.rb
|
1024
|
-
- spec/canvas_sync/jobs/sync_context_modules_job_spec.rb
|
1025
|
-
- spec/canvas_sync/jobs/report_starter_spec.rb
|
1026
|
-
- spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb
|
1027
|
-
- spec/canvas_sync/jobs/sync_assignments_job_spec.rb
|
1028
|
-
- spec/canvas_sync/jobs/sync_submissions_job_spec.rb
|
1029
|
-
- spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb
|
1030
|
-
- spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb
|
1031
|
-
- spec/canvas_sync/jobs/sync_admins_job_spec.rb
|
1032
|
-
- spec/canvas_sync/jobs/sync_roles_job_spec.rb
|
1033
|
-
- spec/canvas_sync/jobs/sync_terms_job_spec.rb
|
1034
|
-
- spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb
|
1035
|
-
- spec/canvas_sync/jobs/report_processor_job_spec.rb
|
1036
|
-
- spec/canvas_sync/canvas_sync_spec.rb
|
1037
|
-
- spec/canvas_sync/services/module_item_event_spec.rb
|
1038
|
-
- spec/canvas_sync/services/module_event_spec.rb
|
1039
|
-
- spec/canvas_sync/live_events/live_event_sync_spec.rb
|
1040
|
-
- spec/canvas_sync/live_events/live_events_controller_spec.rb
|
1041
|
-
- spec/canvas_sync/live_events/process_event_job_spec.rb
|
1042
|
-
- spec/job_uniqueness/spec_helper.rb
|
1043
|
-
- spec/job_uniqueness/lock_context_spec.rb
|
1044
|
-
- spec/job_uniqueness/on_conflict_spec.rb
|
1045
|
-
- spec/job_uniqueness/compat/sidekiq_spec.rb
|
1046
|
-
- spec/job_uniqueness/compat/active_job_spec.rb
|
1047
|
-
- spec/job_uniqueness/on_conflict/reschedule_spec.rb
|
1048
|
-
- spec/job_uniqueness/on_conflict/raise_spec.rb
|
1049
|
-
- spec/job_uniqueness/on_conflict/log_spec.rb
|
1050
|
-
- spec/job_uniqueness/unique_job_common_spec.rb
|
1051
|
-
- spec/job_uniqueness/support/test_worker.rb
|
1052
|
-
- spec/job_uniqueness/support/lock_strategy.rb
|
1053
|
-
- spec/job_uniqueness/support/on_conflict.rb
|
1054
|
-
- spec/job_uniqueness/strategy/until_executed_spec.rb
|
1055
|
-
- spec/job_uniqueness/strategy/until_and_while_executing_spec.rb
|
1056
|
-
- spec/job_uniqueness/strategy/until_executing_spec.rb
|
1057
|
-
- spec/job_uniqueness/strategy/until_expired_spec.rb
|
1058
|
-
- spec/job_uniqueness/strategy/while_executing_spec.rb
|
1059
|
-
- spec/job_uniqueness/strategy/base_spec.rb
|
1023
|
+
- spec/dummy/db/migrate/20240523101010_create_learning_outcome_results.rb
|
1024
|
+
- spec/dummy/db/migrate/20240828161300_create_course_progresses.rb
|
1025
|
+
- spec/dummy/db/schema.rb
|
1026
|
+
- spec/factories/account_factory.rb
|
1027
|
+
- spec/factories/admin_factory.rb
|
1028
|
+
- spec/factories/assignment_factory.rb
|
1029
|
+
- spec/factories/assignment_group_factory.rb
|
1030
|
+
- spec/factories/context_module_factory.rb
|
1031
|
+
- spec/factories/context_module_item_factory.rb
|
1032
|
+
- spec/factories/course_factory.rb
|
1033
|
+
- spec/factories/enrollment_factory.rb
|
1034
|
+
- spec/factories/group_factory.rb
|
1035
|
+
- spec/factories/group_membership_factory.rb
|
1036
|
+
- spec/factories/role_factory.rb
|
1037
|
+
- spec/factories/section_factory.rb
|
1038
|
+
- spec/factories/submission_factory.rb
|
1039
|
+
- spec/factories/term_factory.rb
|
1040
|
+
- spec/factories/user_factory.rb
|
1060
1041
|
- spec/job_batching/batch_spec.rb
|
1061
|
-
- spec/job_batching/
|
1062
|
-
- spec/job_batching/context_hash_spec.rb
|
1063
|
-
- spec/job_batching/compat/sidekiq_spec.rb
|
1042
|
+
- spec/job_batching/callback_spec.rb
|
1064
1043
|
- spec/job_batching/compat/active_job_spec.rb
|
1044
|
+
- spec/job_batching/compat/sidekiq_spec.rb
|
1045
|
+
- spec/job_batching/context_hash_spec.rb
|
1046
|
+
- spec/job_batching/flow_spec.rb
|
1047
|
+
- spec/job_batching/integration/fail_then_succeed.rb
|
1048
|
+
- spec/job_batching/integration/integration.rb
|
1065
1049
|
- spec/job_batching/integration/nested.rb
|
1066
|
-
- spec/job_batching/integration/workflow.rb
|
1067
1050
|
- spec/job_batching/integration/simple.rb
|
1068
|
-
- spec/job_batching/integration/
|
1069
|
-
- spec/job_batching/integration/fail_then_succeed.rb
|
1051
|
+
- spec/job_batching/integration/workflow.rb
|
1070
1052
|
- spec/job_batching/integration_helper.rb
|
1071
|
-
- spec/job_batching/
|
1053
|
+
- spec/job_batching/pool_spec.rb
|
1072
1054
|
- spec/job_batching/status_spec.rb
|
1073
1055
|
- spec/job_batching/support/base_job.rb
|
1074
1056
|
- spec/job_batching/support/sample_callback.rb
|
1075
|
-
- spec/
|
1057
|
+
- spec/job_uniqueness/compat/active_job_spec.rb
|
1058
|
+
- spec/job_uniqueness/compat/sidekiq_spec.rb
|
1059
|
+
- spec/job_uniqueness/lock_context_spec.rb
|
1060
|
+
- spec/job_uniqueness/on_conflict/log_spec.rb
|
1061
|
+
- spec/job_uniqueness/on_conflict/raise_spec.rb
|
1062
|
+
- spec/job_uniqueness/on_conflict/reschedule_spec.rb
|
1063
|
+
- spec/job_uniqueness/on_conflict_spec.rb
|
1064
|
+
- spec/job_uniqueness/spec_helper.rb
|
1065
|
+
- spec/job_uniqueness/strategy/base_spec.rb
|
1066
|
+
- spec/job_uniqueness/strategy/until_and_while_executing_spec.rb
|
1067
|
+
- spec/job_uniqueness/strategy/until_executed_spec.rb
|
1068
|
+
- spec/job_uniqueness/strategy/until_executing_spec.rb
|
1069
|
+
- spec/job_uniqueness/strategy/until_expired_spec.rb
|
1070
|
+
- spec/job_uniqueness/strategy/while_executing_spec.rb
|
1071
|
+
- spec/job_uniqueness/support/lock_strategy.rb
|
1072
|
+
- spec/job_uniqueness/support/on_conflict.rb
|
1073
|
+
- spec/job_uniqueness/support/test_worker.rb
|
1074
|
+
- spec/job_uniqueness/unique_job_common_spec.rb
|
1075
|
+
- spec/spec_helper.rb
|
1076
1076
|
- spec/support/fake_canvas.rb
|
1077
|
-
- spec/support/fixtures/canvas_responses/roles.json
|
1078
1077
|
- spec/support/fixtures/canvas_responses/admins.json
|
1078
|
+
- spec/support/fixtures/canvas_responses/module.json
|
1079
1079
|
- spec/support/fixtures/canvas_responses/module_item.json
|
1080
|
+
- spec/support/fixtures/canvas_responses/roles.json
|
1080
1081
|
- spec/support/fixtures/canvas_responses/terms.json
|
1081
|
-
- spec/support/fixtures/
|
1082
|
-
- spec/support/fixtures/reports/
|
1083
|
-
- spec/support/fixtures/reports/
|
1084
|
-
- spec/support/fixtures/reports/learning_outcomes.csv
|
1082
|
+
- spec/support/fixtures/reports/assignment_groups.csv
|
1083
|
+
- spec/support/fixtures/reports/assignments.csv
|
1084
|
+
- spec/support/fixtures/reports/content_migrations.csv
|
1085
1085
|
- spec/support/fixtures/reports/context_module_items.csv
|
1086
1086
|
- spec/support/fixtures/reports/context_modules.csv
|
1087
|
-
- spec/support/fixtures/reports/group_memberships.csv
|
1088
|
-
- spec/support/fixtures/reports/content_migrations.csv
|
1089
|
-
- spec/support/fixtures/reports/users.csv
|
1090
|
-
- spec/support/fixtures/reports/submissions.csv
|
1091
|
-
- spec/support/fixtures/reports/course_progresses_conflict.csv
|
1092
1087
|
- spec/support/fixtures/reports/course_nicknames.csv
|
1088
|
+
- spec/support/fixtures/reports/course_progresses.csv
|
1089
|
+
- spec/support/fixtures/reports/course_progresses_conflict.csv
|
1090
|
+
- spec/support/fixtures/reports/courses.csv
|
1093
1091
|
- spec/support/fixtures/reports/enrollments.csv
|
1094
|
-
- spec/support/fixtures/reports/
|
1095
|
-
- spec/support/fixtures/reports/assignments.csv
|
1092
|
+
- spec/support/fixtures/reports/grading_period_groups.csv
|
1096
1093
|
- spec/support/fixtures/reports/grading_periods.csv
|
1097
|
-
- spec/support/fixtures/reports/
|
1098
|
-
- spec/support/fixtures/reports/
|
1099
|
-
- spec/support/fixtures/reports/
|
1094
|
+
- spec/support/fixtures/reports/group_memberships.csv
|
1095
|
+
- spec/support/fixtures/reports/groups.csv
|
1096
|
+
- spec/support/fixtures/reports/learning_outcome_results.csv
|
1097
|
+
- spec/support/fixtures/reports/learning_outcomes.csv
|
1100
1098
|
- spec/support/fixtures/reports/provisioning_csv
|
1101
|
-
- spec/support/fixtures/reports/user_observers.csv
|
1102
|
-
- spec/support/fixtures/reports/rubrics.csv
|
1103
|
-
- spec/support/fixtures/reports/assignment_groups.csv
|
1104
|
-
- spec/support/fixtures/reports/course_progresses.csv
|
1105
|
-
- spec/support/fixtures/reports/rubric_assessments.csv
|
1106
|
-
- spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
|
1107
1099
|
- spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
|
1108
|
-
- spec/support/fixtures/reports/
|
1109
|
-
- spec/
|
1110
|
-
- spec/
|
1111
|
-
- spec/
|
1112
|
-
- spec/
|
1113
|
-
- spec/
|
1114
|
-
- spec/
|
1115
|
-
- spec/
|
1116
|
-
- spec/
|
1117
|
-
- spec/factories/section_factory.rb
|
1118
|
-
- spec/factories/enrollment_factory.rb
|
1119
|
-
- spec/factories/context_module_factory.rb
|
1120
|
-
- spec/factories/context_module_item_factory.rb
|
1121
|
-
- spec/factories/submission_factory.rb
|
1122
|
-
- spec/factories/assignment_group_factory.rb
|
1123
|
-
- spec/factories/account_factory.rb
|
1100
|
+
- spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
|
1101
|
+
- spec/support/fixtures/reports/rubric_assessments.csv
|
1102
|
+
- spec/support/fixtures/reports/rubric_associations.csv
|
1103
|
+
- spec/support/fixtures/reports/rubrics.csv
|
1104
|
+
- spec/support/fixtures/reports/sections.csv
|
1105
|
+
- spec/support/fixtures/reports/submissions.csv
|
1106
|
+
- spec/support/fixtures/reports/user_observers.csv
|
1107
|
+
- spec/support/fixtures/reports/users.csv
|
1108
|
+
- spec/support/fixtures/reports/xlist.csv
|