canvas_sync 0.22.3 → 0.22.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/canvas_sync/generators/templates/migrations/create_context_modules.rb +2 -0
  3. data/lib/canvas_sync/generators/templates/migrations/create_course_progresses.rb +20 -0
  4. data/lib/canvas_sync/generators/templates/models/context_module.rb +36 -2
  5. data/lib/canvas_sync/generators/templates/models/context_module_item.rb +11 -3
  6. data/lib/canvas_sync/generators/templates/models/course_progress.rb +14 -0
  7. data/lib/canvas_sync/importers/bulk_importer.rb +3 -0
  8. data/lib/canvas_sync/job_batches/batch.rb +18 -22
  9. data/lib/canvas_sync/job_uniqueness/lock_context.rb +4 -26
  10. data/lib/canvas_sync/jobs/sync_course_progresses_job.rb +21 -0
  11. data/lib/canvas_sync/processors/course_completion_report_processor.rb +20 -0
  12. data/lib/canvas_sync/processors/model_mappings.yml +27 -0
  13. data/lib/canvas_sync/version.rb +1 -1
  14. data/lib/canvas_sync.rb +4 -0
  15. data/spec/canvas_sync/processors/context_modules_processor_spec.rb +14 -0
  16. data/spec/canvas_sync/processors/course_completion_report_processor_spec.rb +47 -0
  17. data/spec/dummy/app/models/context_module.rb +36 -2
  18. data/spec/dummy/app/models/context_module_item.rb +11 -3
  19. data/spec/dummy/app/models/course_progress.rb +20 -0
  20. data/spec/dummy/db/migrate/20190702203631_create_context_modules.rb +2 -0
  21. data/spec/dummy/db/migrate/20240828161300_create_course_progresses.rb +26 -0
  22. data/spec/dummy/db/schema.rb +15 -0
  23. data/spec/job_uniqueness/lock_context_spec.rb +0 -11
  24. data/spec/support/fixtures/reports/context_modules.csv +3 -3
  25. data/spec/support/fixtures/reports/course_progresses.csv +3 -0
  26. data/spec/support/fixtures/reports/course_progresses_conflict.csv +2 -0
  27. metadata +210 -197
  28. 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: cc62b25843e2b3e57b83e1ca41b4a0e546666ce6e824a8a799f534ee90fb28c5
4
- data.tar.gz: 1fb1747c3882282894b0aa4e6fef9d7240977a453da6415e3a31460c55833306
3
+ metadata.gz: b588205886b2732d915af7bd8a4e41fed60dae2593ca824c8fa046410258d6f3
4
+ data.tar.gz: 9f6a3238ae187f6a9a01135957ef8f769e127fc2870103c1bb7acacae57973ba
5
5
  SHA512:
6
- metadata.gz: 3ac70536bc476c02ee262487ff7074493e99c05d585cec78a32cddb5569feb9e5ca6407a7104cf7538ed9030e4cb2401be823171de5f5e261de5bd2aeafbc11f
7
- data.tar.gz: 31178103ff1168d6a54b622c612260857c4f5841dff32c637a95877a1df3f7c4467221e05c19e7688f1ebf3284d79cc8cf5113208f89ac4299983dcaa2ccf51d
6
+ metadata.gz: 9bbd02c072cd7f3eadce5f342b40eaa3f15f3a33843a0f93c20ff4afff0f401ae80532eddf99edd236027876bae20b0977cb0f5c10ddab57fb9d89f76c609efb
7
+ data.tar.gz: fa5845858716a91706e6b08877234635fced66701db9d6fc0e0c8956e3e1bb73e862cf7f69da062ba1823cd7cd8c1d23b66c97f20f51239523eaa8d59adcd9b8
@@ -11,6 +11,8 @@ class CreateContextModules < ActiveRecord::Migration[5.1]
11
11
  t.string :workflow_state
12
12
  t.datetime :deleted_at
13
13
  t.datetime :unlock_at
14
+ t.text :completion_requirements
15
+ t.text :prerequisites
14
16
  t.timestamps
15
17
  end
16
18
 
@@ -0,0 +1,20 @@
1
+ # <%= autogenerated_migration_warning %>
2
+
3
+ class CreateCourseProgresses < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :course_progresses do |t|
6
+ t.bigint :canvas_course_id, null: false
7
+ t.bigint :canvas_user_id, null: false
8
+ t.integer :requirement_count
9
+ t.integer :requirement_completed_count
10
+ t.datetime :completion_date
11
+
12
+ t.timestamps
13
+ end
14
+
15
+ add_index :course_progresses, :canvas_user_id
16
+ add_index :course_progresses, :canvas_course_id
17
+ add_index :course_progresses, [:canvas_user_id, :canvas_course_id], unique: true
18
+ end
19
+ end
20
+
@@ -14,8 +14,42 @@ class ContextModule < ApplicationRecord
14
14
  has_many :context_module_items, primary_key: :canvas_id, foreign_key: :canvas_context_module_id
15
15
  has_many :assignments, through: :context_module_items
16
16
 
17
+ serialize :completion_requirements
18
+ serialize :prerequisites
19
+
17
20
  api_syncable({
18
- # TODO If your tool Syncs ContextModules, please complete this and merge it into CanvasSync
19
- }, -> (api) { api.course_module(canvas_context_id, canvas_id) })
21
+ canvas_id: :id,
22
+ canvas_context_id: :context_id,
23
+ canvas_context_type: :context_type,
24
+ position: :position,
25
+ name: :name,
26
+ workflow_state: :workflow_state,
27
+ unlock_at: :unlock_at,
28
+ completion_requirements: :completion_requirements,
29
+ prerequisites: :prerequisites,
30
+ requirement_count: :requirement_count
31
+ }, lambda { |api|
32
+ course_modules = api.course_modules(canvas_context_id, { include: ['items'] }) # avoids having 2 API calls for modules as we reuse this data
33
+ context_module = course_modules&.detect { |course_module| course_module['id'] == canvas_id }
34
+
35
+ if context_module.nil? # no context_module here means it is deleted in Canvas
36
+ self.workflow_state = :deleted
37
+ return self
38
+ end
39
+
40
+ # The ContextModule model in Canvas has the 'completion_requirements' and 'prerequisites' fields that are not returned directly from the API
41
+ # We need to compute them here based on data that we receive from course_modules in the API
42
+ context_module['prerequisites'] = course_modules.map do |course_module|
43
+ next unless context_module['prerequisite_module_ids']&.include?(course_module['id'])
44
+
45
+ {
46
+ id: course_module['id'],
47
+ name: course_module['name'],
48
+ type: 'context_module'
49
+ }.with_indifferent_access
50
+ end.compact
20
51
 
52
+ context_module['completion_requirements'] = context_module['items']&.map { |item| item['completion_requirement'] }&.compact
53
+ context_module
54
+ })
21
55
  end
@@ -12,7 +12,15 @@ class ContextModuleItem < ApplicationRecord
12
12
  belongs_to :assignment, foreign_key: :canvas_assignment_id, primary_key: :canvas_id
13
13
 
14
14
  api_syncable({
15
- # TODO If your tool Syncs ContextModuleItems, please complete this and merge it into CanvasSync
16
- }, -> (api) { api.module_item(context_module.context.canvas_id, context_module.canvas_id, canvas_id) })
17
-
15
+ canvas_id: :id,
16
+ canvas_context_module_id: :module_id,
17
+ position: :position,
18
+ canvas_content_type: :type,
19
+ canvas_content_id: :content_id,
20
+ canvas_assignment_id: :assignment_id
21
+ }, lambda { |api|
22
+ module_item = api.module_item(context_module.context.canvas_id, context_module.canvas_id, canvas_id)
23
+ module_item['assignment_id'] = api.assignment(context_module.context.canvas_id, module_item['content_id'])['id'] if module_item['type'] == 'Assignment'
24
+ module_item
25
+ })
18
26
  end
