canvas_sync 0.17.26.beta1 → 0.17.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/lib/canvas_sync/generators/templates/migrations/create_content_migrations.rb +24 -0
- data/lib/canvas_sync/generators/templates/models/content_migration.rb +10 -0
- data/lib/canvas_sync/importers/bulk_importer.rb +1 -1
- data/lib/canvas_sync/job_batches/context_hash.rb +4 -0
- data/lib/canvas_sync/job_batches/jobs/concurrent_batch_job.rb +12 -9
- data/lib/canvas_sync/job_batches/jobs/managed_batch_job.rb +62 -25
- data/lib/canvas_sync/job_batches/jobs/serial_batch_job.rb +9 -3
- data/lib/canvas_sync/job_batches/sidekiq/web/helpers.rb +1 -1
- data/lib/canvas_sync/jobs/begin_sync_chain_job.rb +2 -0
- data/lib/canvas_sync/jobs/sync_content_migrations_job.rb +20 -0
- data/lib/canvas_sync/jobs/term_batches_job.rb +30 -3
- data/lib/canvas_sync/processors/content_migrations_processor.rb +19 -0
- data/lib/canvas_sync/processors/model_mappings.yml +40 -0
- data/lib/canvas_sync/version.rb +1 -1
- data/lib/canvas_sync.rb +12 -0
- data/spec/canvas_sync/jobs/sync_content_migrations_job_spec.rb +30 -0
- data/spec/canvas_sync/processors/content_migrations_processor_spec.rb +13 -0
- data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +5 -0
- data/spec/dummy/app/models/content_migration.rb +16 -0
- data/spec/dummy/db/migrate/20220308072643_create_content_migrations.rb +30 -0
- data/spec/dummy/db/schema.rb +19 -1
- data/spec/support/fixtures/reports/content_migrations.csv +3 -0
- data/spec/support/fixtures/reports/users.csv +3 -2
- metadata +19 -13
- data/spec/dummy/log/development.log +0 -2069
- data/spec/dummy/log/test.log +0 -83945
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv +0 -3
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8359f6a5054489357a480d15019981f0ade50a145f714bcbd2274c6570689316
|
4
|
+
data.tar.gz: c98c3d8ecda4291e162e31d7c4dfdf9ddff65763f0bb7c345006585f53894cf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ce90338e8e3751fd5767a09eaaf89e733532ffa59df5569bf908930929f34d5167bc01e2637a5eef6ba5ef515c2e6410cc17ce757542b4d0620bb08bd03fd38
|
7
|
+
data.tar.gz: e4456ad37bbf87b63a495d041f038ad6ece797b59c11d19cd7028a030aef452281105f2c53ab56bef3b4cf515f838366874b56838c87936d113c3cacf5570771
|
data/README.md
CHANGED
@@ -34,6 +34,7 @@ The following custom reports are required for the specified models:
|
|
34
34
|
- assignment_groups = "Assignment Group Export" (proserv_assignment_group_export_csv)
|
35
35
|
- context_modules = "Professional Services Context Modules Report" (proserv_context_modules_csv)
|
36
36
|
- context_module_items = "Professional Services Context Module Items Report" (proserv_context_module_items_csv)
|
37
|
+
- content_migrations = "Professional Services Content Migrations Report" (proserv_content_migrations_csv)
|
37
38
|
|
38
39
|
## Prerequisites
|
39
40
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# <%= autogenerated_migration_warning %>
|
2
|
+
|
3
|
+
class CreateContentMigrations < ActiveRecord::Migration[5.1]
|
4
|
+
def change
|
5
|
+
create_table :content_migrations do |t|
|
6
|
+
t.bigint :canvas_id
|
7
|
+
t.bigint :canvas_context_id
|
8
|
+
t.string :canvas_context_type
|
9
|
+
t.string :workflow_state
|
10
|
+
t.text :migration_settings
|
11
|
+
t.datetime :started_at
|
12
|
+
t.datetime :finished_at
|
13
|
+
t.float :progress
|
14
|
+
t.bigint :canvas_source_course_id
|
15
|
+
t.string :migration_type
|
16
|
+
t.bigint :canvas_child_subscription_id
|
17
|
+
t.bigint :canvas_root_account_id
|
18
|
+
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
|
22
|
+
add_index :content_migrations, :canvas_id, unique: true
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# <%= autogenerated_model_warning %>
|
2
|
+
|
3
|
+
class ContentMigration < ApplicationRecord
|
4
|
+
include CanvasSync::Record
|
5
|
+
include CanvasSync::Concerns::ApiSyncable
|
6
|
+
|
7
|
+
validates :canvas_id, uniqueness: true, presence: true
|
8
|
+
belongs_to :context, polymorphic: true, optional: true, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
|
9
|
+
|
10
|
+
end
|
@@ -65,7 +65,7 @@ module CanvasSync
|
|
65
65
|
}
|
66
66
|
|
67
67
|
row_buffer = nil
|
68
|
-
if defined?(User) && klass == User && csv_column_names.include?(
|
68
|
+
if defined?(User) && klass == User && csv_column_names.include?('user_id')
|
69
69
|
row_buffer = UserRowBuffer.new(&row_buffer_out)
|
70
70
|
else
|
71
71
|
row_buffer = NullRowBuffer.new(&row_buffer_out)
|
@@ -3,16 +3,19 @@ require_relative './base_job'
|
|
3
3
|
module CanvasSync
|
4
4
|
module JobBatches
|
5
5
|
class ConcurrentBatchJob < BaseJob
|
6
|
+
def self.make_batch(sub_jobs, context: nil, &blk)
|
7
|
+
ManagedBatchJob.make_batch(
|
8
|
+
sub_jobs,
|
9
|
+
ordered: false,
|
10
|
+
concurrency: true,
|
11
|
+
context: context,
|
12
|
+
desc_prefix: 'ConcurrentBatchJob',
|
13
|
+
&blk
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
6
17
|
def perform(sub_jobs, context: nil)
|
7
|
-
|
8
|
-
b.description = "Concurrent Batch Root"
|
9
|
-
b.context = context
|
10
|
-
b.jobs do
|
11
|
-
sub_jobs.each do |j|
|
12
|
-
ChainBuilder.enqueue_job(j)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
18
|
+
self.class.make_batch(sub_jobs, context: context)
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -3,8 +3,8 @@ require_relative './base_job'
|
|
3
3
|
module CanvasSync
|
4
4
|
module JobBatches
|
5
5
|
class ManagedBatchJob < BaseJob
|
6
|
-
def
|
7
|
-
|
6
|
+
def self.make_batch(sub_jobs, ordered: true, concurrency: nil, context: nil, desc_prefix: nil, &blk)
|
7
|
+
desc_prefix ||= ''
|
8
8
|
|
9
9
|
if concurrency == 0 || concurrency == nil || concurrency == true
|
10
10
|
concurrency = sub_jobs.count
|
@@ -14,38 +14,60 @@ module CanvasSync
|
|
14
14
|
|
15
15
|
root_batch = Batch.new
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
r.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
17
|
+
if concurrency < sub_jobs.count
|
18
|
+
man_batch_id = SecureRandom.urlsafe_base64(10)
|
19
|
+
|
20
|
+
Batch.redis do |r|
|
21
|
+
r.multi do
|
22
|
+
r.hset("MNGBID-#{man_batch_id}", "root_bid", root_batch.bid)
|
23
|
+
r.hset("MNGBID-#{man_batch_id}", "ordered", ordered)
|
24
|
+
r.hset("MNGBID-#{man_batch_id}", "concurrency", concurrency)
|
25
|
+
r.expire("MNGBID-#{man_batch_id}", Batch::BID_EXPIRE_TTL)
|
26
|
+
|
27
|
+
mapped_sub_jobs = sub_jobs.each_with_index.map do |j, i|
|
28
|
+
j['_mngbid_index_'] = i # This allows duplicate jobs when a Redis Set is used
|
29
|
+
j = ActiveJob::Arguments.serialize([j])
|
30
|
+
JSON.unparse(j)
|
31
|
+
end
|
32
|
+
if ordered
|
33
|
+
r.rpush("MNGBID-#{man_batch_id}-jobs", mapped_sub_jobs)
|
34
|
+
else
|
35
|
+
r.sadd("MNGBID-#{man_batch_id}-jobs", mapped_sub_jobs)
|
36
|
+
end
|
37
|
+
r.expire("MNGBID-#{man_batch_id}-jobs", Batch::BID_EXPIRE_TTL)
|
33
38
|
end
|
34
|
-
r.expire("MNGBID-#{man_batch_id}-jobs", Batch::BID_EXPIRE_TTL)
|
35
39
|
end
|
40
|
+
|
41
|
+
root_batch.allow_context_changes = (concurrency == 1)
|
42
|
+
root_batch.on(:success, "#{to_s}.cleanup_redis", managed_batch_id: man_batch_id)
|
43
|
+
|
44
|
+
desc_prefix = "MGD(#{man_batch_id}): #{desc_prefix}"
|
36
45
|
end
|
37
46
|
|
38
|
-
root_batch.description = "Managed Batch Root (#{man_batch_id})"
|
39
|
-
root_batch.allow_context_changes = (concurrency == 1)
|
40
47
|
root_batch.context = context
|
41
|
-
root_batch.on(:success, "#{self.class.to_s}.cleanup_redis", managed_batch_id: man_batch_id)
|
42
|
-
root_batch.jobs {}
|
43
48
|
|
44
|
-
|
45
|
-
|
49
|
+
blk.call(ManagedBatchProxy.new(root_batch)) if blk.present?
|
50
|
+
|
51
|
+
root_batch.description = "#{desc_prefix}: #{root_batch.description || 'Root'}"
|
52
|
+
|
53
|
+
if concurrency < sub_jobs.count
|
54
|
+
root_batch.jobs {}
|
55
|
+
concurrency.times do
|
56
|
+
perform_next_sequence_job(man_batch_id)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
root_batch.jobs do
|
60
|
+
sub_jobs.each do |j|
|
61
|
+
ChainBuilder.enqueue_job(j)
|
62
|
+
end
|
63
|
+
end
|
46
64
|
end
|
47
65
|
end
|
48
66
|
|
67
|
+
def perform(sub_jobs, context: nil, ordered: true, concurrency: nil)
|
68
|
+
self.class.make_batch(sub_jobs, ordered: ordered, concurrency: concurrency, context: context)
|
69
|
+
end
|
70
|
+
|
49
71
|
def self.cleanup_redis(status, options)
|
50
72
|
man_batch_id = options['managed_batch_id']
|
51
73
|
Batch.redis do |r|
|
@@ -94,6 +116,21 @@ module CanvasSync
|
|
94
116
|
end
|
95
117
|
end
|
96
118
|
end
|
119
|
+
|
120
|
+
class ManagedBatchProxy
|
121
|
+
def initialize(real_batch)
|
122
|
+
@real_batch = real_batch
|
123
|
+
end
|
124
|
+
|
125
|
+
delegate_missing_to :real_batch
|
126
|
+
|
127
|
+
def jobs
|
128
|
+
raise "Managed Batches do not support calling .jobs directly!"
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
attr_reader :real_batch
|
133
|
+
end
|
97
134
|
end
|
98
135
|
end
|
99
136
|
end
|
@@ -3,14 +3,20 @@ require_relative './base_job'
|
|
3
3
|
module CanvasSync
|
4
4
|
module JobBatches
|
5
5
|
class SerialBatchJob < BaseJob
|
6
|
-
def
|
7
|
-
ManagedBatchJob.
|
6
|
+
def self.make_batch(sub_jobs, context: nil, &blk)
|
7
|
+
ManagedBatchJob.make_batch(
|
8
8
|
sub_jobs,
|
9
|
-
context: context,
|
10
9
|
ordered: true,
|
11
10
|
concurrency: false,
|
11
|
+
context: context,
|
12
|
+
desc_prefix: 'SerialBatchJob',
|
13
|
+
&blk
|
12
14
|
)
|
13
15
|
end
|
16
|
+
|
17
|
+
def perform(sub_jobs, context: nil)
|
18
|
+
self.class.make_batch(sub_jobs, context: context)
|
19
|
+
end
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CanvasSync
|
2
|
+
module Jobs
|
3
|
+
class SyncContentMigrationsJob < ReportStarter
|
4
|
+
# Syncs ContentMigrations
|
5
|
+
#
|
6
|
+
# Starts a report processor for the content migrations report
|
7
|
+
# (the proserv_content_migrations_csv report must be enabled)
|
8
|
+
#
|
9
|
+
# @param options [Hash]
|
10
|
+
def perform(options)
|
11
|
+
super(
|
12
|
+
"proserv_content_migrations_csv",
|
13
|
+
merge_report_params(options),
|
14
|
+
CanvasSync::Processors::ContentMigrationsProcessor.to_s,
|
15
|
+
{},
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -6,15 +6,42 @@ module CanvasSync
|
|
6
6
|
context = options[:context] || {}
|
7
7
|
if options[:term_scope]
|
8
8
|
Term.send(options[:term_scope]).find_each.map do |term|
|
9
|
-
|
10
|
-
|
9
|
+
term_id = get_term_id(term)
|
10
|
+
local_context = context.merge(canvas_term_id: term_id)
|
11
|
+
|
12
|
+
# Override the delta-syncing date if:
|
13
|
+
# 1. the Term hasn't been synced before or
|
14
|
+
# 2. the Term underwent a period of not syncing
|
15
|
+
term_last_sync = CanvasSync.redis.get(self.class.last_sync_key(term_id))
|
16
|
+
if batch_context[:updated_after]
|
17
|
+
if !term_last_sync.present? || batch_context[:updated_after] > term_last_sync
|
18
|
+
local_context[:updated_after] = term_last_sync.presence
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
JobBatches::ManagedBatchJob.make_batch(jobs, ordered: false, concurrency: true) do |b|
|
23
|
+
b.description = "TermBatchJob(#{term.canvas_id}) Root"
|
24
|
+
b.context = local_context
|
25
|
+
b.on(:success, "#{self.class.to_s}.batch_finished")
|
26
|
+
end
|
11
27
|
end
|
12
28
|
else
|
13
|
-
JobBatches::ConcurrentBatchJob.
|
29
|
+
JobBatches::ConcurrentBatchJob.make_batch(jobs, context: context)
|
14
30
|
end
|
15
31
|
end
|
16
32
|
end
|
17
33
|
|
34
|
+
def self.batch_finished(status, opts)
|
35
|
+
ctx = JobBatches::Batch.current_context
|
36
|
+
term_id = ctx[:canvas_term_id]
|
37
|
+
CanvasSync.redis.set(last_sync_key(term_id), ctx[:batch_start_time])
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.last_sync_key(term_id)
|
41
|
+
ctx = JobBatches::Batch.current_context
|
42
|
+
"#{CanvasSync.redis_prefix}:#{ctx[:batch_genre]}:#{term_id}:last_sync"
|
43
|
+
end
|
44
|
+
|
18
45
|
def get_term_id(term)
|
19
46
|
term.try(:canvas_id) || term.canvas_term_id
|
20
47
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "./report_processor"
|
2
|
+
|
3
|
+
module CanvasSync
|
4
|
+
module Processors
|
5
|
+
# Processes a content migrations report using the bulk importer.
|
6
|
+
#
|
7
|
+
# @param report_file_path [String]
|
8
|
+
# @param options [Hash]
|
9
|
+
class ContentMigrationsProcessor < 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, ContentMigration, options: options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -469,3 +469,43 @@ grading_period_groups:
|
|
469
469
|
status:
|
470
470
|
database_column_name: workflow_state
|
471
471
|
type: string
|
472
|
+
|
473
|
+
content_migrations:
|
474
|
+
conflict_target: canvas_migration_id
|
475
|
+
report_columns:
|
476
|
+
canvas_migration_id:
|
477
|
+
database_column_name: canvas_id
|
478
|
+
type: integer
|
479
|
+
canvas_context_id:
|
480
|
+
database_column_name: canvas_context_id
|
481
|
+
type: integer
|
482
|
+
canvas_context_type:
|
483
|
+
database_column_name: canvas_context_type
|
484
|
+
type: string
|
485
|
+
workflow_state:
|
486
|
+
database_column_name: workflow_state
|
487
|
+
type: string
|
488
|
+
migration_settings:
|
489
|
+
database_column_name: migration_settings
|
490
|
+
type: text
|
491
|
+
started_at:
|
492
|
+
database_column_name: started_at
|
493
|
+
type: datetime
|
494
|
+
finished_at:
|
495
|
+
database_column_name: finished_at
|
496
|
+
type: datetime
|
497
|
+
progress:
|
498
|
+
database_column_name: progress
|
499
|
+
type: float
|
500
|
+
canvas_source_course_id:
|
501
|
+
database_column_name: canvas_source_course_id
|
502
|
+
type: integer
|
503
|
+
migration_type:
|
504
|
+
database_column_name: migration_type
|
505
|
+
type: string
|
506
|
+
canvas_child_subscription_id:
|
507
|
+
database_column_name: canvas_child_subscription_id
|
508
|
+
type: integer
|
509
|
+
canvas_root_account_id:
|
510
|
+
database_column_name: canvas_root_account_id
|
511
|
+
type: integer
|
data/lib/canvas_sync/version.rb
CHANGED
data/lib/canvas_sync.rb
CHANGED
@@ -44,6 +44,7 @@ module CanvasSync
|
|
44
44
|
user_observers
|
45
45
|
grading_periods
|
46
46
|
grading_period_groups
|
47
|
+
content_migrations
|
47
48
|
].freeze
|
48
49
|
|
49
50
|
SUPPORTED_TERM_SCOPE_MODELS = %w[
|
@@ -150,6 +151,7 @@ module CanvasSync
|
|
150
151
|
assignment_groups: CanvasSync::Jobs::SyncAssignmentGroupsJob,
|
151
152
|
context_modules: CanvasSync::Jobs::SyncContextModulesJob,
|
152
153
|
context_module_items: CanvasSync::Jobs::SyncContextModuleItemsJob,
|
154
|
+
content_migrations: CanvasSync::Jobs::SyncContentMigrationsJob,
|
153
155
|
}.with_indifferent_access
|
154
156
|
|
155
157
|
root_chain = base_canvas_sync_chain(**kwargs, globals: options[:global] || kwargs[:globals])
|
@@ -320,5 +322,15 @@ module CanvasSync
|
|
320
322
|
return if invalid.empty?
|
321
323
|
raise "Invalid live event(s) specified: #{invalid.join(', ')}. Only #{SUPPORTED_LIVE_EVENTS.join(', ')} are supported."
|
322
324
|
end
|
325
|
+
|
326
|
+
def redis(*args, &blk)
|
327
|
+
JobBatches::Batch.redis(*args, &blk)
|
328
|
+
end
|
329
|
+
|
330
|
+
def redis_prefix
|
331
|
+
pfx = "cs"
|
332
|
+
pfx = "#{Apartment::Tenant.current}:#{pfx}" if defined?(Apartment)
|
333
|
+
pfx
|
334
|
+
end
|
323
335
|
end
|
324
336
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe CanvasSync::Jobs::SyncContentMigrationsJob do
|
4
|
+
describe "#perform" do
|
5
|
+
context "no parameters is specified" do
|
6
|
+
it "enqueues a ReportStarter for the proserv_content_migrations_csv" do
|
7
|
+
expect_any_instance_of(Bearcat::Client).to receive(:start_report)
|
8
|
+
.with("self", "proserv_content_migrations_csv", { parameters: { } })
|
9
|
+
.and_return("id" => 1)
|
10
|
+
|
11
|
+
expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
|
12
|
+
|
13
|
+
CanvasSync::Jobs::SyncContentMigrationsJob.perform_now({})
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "updated_after parameters is specified" do
|
18
|
+
it "enqueues a ReportStarter for the proserv_content_migrations_csv and get data from given date" do
|
19
|
+
expect_any_instance_of(Bearcat::Client).to receive(:start_report)
|
20
|
+
.with("self", "proserv_content_migrations_csv", { parameters: { updated_after: 6.hours.ago.to_s } })
|
21
|
+
.and_return("id" => 1)
|
22
|
+
|
23
|
+
expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
|
24
|
+
|
25
|
+
set_batch_context(updated_after: 6.hours.ago.to_s)
|
26
|
+
CanvasSync::Jobs::SyncContentMigrationsJob.perform_now({})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe CanvasSync::Processors::ContentMigrationsProcessor do
|
4
|
+
let(:subject) { CanvasSync::Processors::ContentMigrationsProcessor }
|
5
|
+
|
6
|
+
describe "#process" do
|
7
|
+
it "inserts content migrations" do
|
8
|
+
expect {
|
9
|
+
subject.process("spec/support/fixtures/reports/content_migrations.csv", {}, 1)
|
10
|
+
}.to change { ContentMigration.count }.by(2)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -10,6 +10,11 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
|
|
10
10
|
}.to change { User.count }.by(2)
|
11
11
|
end
|
12
12
|
|
13
|
+
it 'uses a User row with a sis_id' do
|
14
|
+
subject.process('spec/support/fixtures/reports/users.csv', { models: ['users'] }, 1)
|
15
|
+
expect(User.find_by(canvas_id: 2).sis_id).to eq 'sis_id_2'
|
16
|
+
end
|
17
|
+
|
13
18
|
it 'processes courses' do
|
14
19
|
expect {
|
15
20
|
subject.process('spec/support/fixtures/reports/courses.csv', { models: ['courses'] }, 1)
|
@@ -0,0 +1,16 @@
|
|
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
|
+
class ContentMigration < ApplicationRecord
|
10
|
+
include CanvasSync::Record
|
11
|
+
include CanvasSync::Concerns::ApiSyncable
|
12
|
+
|
13
|
+
validates :canvas_id, uniqueness: true, presence: true
|
14
|
+
belongs_to :context, polymorphic: true, optional: true, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
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 CreateContentMigrations < ActiveRecord::Migration[5.1]
|
10
|
+
def change
|
11
|
+
create_table :content_migrations do |t|
|
12
|
+
t.bigint :canvas_id
|
13
|
+
t.bigint :canvas_context_id
|
14
|
+
t.string :canvas_context_type
|
15
|
+
t.string :workflow_state
|
16
|
+
t.text :migration_settings
|
17
|
+
t.datetime :started_at
|
18
|
+
t.datetime :finished_at
|
19
|
+
t.float :progress
|
20
|
+
t.bigint :canvas_source_course_id
|
21
|
+
t.string :migration_type
|
22
|
+
t.bigint :canvas_child_subscription_id
|
23
|
+
t.bigint :canvas_root_account_id
|
24
|
+
|
25
|
+
t.timestamps
|
26
|
+
end
|
27
|
+
|
28
|
+
add_index :content_migrations, :canvas_id, unique: true
|
29
|
+
end
|
30
|
+
end
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(version:
|
13
|
+
ActiveRecord::Schema.define(version: 2022_03_08_072643) do
|
14
14
|
|
15
15
|
# These are extensions that must be enabled in order to support this database
|
16
16
|
enable_extension "plpgsql"
|
@@ -110,6 +110,24 @@ ActiveRecord::Schema.define(version: 2021_10_01_184920) do
|
|
110
110
|
t.string "batch_bid"
|
111
111
|
end
|
112
112
|
|
113
|
+
create_table "content_migrations", force: :cascade do |t|
|
114
|
+
t.bigint "canvas_id"
|
115
|
+
t.bigint "canvas_context_id"
|
116
|
+
t.string "canvas_context_type"
|
117
|
+
t.string "workflow_state"
|
118
|
+
t.text "migration_settings"
|
119
|
+
t.datetime "started_at"
|
120
|
+
t.datetime "finished_at"
|
121
|
+
t.float "progress"
|
122
|
+
t.bigint "canvas_source_course_id"
|
123
|
+
t.string "migration_type"
|
124
|
+
t.bigint "canvas_child_subscription_id"
|
125
|
+
t.bigint "canvas_root_account_id"
|
126
|
+
t.datetime "created_at", null: false
|
127
|
+
t.datetime "updated_at", null: false
|
128
|
+
t.index ["canvas_id"], name: "index_content_migrations_on_canvas_id", unique: true
|
129
|
+
end
|
130
|
+
|
113
131
|
create_table "context_module_items", force: :cascade do |t|
|
114
132
|
t.bigint "canvas_id"
|
115
133
|
t.bigint "canvas_context_module_id"
|
@@ -0,0 +1,3 @@
|
|
1
|
+
canvas_migration_id,canvas_context_id,canvas_context_type,workflow_state,migration_settings,started_at,finished_at,progress,canvas_source_course_id,migration_type,canvas_child_subscription_id,canvas_root_account_id
|
2
|
+
101,1250,Course,imported,,2022-02-18 10:10:40,2022-02-18 10:11:40,100,1200,course_copy_importer,,1
|
3
|
+
102,1251,Course,imported,,2022-02-18 10:10:40,2022-02-18 10:11:40,100,1120,master_course_import,3,1
|
@@ -1,4 +1,5 @@
|
|
1
1
|
canvas_user_id,user_id,integration_id,authentication_provider_id,login_id,first_name,last_name,full_name,sortable_name,short_name,email,status,created_by_sis
|
2
2
|
1,sis_id_1,,123,spiderdude1337,Patches,the Spider,Patches the Spider,"the Spider, Patches",,poorbastard@yharnam.com,active,FALSE
|
3
|
-
2
|
4
|
-
2,sis_id_2,,1234,retireddude110,Hunter,Djura,Hunter Djura,"Djura, Hunter",,dreamer@yharnam.com,active,FALSE
|
3
|
+
2,,,1234,retireddude109,Hunter,Djura,Hunter Djura,"Djura, Hunter",,dreamer@yharnam.com,active,FALSE
|
4
|
+
2,sis_id_2,,1234,retireddude110,Hunter,Djura,Hunter Djura,"Djura, Hunter",,dreamer@yharnam.com,active,FALSE
|
5
|
+
2,,,1234,retireddude110,Hunter,Djura,Hunter Djura,"Djura, Hunter",,dreamer@yharnam.com,active,FALSE
|