@@ -0,0 +1,14 @@
1
+ # <%= autogenerated_model_warning %>
2
+
3
+ # CourseProgress is not a Canvas model. It is a table built from the Custom Report
4
+ class CourseProgress < ApplicationRecord
5
+ include CanvasSync::Record
6
+
7
+ canvas_sync_features :defaults
8
+
9
+ belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id, optional: true
10
+ belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
11
+
12
+ validates_presence_of :canvas_user_id, :canvas_course_id
13
+ validates_uniqueness_of :canvas_user_id, scope: :canvas_course_id
14
+ end
@@ -53,6 +53,9 @@ module CanvasSync
53
53
  # TODO: add some timezone config to the mapping.
54
54
  # In cases where the timestamp or date doesn't include a timezone, you should be able to specify one
55
55
  value = DateTime.parse(value).utc rescue nil # rubocop:disable Style/RescueModifier
56
+ elsif col_def[:type].to_sym == :yaml
57
+ # CSV parse from reading the report escapes the new lines and YAML throws an error with double backslashes
58
+ value = YAML.load(value.gsub("\\n", "\n")) rescue nil # rubocop:disable Style/RescueModifier
56
59
  end
57
60
  end
58
61
 
@@ -478,22 +478,20 @@ module CanvasSync::JobBatches
478
478
 
479
479
  # Internal method to cleanup a Redis Hash and related keys
480
480
  def cleanup_redis_index_for(key, suffixes = [""])
481
- redis do |r|
482
- if r.hget(k, "created_at").present?
483
- r.multi do |r|
484
- suffixes.each do |suffix|
485
- r.expire(key + suffix, BID_EXPIRE_TTL)
486
- end
481
+ if r.hget(k, "created_at").present?
482
+ r.multi do |r|
483
+ suffixes.each do |suffix|
484
+ r.expire(key + suffix, BID_EXPIRE_TTL)
487
485
  end
488
- false
489
- else
490
- r.multi do |r|
491
- suffixes.each do |suffix|
492
- r.unlink(key + suffix)
493
- end
486
+ end
487
+ false
488
+ else
489
+ r.multi do |r|
490
+ suffixes.each do |suffix|
491
+ r.unlink(key + suffix)
494
492
  end
495
- true
496
493
  end
494
+ true
497
495
  end
498
496
  end
499
497
 
@@ -501,16 +499,14 @@ module CanvasSync::JobBatches
501
499
  def cleanup_redis_index!
502
500
  suffixes = ["", "-callbacks-complete", "-callbacks-success", "-failed", "-dead", "-batches-success", "-batches-complete", "-batches-failed", "-bids", "-jids", "-pending_callbacks"]
503
501
 
504
- redis do |r|
505
- cleanup_index = ->(index) {
506
- r.zrangebyscore(index, "0", BID_EXPIRE_TTL.seconds.ago.to_i).each do |bid|
507
- r.zrem(index, bid) if cleanup_redis_index_for("BID-#{bid}", suffixes)
508
- end
509
- }
502
+ cleanup_index = ->(index) {
503
+ r.zrangebyscore(index, "0", BID_EXPIRE_TTL.seconds.ago.to_i).each do |bid|
504
+ r.zrem(index, bid) if cleanup_redis_index_for("BID-#{bid}", suffixes)
505
+ end
506
+ }
510
507
 
511
- cleanup_index.("BID-ROOT-bids")
512
- cleanup_index.("batches")
513
- end
508
+ cleanup_index.call("BID-ROOT-bids")
509
+ cleanup_index.call("batches")
514
510
  end
515
511
 
516
512
  def redis(&blk)
@@ -122,27 +122,14 @@ module CanvasSync::JobUniqueness
122
122
 
123
123
  args = @context_data[:args] || []
124
124
  kwargs = @context_data[:kwargs] || {}
125
- hash = config[:hash]
126
125
  if config[:hash].is_a?(Proc)
127
- hash = config[:hash].call(*args, **kwargs)
126
+ base_key << config[:hash].call(*args, **kwargs)
128
127
  elsif config[:hash].nil?
129
- hash = [*args, kwargs]
130
- end
131
-
132
- hash = ":#{hash}" if hash.is_a?(Symbol)
133
-
134
- if hash && !hash.is_a?(String)
135
- hash = Array(hash)
136
-
137
- # Normalize the hash to ensure that the order of any Hash keys don't matter
138
- hash = normalize_hash_chunk(hash)
139
-
140
- normalized = ActiveJob::Arguments.serialize(hash)
141
- hash = OpenSSL::Digest::MD5.hexdigest(JSON.dump(normalized))
128
+ base_key << OpenSSL::Digest::MD5.hexdigest(JSON.dump([ args, kwargs.sort]))
129
+ else
130
+ base_key << config[:hash]
142
131
  end
143
132
 
144
- base_key << hash if hash
145
-
146
133
  base_key.join(":")
147
134
  end
148
135
  end
@@ -186,14 +173,5 @@ module CanvasSync::JobUniqueness
186
173
 
187
174
  private
188
175
 
189
- def normalize_hash_chunk(chunk)
190
- if chunk.is_a?(Hash)
191
- chunk.map { |k, v| [k, normalize_hash_chunk(v)] }.sort.to_h
192
- elsif chunk.is_a?(Array)
193
- chunk.map { |c| normalize_hash_chunk(c) }
194
- else
195
- chunk
196
- end
197
- end
198
176
  end
199
177
  end
@@ -0,0 +1,21 @@
1
+ module CanvasSync
2
+ module Jobs
3
+ class SyncCourseProgressesJob < ReportStarter
4
+ # Syncs CourseProgresses
5
+ #
6
+ # Starts a report processor for the course completion report
7
+ # (the proserv_course_completion_csv report must be enabled)
8
+ #
9
+ # @param options [Hash]
10
+ def perform(options)
11
+ super(
12
+ 'proserv_course_completion_csv',
13
+ merge_report_params(options),
14
+ CanvasSync::Processors::CourseCompletionReportProcessor.to_s,
15
+ {},
16
+ )
17
+ end
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,20 @@
1
+ require_relative "./report_processor"
2
+
3
+ module CanvasSync
4
+ module Processors
5
+ # Processes a course completion report using the bulk importer.
6
+ #
7
+ # @param report_file_path [String]
8
+ # @param options [Hash]
9
+ class CourseCompletionReportProcessor < ReportProcessor
10
+ def self.process(report_file_path, _options, report_id)
11
+ new(report_file_path, _options)
12
+ end
13
+
14
+ def initialize(report_file_path, options)
15
+ do_bulk_import(report_file_path, CourseProgress, options: options)
16
+ end
17
+ end
18
+ end
19
+ end
20
+
@@ -105,6 +105,27 @@ courses:
105
105
  database_column_name: grading_standard_id
106
106
  type: integer
107
107
 
108
+ course_progresses:
109
+ conflict_target:
110
+ - student_id
111
+ - course_id
112
+ report_columns:
113
+ student_id:
114
+ database_column_name: canvas_user_id
115
+ type: integer
116
+ course_id:
117
+ database_column_name: canvas_course_id
118
+ type: integer
119
+ requirement_count:
120
+ database_column_name: requirement_count
121
+ type: integer
122
+ requirement_completed_count:
123
+ database_column_name: requirement_completed_count
124
+ type: integer
125
+ completion_date:
126
+ database_column_name: completion_date
127
+ type: datetime
128
+
108
129
  enrollments:
109
130
  conflict_target: canvas_enrollment_id
110
131
  report_columns:
@@ -324,6 +345,12 @@ context_modules:
324
345
  deleted_at:
325
346
  database_column_name: deleted_at
326
347
  type: datetime
348
+ completion_requirements:
349
+ database_column_name: completion_requirements
350
+ type: yaml
351
+ prerequisites:
352
+ database_column_name: prerequisites
353
+ type: yaml
327
354
 
328
355
  context_module_items:
329
356
  conflict_target: canvas_context_module_item_id
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.22.3".freeze
2
+ VERSION = "0.22.4".freeze
3
3
  end
data/lib/canvas_sync.rb CHANGED
@@ -53,6 +53,7 @@ module CanvasSync
53
53
  rubrics
54
54
  rubric_associations
55
55
  rubric_assessments
56
+ course_progresses
56
57
  ].freeze
57
58
 
58
59
  SUPPORTED_TERM_SCOPE_MODELS = %w[
@@ -64,6 +65,7 @@ module CanvasSync
64
65
  rubrics
65
66
  rubric_associations
66
67
  rubric_assessments
68
+ course_progresses
67
69
  ].freeze
68
70
 
69
71
  DEFAULT_TERM_SCOPE_MODELS = %w[
@@ -75,6 +77,7 @@ module CanvasSync
75
77
  rubrics
76
78
  rubric_associations
77
79
  rubric_assessments
80
+ course_progresses
78
81
  ].freeze
79
82
 
80
83
  SUPPORTED_LIVE_EVENTS = %w[
@@ -166,6 +169,7 @@ module CanvasSync
166
169
  context_modules: CanvasSync::Jobs::SyncContextModulesJob,
167
170
  context_module_items: CanvasSync::Jobs::SyncContextModuleItemsJob,
168
171
  content_migrations: CanvasSync::Jobs::SyncContentMigrationsJob,
172
+ course_progresses: CanvasSync::Jobs::SyncCourseProgressesJob,
169
173
  rubrics: CanvasSync::Jobs::SyncRubricsJob,
170
174
  rubric_associations: CanvasSync::Jobs::SyncRubricAssociationsJob,
171
175
  rubric_assessments: CanvasSync::Jobs::SyncRubricAssessmentsJob,
@@ -8,6 +8,20 @@ RSpec.describe CanvasSync::Processors::ContextModulesProcessor do
8
8
  expect {
9
9
  subject.process("spec/support/fixtures/reports/context_modules.csv", {}, 1)
10
10
  }.to change { ContextModule.count }.by(2)
11
+ expect(ContextModule.first).to have_attributes(
12
+ canvas_id: 23,
13
+ canvas_context_id: 785,
14
+ canvas_context_type: 'Course',
15
+ name: 'New Mod',
16
+ position: 1,
17
+ workflow_state: 'active',
18
+ completion_requirements: [],
19
+ prerequisites: []
20
+ )
21
+ # Check for properly serialized YAML
22
+ expect(ContextModule.last.completion_requirements).to eq([
23
+ { id: 1, type: 'must_view' }
24
+ ])
11
25
  end
12
26
  end
13
27
  end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe CanvasSync::Processors::CourseCompletionReportProcessor do
4
+
5
+ describe '#process' do
6
+ it 'inserts course progresses' do
7
+ expect {
8
+ described_class.process('spec/support/fixtures/reports/course_progresses.csv', {}, 1)
9
+ }.to change { CourseProgress.count }.by(2)
10
+ cp = CourseProgress.first
11
+ expect(cp).to have_attributes(
12
+ canvas_user_id: 1,
13
+ canvas_course_id: 1,
14
+ requirement_count: 0,
15
+ requirement_completed_count: 0,
16
+ )
17
+ expect(cp.completion_date.strftime('%Y-%m-%d %H:%M:%S')).to eq('2024-05-01 09:00:00')
18
+ expect(CourseProgress.last).to have_attributes(
19
+ canvas_user_id: 2,
20
+ canvas_course_id: 2,
21
+ requirement_count: 1,
22
+ requirement_completed_count: 1,
23
+ completion_date: nil
24
+ )
25
+ end
26
+
27
+ context 'record already present in the database' do
28
+ before do
29
+ described_class.process('spec/support/fixtures/reports/course_progresses.csv', {}, 1)
30
+ end
31
+
32
+ it 'updates the course progress' do
33
+ expect {
34
+ described_class.process('spec/support/fixtures/reports/course_progresses_conflict.csv', {}, 1)
35
+ }.to change { CourseProgress.count }.by(0)
36
+ cp = CourseProgress.first
37
+ expect(cp).to have_attributes(
38
+ canvas_user_id: 1,
39
+ canvas_course_id: 1,
40
+ requirement_count: 10,
41
+ requirement_completed_count: 10,
42
+ )
43
+ expect(cp.completion_date.strftime('%Y-%m-%d %H:%M:%S')).to eq('2028-05-01 09:00:00')
44
+ end
45
+ end
46
+ end
47
+ end
@@ -20,8 +20,42 @@ class ContextModule < ApplicationRecord
20
20
  has_many :context_module_items, primary_key: :canvas_id, foreign_key: :canvas_context_module_id
21
21
  has_many :assignments, through: :context_module_items
22
22
 
23
+ serialize :completion_requirements
24
+ serialize :prerequisites
25
+
23
26
  api_syncable({
24
- # TODO If your tool Syncs ContextModules, please complete this and merge it into CanvasSync
25
- }, -> (api) { api.course_module(canvas_context_id, canvas_id) })
27
+ canvas_id: :id,
28
+ canvas_context_id: :context_id,
29
+ canvas_context_type: :context_type,
30
+ position: :position,
31
+ name: :name,
32
+ workflow_state: :workflow_state,
33
+ unlock_at: :unlock_at,
34
+ completion_requirements: :completion_requirements,
35
+ prerequisites: :prerequisites,
36
+ requirement_count: :requirement_count
37
+ }, lambda { |api|
38
+ course_modules = api.course_modules(canvas_context_id, { include: ['items'] }) # avoids having 2 API calls for modules as we reuse this data
39
+ context_module = course_modules&.detect { |course_module| course_module['id'] == canvas_id }
40
+
41
+ if context_module.nil? # no context_module here means it is deleted in Canvas
42
+ self.workflow_state = :deleted
43
+ return self
44
+ end
45
+
46
+ # The ContextModule model in Canvas has the 'completion_requirements' and 'prerequisites' fields that are not returned directly from the API
47
+ # We need to compute them here based on data that we receive from course_modules in the API
48
+ context_module['prerequisites'] = course_modules.map do |course_module|
49
+ next unless context_module['prerequisite_module_ids']&.include?(course_module['id'])
50
+
51
+ {
52
+ id: course_module['id'],
53
+ name: course_module['name'],
54
+ type: 'context_module'
55
+ }.with_indifferent_access
56
+ end.compact
26
57
 
58
+ context_module['completion_requirements'] = context_module['items']&.map { |item| item['completion_requirement'] }&.compact
59
+ context_module
60
+ })
27
61
  end
@@ -18,7 +18,15 @@ class ContextModuleItem < ApplicationRecord
18
18
  belongs_to :assignment, foreign_key: :canvas_assignment_id, primary_key: :canvas_id
19
19
 
20
20
  api_syncable({
21
- # TODO If your tool Syncs ContextModuleItems, please complete this and merge it into CanvasSync
22
- }, -> (api) { api.module_item(context_module.context.canvas_id, context_module.canvas_id, canvas_id) })
23
-
21
+ canvas_id: :id,
22
+ canvas_context_module_id: :module_id,
23
+ position: :position,
24
+ canvas_content_type: :type,
25
+ canvas_content_id: :content_id,
26
+ canvas_assignment_id: :assignment_id
27
+ }, lambda { |api|
28
+ module_item = api.module_item(context_module.context.canvas_id, context_module.canvas_id, canvas_id)
29
+ module_item['assignment_id'] = api.assignment(context_module.context.canvas_id, module_item['content_id'])['id'] if module_item['type'] == 'Assignment'
30
+ module_item
31
+ })
24
32
  end
@@ -0,0 +1,20 @@
1
+ # #
2
+ # AUTO GENERATED MODEL
3
+ # This model was auto generated by the CanvasSync Gem.
4
+ # You can customize it as needed, but make sure you test
5
+ # any changes you make to the auto generated methods.
6
+ #
7
+
8
+
9
+ # CourseProgress is not a Canvas model. It is a table built from the Custom Report
10
+ class CourseProgress < ApplicationRecord
11
+ include CanvasSync::Record
12
+
13
+ canvas_sync_features :defaults
14
+
15
+ belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id, optional: true
16
+ belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
17
+
18
+ validates_presence_of :canvas_user_id, :canvas_course_id
19
+ validates_uniqueness_of :canvas_user_id, scope: :canvas_course_id
20
+ end
@@ -17,6 +17,8 @@ class CreateContextModules < ActiveRecord::Migration[5.1]
17
17
  t.string :workflow_state
18
18
  t.datetime :deleted_at
19
19
  t.datetime :unlock_at
20
+ t.text :completion_requirements
21
+ t.text :prerequisites
20
22
  t.timestamps
21
23
  end
22
24
 
@@ -0,0 +1,26 @@
1
+ # #
2
+ # AUTO GENERATED MIGRATION
3
+ # This migration was auto generated by the CanvasSync Gem.
4
+ # You can add new columns to this table, but removing or
5
+ # re-naming ones created here may break Canvas Syncing.
6
+ #
7
+
8
+
9
+ class CreateCourseProgresses < ActiveRecord::Migration[5.1]
10
+ def change
11
+ create_table :course_progresses do |t|
12
+ t.bigint :canvas_course_id, null: false
13
+ t.bigint :canvas_user_id, null: false
14
+ t.integer :requirement_count
15
+ t.integer :requirement_completed_count
16
+ t.datetime :completion_date
17
+
18
+ t.timestamps
19
+ end
20
+
21
+ add_index :course_progresses, :canvas_user_id
22
+ add_index :course_progresses, :canvas_course_id
23
+ add_index :course_progresses, [:canvas_user_id, :canvas_course_id], unique: true
24
+ end
25
+ end
26
+
@@ -153,6 +153,8 @@ ActiveRecord::Schema.define(version: 2024_05_23_101010) do
153
153
  t.datetime "unlock_at"
154
154
  t.datetime "created_at", null: false
155
155
  t.datetime "updated_at", null: false
156
+ t.text "completion_requirements"
157
+ t.text "prerequisites"
156
158
  t.index ["canvas_context_id", "canvas_context_type"], name: "index_context_modules_on_context"
157
159
  t.index ["canvas_id"], name: "index_context_modules_on_canvas_id", unique: true
158
160
  end
@@ -168,6 +170,19 @@ ActiveRecord::Schema.define(version: 2024_05_23_101010) do
168
170
  t.index ["canvas_user_preference_value_id"], name: "index_course_nicknames_on_canvas_user_preference_value_id", unique: true
169
171
  end
170
172
 
173
+ create_table "course_progresses", force: :cascade do |t|
174
+ t.bigint "canvas_course_id", null: false
175
+ t.bigint "canvas_user_id", null: false
176
+ t.integer "requirement_count"
177
+ t.integer "requirement_completed_count"
178
+ t.datetime "completion_date"
179
+ t.datetime "created_at", null: false
180
+ t.datetime "updated_at", null: false
181
+ t.index ["canvas_user_id"], name: "index_course_progresses_on_canvas_user_id"
182
+ t.index ["canvas_course_id"], name: "index_course_progresses_on_canvas_course_id"
183
+ t.index ["canvas_user_id", "canvas_course_id"], name: "index_course_progresses_on_canvas_user_id_and_canvas_course_id", unique: true
184
+ end
185
+
171
186
  create_table "courses", force: :cascade do |t|
172
187
  t.bigint "canvas_id", null: false
173
188
  t.string "sis_id"
@@ -24,17 +24,6 @@ RSpec.describe CanvasSync::JobUniqueness::LockContext do
24
24
  TestWorker.unique_job_options[:scope] = scope
25
25
  end
26
26
 
27
- it 'returns matching keys for equal hashes' do
28
- context_data[:args] = [{ foo: 'bar', bar: 'foo' }]
29
- key1 = lock_context.base_key
30
- lock_context.instance_variable_set(:@base_key, nil)
31
-
32
- context_data[:args] = [{ bar: 'foo', foo: 'bar' }]
33
- key2 = lock_context.base_key
34
-
35
- expect(key1).to eq key2
36
- end
37
-
38
27
  context 'when scope is a Proc' do
39
28
  let(:scope) { ->(queue:) { "blob" } }
40
29
 
@@ -1,3 +1,3 @@
1
- canvas_context_module_id,canvas_context_id,canvas_context_type,name,position,workflow_state,deleted_at,unlock_at,migration_id,require_sequential_progress,requirement_count
2
- 23,785,Course,New Mod,1,active,,,,false,
3
- 4,27,Course,Modules gonna module,1,unpublished,,,,false,
1
+ canvas_context_module_id,canvas_context_id,canvas_context_type,name,position,workflow_state,deleted_at,unlock_at,migration_id,require_sequential_progress,requirement_count,completion_requirements,prerequisites
2
+ 23,785,Course,New Mod,1,active,,,,false,,--- [],--- []
3
+ 4,27,Course,Modules gonna module,1,unpublished,,,,false,2,"---\n- :id: 1\n :type: must_view","---\n- :id: 1\n :type: context_module\n :name: 'Unit 1: Introduction'"
@@ -0,0 +1,3 @@
1
+ student_id,course_id,requirement_count,requirement_completed_count,completion_date
2
+ 1,1,0,0,"2024-05-01 09:00:00"
3
+ 2,2,1,1,""
@@ -0,0 +1,2 @@
1
+ student_id,course_id,requirement_count,requirement_completed_count,completion_date
2
+ 1,1,10,10,"2028-05-01 09:00:00"
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.3
4
+ version: 0.22.4
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-08-28 00:00:00.000000000 Z
11
+ date: 2024-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -430,7 +430,7 @@ dependencies:
430
430
  - - ">="
431
431
  - !ruby/object:Gem::Version
432
432
  version: '0'
433
- description:
433
+ description:
434
434
  email:
435
435
  - pseng@instructure.com
436
436
  executables: []
@@ -458,7 +458,6 @@ files:
458
458
  - lib/canvas_sync/concerns/account/ancestry.rb
459
459
  - lib/canvas_sync/concerns/account/base.rb
460
460
  - lib/canvas_sync/concerns/api_syncable.rb
461
- - lib/canvas_sync/concerns/auto_relations.rb
462
461
  - lib/canvas_sync/concerns/legacy_columns.rb
463
462
  - lib/canvas_sync/concerns/live_event_sync.rb
464
463
  - lib/canvas_sync/concerns/role/base.rb
@@ -475,6 +474,7 @@ files:
475
474
  - lib/canvas_sync/generators/templates/migrations/create_context_module_items.rb
476
475
  - lib/canvas_sync/generators/templates/migrations/create_context_modules.rb
477
476
  - lib/canvas_sync/generators/templates/migrations/create_course_nicknames.rb
477
+ - lib/canvas_sync/generators/templates/migrations/create_course_progresses.rb
478
478
  - lib/canvas_sync/generators/templates/migrations/create_courses.rb
479
479
  - lib/canvas_sync/generators/templates/migrations/create_enrollments.rb
480
480
  - lib/canvas_sync/generators/templates/migrations/create_grading_period_groups.rb
@@ -502,6 +502,7 @@ files:
502
502
  - lib/canvas_sync/generators/templates/models/context_module_item.rb
503
503
  - lib/canvas_sync/generators/templates/models/course.rb
504
504
  - lib/canvas_sync/generators/templates/models/course_nickname.rb
505
+ - lib/canvas_sync/generators/templates/models/course_progress.rb
505
506
  - lib/canvas_sync/generators/templates/models/enrollment.rb
506
507
  - lib/canvas_sync/generators/templates/models/grading_period.rb
507
508
  - lib/canvas_sync/generators/templates/models/grading_period_group.rb
@@ -599,6 +600,7 @@ files:
599
600
  - lib/canvas_sync/jobs/sync_content_migrations_job.rb
600
601
  - lib/canvas_sync/jobs/sync_context_module_items_job.rb
601
602
  - lib/canvas_sync/jobs/sync_context_modules_job.rb
603
+ - lib/canvas_sync/jobs/sync_course_progresses_job.rb
602
604
  - lib/canvas_sync/jobs/sync_provisioning_report_job.rb
603
605
  - lib/canvas_sync/jobs/sync_roles_job.rb
604
606
  - lib/canvas_sync/jobs/sync_rubric_assessments_job.rb
@@ -617,6 +619,7 @@ files:
617
619
  - lib/canvas_sync/processors/content_migrations_processor.rb
618
620
  - lib/canvas_sync/processors/context_module_items_processor.rb
619
621
  - lib/canvas_sync/processors/context_modules_processor.rb
622
+ - lib/canvas_sync/processors/course_completion_report_processor.rb
620
623
  - lib/canvas_sync/processors/model_mappings.yml
621
624
  - lib/canvas_sync/processors/normal_processor.rb
622
625
  - lib/canvas_sync/processors/provisioning_report_processor.rb
@@ -669,6 +672,7 @@ files:
669
672
  - spec/canvas_sync/processors/content_migrations_processor_spec.rb
670
673
  - spec/canvas_sync/processors/context_module_items_processor_spec.rb
671
674
  - spec/canvas_sync/processors/context_modules_processor_spec.rb
675
+ - spec/canvas_sync/processors/course_completion_report_processor_spec.rb
672
676
  - spec/canvas_sync/processors/normal_processor_spec.rb
673
677
  - spec/canvas_sync/processors/provisioning_report_processor_spec.rb
674
678
  - spec/canvas_sync/processors/rubric_assessments_spec.rb
@@ -689,6 +693,7 @@ files:
689
693
  - spec/dummy/app/models/context_module_item.rb
690
694
  - spec/dummy/app/models/course.rb
691
695
  - spec/dummy/app/models/course_nickname.rb
696
+ - spec/dummy/app/models/course_progress.rb
692
697
  - spec/dummy/app/models/enrollment.rb
693
698
  - spec/dummy/app/models/grading_period.rb
694
699
  - spec/dummy/app/models/grading_period_group.rb
@@ -774,6 +779,7 @@ files:
774
779
  - spec/dummy/db/migrate/20240510094100_create_rubric_associations.rb
775
780
  - spec/dummy/db/migrate/20240510101100_create_rubric_assessments.rb
776
781
  - spec/dummy/db/migrate/20240523101010_create_learning_outcome_results.rb
782
+ - spec/dummy/db/migrate/20240828161300_create_course_progresses.rb
777
783
  - spec/dummy/db/schema.rb
778
784
  - spec/factories/account_factory.rb
779
785
  - spec/factories/admin_factory.rb
@@ -837,6 +843,8 @@ files:
837
843
  - spec/support/fixtures/reports/context_module_items.csv
838
844
  - spec/support/fixtures/reports/context_modules.csv
839
845
  - spec/support/fixtures/reports/course_nicknames.csv
846
+ - spec/support/fixtures/reports/course_progresses.csv
847
+ - spec/support/fixtures/reports/course_progresses_conflict.csv
840
848
  - spec/support/fixtures/reports/courses.csv
841
849
  - spec/support/fixtures/reports/enrollments.csv
842
850
  - spec/support/fixtures/reports/grading_period_groups.csv
@@ -859,7 +867,7 @@ files:
859
867
  homepage: https://instructure.com
860
868
  licenses: []
861
869
  metadata: {}
862
- post_install_message:
870
+ post_install_message:
863
871
  rdoc_options: []
864
872
  require_paths:
865
873
  - lib
@@ -874,236 +882,241 @@ required_rubygems_version: !ruby/object:Gem::Requirement
874
882
  - !ruby/object:Gem::Version
875
883
  version: '0'
876
884
  requirements: []
877
- rubygems_version: 3.1.6
878
- signing_key:
885
+ rubygems_version: 3.5.4
886
+ signing_key:
879
887
  specification_version: 4
880
888
  summary: Gem for generating Canvas models and migrations and syncing data from Canvas
881
889
  test_files:
882
- - spec/canvas_sync/live_events/process_event_job_spec.rb
890
+ - spec/canvas_sync/canvas_sync_spec.rb
891
+ - spec/canvas_sync/jobs/canvas_process_waiter_spec.rb
892
+ - spec/canvas_sync/jobs/job_spec.rb
893
+ - spec/canvas_sync/jobs/report_checker_spec.rb
894
+ - spec/canvas_sync/jobs/report_processor_job_spec.rb
895
+ - spec/canvas_sync/jobs/report_starter_spec.rb
896
+ - spec/canvas_sync/jobs/sync_admins_job_spec.rb
897
+ - spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb
898
+ - spec/canvas_sync/jobs/sync_assignments_job_spec.rb
899
+ - spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb
900
+ - spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb
901
+ - spec/canvas_sync/jobs/sync_context_modules_job_spec.rb
902
+ - spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb
903
+ - spec/canvas_sync/jobs/sync_roles_job_spec.rb
904
+ - spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
905
+ - spec/canvas_sync/jobs/sync_submissions_job_spec.rb
906
+ - spec/canvas_sync/jobs/sync_terms_job_spec.rb
883
907
  - spec/canvas_sync/live_events/live_event_sync_spec.rb
884
908
  - spec/canvas_sync/live_events/live_events_controller_spec.rb
885
- - spec/canvas_sync/services/module_event_spec.rb
886
- - spec/canvas_sync/services/module_item_event_spec.rb
909
+ - spec/canvas_sync/live_events/process_event_job_spec.rb
910
+ - spec/canvas_sync/misc_helper_spec.rb
911
+ - spec/canvas_sync/models/accounts_spec.rb
887
912
  - spec/canvas_sync/models/admins_spec.rb
913
+ - spec/canvas_sync/models/assignment_group_spec.rb
888
914
  - spec/canvas_sync/models/assignment_spec.rb
915
+ - spec/canvas_sync/models/context_module_item_spec.rb
889
916
  - spec/canvas_sync/models/context_module_spec.rb
917
+ - spec/canvas_sync/models/course_spec.rb
918
+ - spec/canvas_sync/models/enrollment_spec.rb
890
919
  - spec/canvas_sync/models/group_membership_spec.rb
891
- - spec/canvas_sync/models/context_module_item_spec.rb
920
+ - spec/canvas_sync/models/group_spec.rb
892
921
  - spec/canvas_sync/models/roles_spec.rb
893
- - spec/canvas_sync/models/accounts_spec.rb
894
922
  - spec/canvas_sync/models/section_spec.rb
895
- - spec/canvas_sync/models/group_spec.rb
896
923
  - spec/canvas_sync/models/submission_spec.rb
897
924
  - spec/canvas_sync/models/term_spec.rb
898
- - spec/canvas_sync/models/enrollment_spec.rb
899
- - spec/canvas_sync/models/course_spec.rb
900
925
  - spec/canvas_sync/models/user_spec.rb
901
- - spec/canvas_sync/models/assignment_group_spec.rb
902
- - spec/canvas_sync/misc_helper_spec.rb
903
- - spec/canvas_sync/jobs/sync_context_module_items_job_spec.rb
904
- - spec/canvas_sync/jobs/sync_terms_job_spec.rb
905
- - spec/canvas_sync/jobs/sync_context_modules_job_spec.rb
906
- - spec/canvas_sync/jobs/sync_assignments_job_spec.rb
907
- - spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb
908
- - spec/canvas_sync/jobs/sync_assignment_groups_job_spec.rb
909
- - spec/canvas_sync/jobs/sync_admins_job_spec.rb
910
- - spec/canvas_sync/jobs/report_starter_spec.rb
911
- - spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb
912
- - spec/canvas_sync/jobs/job_spec.rb
913
- - spec/canvas_sync/jobs/report_processor_job_spec.rb
914
- - spec/canvas_sync/jobs/canvas_process_waiter_spec.rb
915
- - spec/canvas_sync/jobs/sync_submissions_job_spec.rb
916
- - spec/canvas_sync/jobs/report_checker_spec.rb
917
- - spec/canvas_sync/jobs/sync_roles_job_spec.rb
918
- - spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
919
- - spec/canvas_sync/canvas_sync_spec.rb
920
- - spec/canvas_sync/processors/provisioning_report_processor_spec.rb
921
- - spec/canvas_sync/processors/content_migrations_processor_spec.rb
926
+ - spec/canvas_sync/processors/assignment_groups_processor_spec.rb
922
927
  - spec/canvas_sync/processors/assignments_processor_spec.rb
923
- - spec/canvas_sync/processors/normal_processor_spec.rb
924
- - spec/canvas_sync/processors/rubrics_processor_spec.rb
928
+ - spec/canvas_sync/processors/content_migrations_processor_spec.rb
929
+ - spec/canvas_sync/processors/context_module_items_processor_spec.rb
925
930
  - spec/canvas_sync/processors/context_modules_processor_spec.rb
926
- - spec/canvas_sync/processors/assignment_groups_processor_spec.rb
931
+ - spec/canvas_sync/processors/course_completion_report_processor_spec.rb
932
+ - spec/canvas_sync/processors/normal_processor_spec.rb
933
+ - spec/canvas_sync/processors/provisioning_report_processor_spec.rb
934
+ - spec/canvas_sync/processors/rubric_assessments_spec.rb
927
935
  - spec/canvas_sync/processors/rubric_associations_spec.rb
936
+ - spec/canvas_sync/processors/rubrics_processor_spec.rb
928
937
  - spec/canvas_sync/processors/submissions_processor_spec.rb
929
- - spec/canvas_sync/processors/context_module_items_processor_spec.rb
930
- - spec/canvas_sync/processors/rubric_assessments_spec.rb
931
- - spec/job_uniqueness/lock_context_spec.rb
932
- - spec/job_uniqueness/on_conflict/reschedule_spec.rb
933
- - spec/job_uniqueness/on_conflict/raise_spec.rb
934
- - spec/job_uniqueness/on_conflict/log_spec.rb
935
- - spec/job_uniqueness/on_conflict_spec.rb
936
- - spec/job_uniqueness/spec_helper.rb
937
- - spec/job_uniqueness/support/on_conflict.rb
938
- - spec/job_uniqueness/support/test_worker.rb
939
- - spec/job_uniqueness/support/lock_strategy.rb
940
- - spec/job_uniqueness/strategy/while_executing_spec.rb
941
- - spec/job_uniqueness/strategy/until_and_while_executing_spec.rb
942
- - spec/job_uniqueness/strategy/until_executing_spec.rb
943
- - spec/job_uniqueness/strategy/until_executed_spec.rb
944
- - spec/job_uniqueness/strategy/until_expired_spec.rb
945
- - spec/job_uniqueness/strategy/base_spec.rb
946
- - spec/job_uniqueness/unique_job_common_spec.rb
947
- - spec/job_uniqueness/compat/active_job_spec.rb
948
- - spec/job_uniqueness/compat/sidekiq_spec.rb
949
- - spec/job_batching/integration_helper.rb
950
- - spec/job_batching/pool_spec.rb
951
- - spec/job_batching/integration/integration.rb
952
- - spec/job_batching/integration/workflow.rb
953
- - spec/job_batching/integration/fail_then_succeed.rb
954
- - spec/job_batching/integration/nested.rb
955
- - spec/job_batching/integration/simple.rb
956
- - spec/job_batching/status_spec.rb
957
- - spec/job_batching/callback_spec.rb
958
- - spec/job_batching/support/base_job.rb
959
- - spec/job_batching/support/sample_callback.rb
960
- - spec/job_batching/batch_spec.rb
961
- - spec/job_batching/flow_spec.rb
962
- - spec/job_batching/compat/active_job_spec.rb
963
- - spec/job_batching/compat/sidekiq_spec.rb
964
- - spec/job_batching/context_hash_spec.rb
965
- - spec/spec_helper.rb
966
- - spec/support/fake_canvas.rb
967
- - spec/support/fixtures/reports/submissions.csv
968
- - spec/support/fixtures/reports/assignments.csv
969
- - spec/support/fixtures/reports/user_observers.csv
970
- - spec/support/fixtures/reports/xlist.csv
971
- - spec/support/fixtures/reports/sections.csv
972
- - spec/support/fixtures/reports/context_modules.csv
973
- - spec/support/fixtures/reports/users.csv
974
- - spec/support/fixtures/reports/grading_period_groups.csv
975
- - spec/support/fixtures/reports/learning_outcomes.csv
976
- - spec/support/fixtures/reports/groups.csv
977
- - spec/support/fixtures/reports/courses.csv
978
- - spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
979
- - spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
980
- - spec/support/fixtures/reports/rubric_associations.csv
981
- - spec/support/fixtures/reports/assignment_groups.csv
982
- - spec/support/fixtures/reports/group_memberships.csv
983
- - spec/support/fixtures/reports/rubric_assessments.csv
984
- - spec/support/fixtures/reports/enrollments.csv
985
- - spec/support/fixtures/reports/learning_outcome_results.csv
986
- - spec/support/fixtures/reports/course_nicknames.csv
987
- - spec/support/fixtures/reports/provisioning_csv
988
- - spec/support/fixtures/reports/grading_periods.csv
989
- - spec/support/fixtures/reports/rubrics.csv
990
- - spec/support/fixtures/reports/content_migrations.csv
991
- - spec/support/fixtures/reports/context_module_items.csv
992
- - spec/support/fixtures/canvas_responses/module.json
993
- - spec/support/fixtures/canvas_responses/terms.json
994
- - spec/support/fixtures/canvas_responses/admins.json
995
- - spec/support/fixtures/canvas_responses/roles.json
996
- - spec/support/fixtures/canvas_responses/module_item.json
997
- - spec/dummy/db/migrate/20201016181346_create_pseudonyms.rb
998
- - spec/dummy/db/migrate/20240510101100_create_rubric_assessments.rb
999
- - spec/dummy/db/migrate/20190702203630_create_assignment_groups.rb
1000
- - spec/dummy/db/migrate/20190702203627_create_submissions.rb
1001
- - spec/dummy/db/migrate/20190702203624_create_enrollments.rb
1002
- - spec/dummy/db/migrate/20190702203621_create_courses.rb
1003
- - spec/dummy/db/migrate/20211001184920_create_grading_period_groups.rb
1004
- - spec/dummy/db/migrate/20220712210559_create_learning_outcomes.rb
1005
- - spec/dummy/db/migrate/20200416214248_create_group_memberships.rb
1006
- - spec/dummy/db/migrate/20220926221926_create_users.rb
1007
- - spec/dummy/db/migrate/20210907233330_create_grading_periods.rb
1008
- - spec/dummy/db/migrate/20190702203631_create_context_modules.rb
1009
- - spec/dummy/db/migrate/20240408223326_create_course_nicknames.rb
1010
- - spec/dummy/db/migrate/20240509105100_create_rubrics.rb
1011
- - spec/dummy/db/migrate/20240510094100_create_rubric_associations.rb
1012
- - spec/dummy/db/migrate/20190702203632_create_context_module_items.rb
1013
- - spec/dummy/db/migrate/20190927204545_create_roles.rb
1014
- - spec/dummy/db/migrate/20190702203622_create_accounts.rb
1015
- - spec/dummy/db/migrate/20190702203626_create_assignments.rb
1016
- - spec/dummy/db/migrate/20240523101010_create_learning_outcome_results.rb
1017
- - spec/dummy/db/migrate/20200415171620_create_groups.rb
1018
- - spec/dummy/db/migrate/20190927204546_create_admins.rb
1019
- - spec/dummy/db/migrate/20190702203625_create_sections.rb
1020
- - spec/dummy/db/migrate/20210907233329_create_user_observers.rb
1021
- - spec/dummy/db/migrate/20190702203623_create_terms.rb
1022
- - spec/dummy/db/migrate/20220308072643_create_content_migrations.rb
1023
- - spec/dummy/db/schema.rb
938
+ - spec/canvas_sync/services/module_event_spec.rb
939
+ - spec/canvas_sync/services/module_item_event_spec.rb
940
+ - spec/dummy/README.rdoc
1024
941
  - spec/dummy/Rakefile
1025
- - spec/dummy/app/services/live_events/submission_event.rb
1026
- - spec/dummy/app/services/live_events/module_created_event.rb
1027
- - spec/dummy/app/services/live_events/module_item_created_event.rb
1028
- - spec/dummy/app/services/live_events/user_created_event.rb
942
+ - spec/dummy/app/models/account.rb
943
+ - spec/dummy/app/models/admin.rb
944
+ - spec/dummy/app/models/application_record.rb
945
+ - spec/dummy/app/models/assignment.rb
946
+ - spec/dummy/app/models/assignment_group.rb
947
+ - spec/dummy/app/models/content_migration.rb
948
+ - spec/dummy/app/models/context_module.rb
949
+ - spec/dummy/app/models/context_module_item.rb
950
+ - spec/dummy/app/models/course.rb
951
+ - spec/dummy/app/models/course_nickname.rb
952
+ - spec/dummy/app/models/course_progress.rb
953
+ - spec/dummy/app/models/enrollment.rb
954
+ - spec/dummy/app/models/grading_period.rb
955
+ - spec/dummy/app/models/grading_period_group.rb
956
+ - spec/dummy/app/models/group.rb
957
+ - spec/dummy/app/models/group_membership.rb
958
+ - spec/dummy/app/models/learning_outcome.rb
959
+ - spec/dummy/app/models/learning_outcome_result.rb
960
+ - spec/dummy/app/models/pseudonym.rb
961
+ - spec/dummy/app/models/role.rb
962
+ - spec/dummy/app/models/rubric.rb
963
+ - spec/dummy/app/models/rubric_assessment.rb
964
+ - spec/dummy/app/models/rubric_association.rb
965
+ - spec/dummy/app/models/section.rb
966
+ - spec/dummy/app/models/submission.rb
967
+ - spec/dummy/app/models/term.rb
968
+ - spec/dummy/app/models/user.rb
969
+ - spec/dummy/app/models/user_observer.rb
970
+ - spec/dummy/app/services/live_events/assignment_created_event.rb
971
+ - spec/dummy/app/services/live_events/assignment_event.rb
972
+ - spec/dummy/app/services/live_events/assignment_updated_event.rb
1029
973
  - spec/dummy/app/services/live_events/base_event.rb
974
+ - spec/dummy/app/services/live_events/course_created_event.rb
975
+ - spec/dummy/app/services/live_events/course_event.rb
1030
976
  - spec/dummy/app/services/live_events/course_section_created_event.rb
1031
- - spec/dummy/app/services/live_events/user_updated_event.rb
977
+ - spec/dummy/app/services/live_events/course_section_event.rb
978
+ - spec/dummy/app/services/live_events/course_section_updated_event.rb
1032
979
  - spec/dummy/app/services/live_events/course_updated_event.rb
1033
- - spec/dummy/app/services/live_events/submission_created_event.rb
1034
- - spec/dummy/app/services/live_events/syllabus_event.rb
1035
- - spec/dummy/app/services/live_events/module_updated_event.rb
1036
- - spec/dummy/app/services/live_events/course_event.rb
1037
980
  - spec/dummy/app/services/live_events/enrollment_created_event.rb
1038
- - spec/dummy/app/services/live_events/grade_event.rb
1039
- - spec/dummy/app/services/live_events/course_section_updated_event.rb
1040
- - spec/dummy/app/services/live_events/course_created_event.rb
1041
981
  - spec/dummy/app/services/live_events/enrollment_event.rb
1042
- - spec/dummy/app/services/live_events/assignment_updated_event.rb
1043
- - spec/dummy/app/services/live_events/syllabus_updated_event.rb
982
+ - spec/dummy/app/services/live_events/enrollment_updated_event.rb
1044
983
  - spec/dummy/app/services/live_events/grade_changed_event.rb
1045
- - spec/dummy/app/services/live_events/module_item_updated_event.rb
984
+ - spec/dummy/app/services/live_events/grade_event.rb
985
+ - spec/dummy/app/services/live_events/module_created_event.rb
1046
986
  - spec/dummy/app/services/live_events/module_event.rb
1047
- - spec/dummy/app/services/live_events/course_section_event.rb
1048
- - spec/dummy/app/services/live_events/assignment_created_event.rb
1049
- - spec/dummy/app/services/live_events/enrollment_updated_event.rb
1050
- - spec/dummy/app/services/live_events/assignment_event.rb
987
+ - spec/dummy/app/services/live_events/module_item_created_event.rb
1051
988
  - spec/dummy/app/services/live_events/module_item_event.rb
989
+ - spec/dummy/app/services/live_events/module_item_updated_event.rb
990
+ - spec/dummy/app/services/live_events/module_updated_event.rb
991
+ - spec/dummy/app/services/live_events/submission_created_event.rb
992
+ - spec/dummy/app/services/live_events/submission_event.rb
1052
993
  - spec/dummy/app/services/live_events/submission_updated_event.rb
994
+ - spec/dummy/app/services/live_events/syllabus_event.rb
995
+ - spec/dummy/app/services/live_events/syllabus_updated_event.rb
996
+ - spec/dummy/app/services/live_events/user_created_event.rb
1053
997
  - spec/dummy/app/services/live_events/user_event.rb
1054
- - spec/dummy/app/models/course_nickname.rb
1055
- - spec/dummy/app/models/user.rb
1056
- - spec/dummy/app/models/submission.rb
1057
- - spec/dummy/app/models/group_membership.rb
1058
- - spec/dummy/app/models/enrollment.rb
1059
- - spec/dummy/app/models/rubric.rb
1060
- - spec/dummy/app/models/rubric_association.rb
1061
- - spec/dummy/app/models/role.rb
1062
- - spec/dummy/app/models/account.rb
1063
- - spec/dummy/app/models/application_record.rb
1064
- - spec/dummy/app/models/admin.rb
1065
- - spec/dummy/app/models/rubric_assessment.rb
1066
- - spec/dummy/app/models/learning_outcome.rb
1067
- - spec/dummy/app/models/learning_outcome_result.rb
1068
- - spec/dummy/app/models/grading_period.rb
1069
- - spec/dummy/app/models/context_module.rb
1070
- - spec/dummy/app/models/context_module_item.rb
1071
- - spec/dummy/app/models/course.rb
1072
- - spec/dummy/app/models/section.rb
1073
- - spec/dummy/app/models/grading_period_group.rb
1074
- - spec/dummy/app/models/user_observer.rb
1075
- - spec/dummy/app/models/assignment_group.rb
1076
- - spec/dummy/app/models/assignment.rb
1077
- - spec/dummy/app/models/term.rb
1078
- - spec/dummy/app/models/pseudonym.rb
1079
- - spec/dummy/app/models/group.rb
1080
- - spec/dummy/app/models/content_migration.rb
1081
- - spec/dummy/config/secrets.yml
998
+ - spec/dummy/app/services/live_events/user_updated_event.rb
999
+ - spec/dummy/bin/rails
1082
1000
  - spec/dummy/config/application.rb
1083
- - spec/dummy/config/initializers/session_store.rb
1084
- - spec/dummy/config/initializers/wrap_parameters.rb
1085
- - spec/dummy/config/initializers/assets.rb
1001
+ - spec/dummy/config/boot.rb
1002
+ - spec/dummy/config/database.yml
1003
+ - spec/dummy/config/environment.rb
1086
1004
  - spec/dummy/config/environments/development.rb
1087
1005
  - spec/dummy/config/environments/test.rb
1088
- - spec/dummy/config/database.yml
1089
- - spec/dummy/config/boot.rb
1006
+ - spec/dummy/config/initializers/assets.rb
1007
+ - spec/dummy/config/initializers/session_store.rb
1008
+ - spec/dummy/config/initializers/wrap_parameters.rb
1090
1009
  - spec/dummy/config/routes.rb
1091
- - spec/dummy/config/environment.rb
1092
- - spec/dummy/README.rdoc
1010
+ - spec/dummy/config/secrets.yml
1093
1011
  - spec/dummy/config.ru
1094
- - spec/dummy/bin/rails
1012
+ - spec/dummy/db/migrate/20190702203621_create_courses.rb
1013
+ - spec/dummy/db/migrate/20190702203622_create_accounts.rb
1014
+ - spec/dummy/db/migrate/20190702203623_create_terms.rb
1015
+ - spec/dummy/db/migrate/20190702203624_create_enrollments.rb
1016
+ - spec/dummy/db/migrate/20190702203625_create_sections.rb
1017
+ - spec/dummy/db/migrate/20190702203626_create_assignments.rb
1018
+ - spec/dummy/db/migrate/20190702203627_create_submissions.rb
1019
+ - spec/dummy/db/migrate/20190702203630_create_assignment_groups.rb
1020
+ - spec/dummy/db/migrate/20190702203631_create_context_modules.rb
1021
+ - spec/dummy/db/migrate/20190702203632_create_context_module_items.rb
1022
+ - spec/dummy/db/migrate/20190927204545_create_roles.rb
1023
+ - spec/dummy/db/migrate/20190927204546_create_admins.rb
1024
+ - spec/dummy/db/migrate/20200415171620_create_groups.rb
1025
+ - spec/dummy/db/migrate/20200416214248_create_group_memberships.rb
1026
+ - spec/dummy/db/migrate/20201016181346_create_pseudonyms.rb
1027
+ - spec/dummy/db/migrate/20210907233329_create_user_observers.rb
1028
+ - spec/dummy/db/migrate/20210907233330_create_grading_periods.rb
1029
+ - spec/dummy/db/migrate/20211001184920_create_grading_period_groups.rb
1030
+ - spec/dummy/db/migrate/20220308072643_create_content_migrations.rb
1031
+ - spec/dummy/db/migrate/20220712210559_create_learning_outcomes.rb
1032
+ - spec/dummy/db/migrate/20220926221926_create_users.rb
1033
+ - spec/dummy/db/migrate/20240408223326_create_course_nicknames.rb
1034
+ - spec/dummy/db/migrate/20240509105100_create_rubrics.rb
1035
+ - spec/dummy/db/migrate/20240510094100_create_rubric_associations.rb
1036
+ - spec/dummy/db/migrate/20240510101100_create_rubric_assessments.rb
1037
+ - spec/dummy/db/migrate/20240523101010_create_learning_outcome_results.rb
1038
+ - spec/dummy/db/migrate/20240828161300_create_course_progresses.rb
1039
+ - spec/dummy/db/schema.rb
1095
1040
  - spec/factories/account_factory.rb
1096
- - spec/factories/term_factory.rb
1097
- - spec/factories/enrollment_factory.rb
1041
+ - spec/factories/admin_factory.rb
1098
1042
  - spec/factories/assignment_factory.rb
1099
1043
  - spec/factories/assignment_group_factory.rb
1100
- - spec/factories/role_factory.rb
1101
- - spec/factories/admin_factory.rb
1044
+ - spec/factories/context_module_factory.rb
1045
+ - spec/factories/context_module_item_factory.rb
1046
+ - spec/factories/course_factory.rb
1047
+ - spec/factories/enrollment_factory.rb
1102
1048
  - spec/factories/group_factory.rb
1103
1049
  - spec/factories/group_membership_factory.rb
1050
+ - spec/factories/role_factory.rb
1104
1051
  - spec/factories/section_factory.rb
1105
- - spec/factories/context_module_item_factory.rb
1106
- - spec/factories/course_factory.rb
1107
1052
  - spec/factories/submission_factory.rb
1053
+ - spec/factories/term_factory.rb
1108
1054
  - spec/factories/user_factory.rb
1109
- - spec/factories/context_module_factory.rb
1055
+ - spec/job_batching/batch_spec.rb
1056
+ - spec/job_batching/callback_spec.rb
1057
+ - spec/job_batching/compat/active_job_spec.rb
1058
+ - spec/job_batching/compat/sidekiq_spec.rb
1059
+ - spec/job_batching/context_hash_spec.rb
1060
+ - spec/job_batching/flow_spec.rb
1061
+ - spec/job_batching/integration/fail_then_succeed.rb
1062
+ - spec/job_batching/integration/integration.rb
1063
+ - spec/job_batching/integration/nested.rb
1064
+ - spec/job_batching/integration/simple.rb
1065
+ - spec/job_batching/integration/workflow.rb
1066
+ - spec/job_batching/integration_helper.rb
1067
+ - spec/job_batching/pool_spec.rb
1068
+ - spec/job_batching/status_spec.rb
1069
+ - spec/job_batching/support/base_job.rb
1070
+ - spec/job_batching/support/sample_callback.rb
1071
+ - spec/job_uniqueness/compat/active_job_spec.rb
1072
+ - spec/job_uniqueness/compat/sidekiq_spec.rb
1073
+ - spec/job_uniqueness/lock_context_spec.rb
1074
+ - spec/job_uniqueness/on_conflict/log_spec.rb
1075
+ - spec/job_uniqueness/on_conflict/raise_spec.rb
1076
+ - spec/job_uniqueness/on_conflict/reschedule_spec.rb
1077
+ - spec/job_uniqueness/on_conflict_spec.rb
1078
+ - spec/job_uniqueness/spec_helper.rb
1079
+ - spec/job_uniqueness/strategy/base_spec.rb
1080
+ - spec/job_uniqueness/strategy/until_and_while_executing_spec.rb
1081
+ - spec/job_uniqueness/strategy/until_executed_spec.rb
1082
+ - spec/job_uniqueness/strategy/until_executing_spec.rb
1083
+ - spec/job_uniqueness/strategy/until_expired_spec.rb
1084
+ - spec/job_uniqueness/strategy/while_executing_spec.rb
1085
+ - spec/job_uniqueness/support/lock_strategy.rb
1086
+ - spec/job_uniqueness/support/on_conflict.rb
1087
+ - spec/job_uniqueness/support/test_worker.rb
1088
+ - spec/job_uniqueness/unique_job_common_spec.rb
1089
+ - spec/spec_helper.rb
1090
+ - spec/support/fake_canvas.rb
1091
+ - spec/support/fixtures/canvas_responses/admins.json
1092
+ - spec/support/fixtures/canvas_responses/module.json
1093
+ - spec/support/fixtures/canvas_responses/module_item.json
1094
+ - spec/support/fixtures/canvas_responses/roles.json
1095
+ - spec/support/fixtures/canvas_responses/terms.json
1096
+ - spec/support/fixtures/reports/assignment_groups.csv
1097
+ - spec/support/fixtures/reports/assignments.csv
1098
+ - spec/support/fixtures/reports/content_migrations.csv
1099
+ - spec/support/fixtures/reports/context_module_items.csv
1100
+ - spec/support/fixtures/reports/context_modules.csv
1101
+ - spec/support/fixtures/reports/course_nicknames.csv
1102
+ - spec/support/fixtures/reports/course_progresses.csv
1103
+ - spec/support/fixtures/reports/course_progresses_conflict.csv
1104
+ - spec/support/fixtures/reports/courses.csv
1105
+ - spec/support/fixtures/reports/enrollments.csv
1106
+ - spec/support/fixtures/reports/grading_period_groups.csv
1107
+ - spec/support/fixtures/reports/grading_periods.csv
1108
+ - spec/support/fixtures/reports/group_memberships.csv
1109
+ - spec/support/fixtures/reports/groups.csv
1110
+ - spec/support/fixtures/reports/learning_outcome_results.csv
1111
+ - spec/support/fixtures/reports/learning_outcomes.csv
1112
+ - spec/support/fixtures/reports/provisioning_csv
1113
+ - spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
1114
+ - spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
1115
+ - spec/support/fixtures/reports/rubric_assessments.csv
1116
+ - spec/support/fixtures/reports/rubric_associations.csv
1117
+ - spec/support/fixtures/reports/rubrics.csv
1118
+ - spec/support/fixtures/reports/sections.csv
1119
+ - spec/support/fixtures/reports/submissions.csv
1120
+ - spec/support/fixtures/reports/user_observers.csv
1121
+ - spec/support/fixtures/reports/users.csv
1122
+ - spec/support/fixtures/reports/xlist.csv
@@ -1,11 +0,0 @@
1
- module CanvasSync::Concerns
2
- module AutoRelations
3
- extend ActiveSupport::Concern
4
-
5
- # CanvasSync::Record.define_feature self, default: true
6
-
7
- included do
8
-
9
- end
10
- end
11
- end