canvas_sync 0.15.1 → 0.16.5
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 +5 -5
- data/db/migrate/20170915210836_create_canvas_sync_job_log.rb +12 -31
- data/db/migrate/20180725155729_add_job_id_to_canvas_sync_job_logs.rb +4 -13
- data/db/migrate/20190916154829_add_fork_count_to_canvas_sync_job_logs.rb +3 -11
- data/lib/canvas_sync.rb +11 -27
- data/lib/canvas_sync/concerns/api_syncable.rb +27 -0
- data/lib/canvas_sync/concerns/legacy_columns.rb +5 -4
- data/lib/canvas_sync/generators/templates/migrations/create_submissions.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/account.rb +3 -0
- data/lib/canvas_sync/generators/templates/models/submission.rb +1 -0
- data/lib/canvas_sync/importers/bulk_importer.rb +7 -4
- data/lib/canvas_sync/job.rb +8 -2
- data/lib/canvas_sync/job_chain.rb +46 -1
- data/lib/canvas_sync/jobs/fork_gather.rb +27 -12
- data/lib/canvas_sync/jobs/report_starter.rb +1 -1
- data/lib/canvas_sync/jobs/sync_provisioning_report_job.rb +5 -5
- data/lib/canvas_sync/jobs/sync_simple_table_job.rb +4 -4
- data/lib/canvas_sync/misc_helper.rb +15 -0
- data/lib/canvas_sync/processors/assignment_groups_processor.rb +3 -2
- data/lib/canvas_sync/processors/assignments_processor.rb +3 -2
- data/lib/canvas_sync/processors/context_module_items_processor.rb +3 -2
- data/lib/canvas_sync/processors/context_modules_processor.rb +3 -2
- data/lib/canvas_sync/processors/model_mappings.yml +3 -0
- data/lib/canvas_sync/processors/normal_processor.rb +2 -1
- data/lib/canvas_sync/processors/provisioning_report_processor.rb +10 -2
- data/lib/canvas_sync/processors/submissions_processor.rb +3 -2
- data/lib/canvas_sync/version.rb +1 -1
- data/spec/canvas_sync/jobs/fork_gather_spec.rb +9 -9
- data/spec/canvas_sync/jobs/sync_provisioning_report_job_spec.rb +2 -2
- data/spec/canvas_sync/jobs/sync_simple_table_job_spec.rb +1 -1
- data/spec/dummy/app/models/account.rb +3 -0
- data/spec/dummy/app/models/pseudonym.rb +14 -0
- data/spec/dummy/app/models/submission.rb +1 -0
- data/spec/dummy/app/models/user.rb +1 -0
- data/spec/dummy/db/migrate/20190702203627_create_submissions.rb +1 -0
- data/spec/dummy/db/migrate/20201016181346_create_pseudonyms.rb +24 -0
- data/spec/dummy/db/schema.rb +17 -4
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +1248 -0
- data/spec/dummy/log/test.log +43258 -0
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv +3 -0
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv +4 -0
- data/spec/support/fixtures/reports/submissions.csv +3 -3
- metadata +22 -8
@@ -9,15 +9,15 @@ module CanvasSync
|
|
9
9
|
# @param options [Hash]
|
10
10
|
def perform(job_chain, options)
|
11
11
|
if options[:term_scope]
|
12
|
-
sub_reports = CanvasSync.fork(@job_log, job_chain, keys: [:canvas_term_id]) do |
|
12
|
+
sub_reports = CanvasSync.fork(@job_log, job_chain, keys: [:canvas_term_id]) do |fork_template|
|
13
13
|
Term.send(options[:term_scope]).find_each.map do |term|
|
14
|
+
fork = fork_template.duplicate
|
14
15
|
# Deep copy the job_chain so each report gets the correct term id passed into
|
15
16
|
# its options with no side effects
|
16
17
|
term_id = get_term_id(term)
|
17
|
-
|
18
|
-
duped_job_chain[:global_options][:canvas_term_id] = term_id
|
18
|
+
fork[:global_options][:canvas_term_id] = term_id
|
19
19
|
{
|
20
|
-
job_chain:
|
20
|
+
job_chain: fork.serialize,
|
21
21
|
params: report_params(options, term_id),
|
22
22
|
options: options,
|
23
23
|
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module CanvasSync
|
4
|
+
module MiscHelper
|
5
|
+
MigrationClass = Rails.version < '5.0' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
|
6
|
+
|
7
|
+
def self.to_boolean(v)
|
8
|
+
if Rails.version < '5.0'
|
9
|
+
ActiveRecord::Type::Boolean.new.type_cast_from_user(v)
|
10
|
+
else
|
11
|
+
ActiveRecord::Type::Boolean.new.deserialize(v)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -8,15 +8,16 @@ module CanvasSync
|
|
8
8
|
# @param options [Hash]
|
9
9
|
class AssignmentGroupsProcessor < ReportProcessor
|
10
10
|
def self.process(report_file_path, _options, report_id)
|
11
|
-
new(report_file_path)
|
11
|
+
new(report_file_path, _options)
|
12
12
|
end
|
13
13
|
|
14
|
-
def initialize(report_file_path)
|
14
|
+
def initialize(report_file_path, options)
|
15
15
|
CanvasSync::Importers::BulkImporter.import(
|
16
16
|
report_file_path,
|
17
17
|
mapping[:assignment_groups][:report_columns],
|
18
18
|
AssignmentGroup,
|
19
19
|
mapping[:assignment_groups][:conflict_target].to_sym,
|
20
|
+
import_args: options
|
20
21
|
)
|
21
22
|
end
|
22
23
|
end
|
@@ -8,15 +8,16 @@ module CanvasSync
|
|
8
8
|
# @param options [Hash]
|
9
9
|
class AssignmentsProcessor < ReportProcessor
|
10
10
|
def self.process(report_file_path, _options, report_id)
|
11
|
-
new(report_file_path)
|
11
|
+
new(report_file_path, _options)
|
12
12
|
end
|
13
13
|
|
14
|
-
def initialize(report_file_path)
|
14
|
+
def initialize(report_file_path, options)
|
15
15
|
CanvasSync::Importers::BulkImporter.import(
|
16
16
|
report_file_path,
|
17
17
|
mapping[:assignments][:report_columns],
|
18
18
|
Assignment,
|
19
19
|
mapping[:assignments][:conflict_target].to_sym,
|
20
|
+
import_args: options
|
20
21
|
)
|
21
22
|
end
|
22
23
|
end
|
@@ -8,15 +8,16 @@ module CanvasSync
|
|
8
8
|
# @param options [Hash]
|
9
9
|
class ContextModuleItemsProcessor < ReportProcessor
|
10
10
|
def self.process(report_file_path, _options, report_id)
|
11
|
-
new(report_file_path)
|
11
|
+
new(report_file_path, _options)
|
12
12
|
end
|
13
13
|
|
14
|
-
def initialize(report_file_path)
|
14
|
+
def initialize(report_file_path, options)
|
15
15
|
CanvasSync::Importers::BulkImporter.import(
|
16
16
|
report_file_path,
|
17
17
|
mapping[:context_module_items][:report_columns],
|
18
18
|
ContextModuleItem,
|
19
19
|
mapping[:context_module_items][:conflict_target].to_sym,
|
20
|
+
import_args: options
|
20
21
|
)
|
21
22
|
end
|
22
23
|
end
|
@@ -8,15 +8,16 @@ module CanvasSync
|
|
8
8
|
# @param options [Hash]
|
9
9
|
class ContextModulesProcessor < ReportProcessor
|
10
10
|
def self.process(report_file_path, _options, report_id)
|
11
|
-
new(report_file_path)
|
11
|
+
new(report_file_path, _options)
|
12
12
|
end
|
13
13
|
|
14
|
-
def initialize(report_file_path)
|
14
|
+
def initialize(report_file_path, options)
|
15
15
|
CanvasSync::Importers::BulkImporter.import(
|
16
16
|
report_file_path,
|
17
17
|
mapping[:context_modules][:report_columns],
|
18
18
|
ContextModule,
|
19
19
|
mapping[:context_modules][:conflict_target].to_sym,
|
20
|
+
import_args: options
|
20
21
|
)
|
21
22
|
end
|
22
23
|
end
|
@@ -18,7 +18,8 @@ module CanvasSync
|
|
18
18
|
report_file_path,
|
19
19
|
mapping[options[:mapping].to_sym][:report_columns],
|
20
20
|
options[:klass].constantize,
|
21
|
-
conflict_target ? conflict_target.to_sym : conflict_target
|
21
|
+
conflict_target ? conflict_target.to_sym : conflict_target,
|
22
|
+
import_args: options
|
22
23
|
)
|
23
24
|
end
|
24
25
|
end
|
@@ -21,7 +21,6 @@ module CanvasSync
|
|
21
21
|
|
22
22
|
def initialize(report_file_path, options) # rubocop:disable Metrics/AbcSize
|
23
23
|
@options = options
|
24
|
-
|
25
24
|
if options[:models].length == 1
|
26
25
|
run_import(options[:models][0], report_file_path)
|
27
26
|
else
|
@@ -75,6 +74,7 @@ module CanvasSync
|
|
75
74
|
mapping[:users][:report_columns],
|
76
75
|
User,
|
77
76
|
mapping[:users][:conflict_target].to_sym,
|
77
|
+
import_args: @options
|
78
78
|
)
|
79
79
|
end
|
80
80
|
|
@@ -84,6 +84,7 @@ module CanvasSync
|
|
84
84
|
mapping[:pseudonyms][:report_columns],
|
85
85
|
Pseudonym,
|
86
86
|
mapping[:pseudonyms][:conflict_target].to_sym,
|
87
|
+
import_args: @options
|
87
88
|
)
|
88
89
|
end
|
89
90
|
|
@@ -92,7 +93,8 @@ module CanvasSync
|
|
92
93
|
report_file_path,
|
93
94
|
mapping[:accounts][:report_columns],
|
94
95
|
Account,
|
95
|
-
mapping[:accounts][:conflict_target].to_sym
|
96
|
+
mapping[:accounts][:conflict_target].to_sym,
|
97
|
+
import_args: @options
|
96
98
|
)
|
97
99
|
end
|
98
100
|
|
@@ -102,6 +104,7 @@ module CanvasSync
|
|
102
104
|
mapping[:courses][:report_columns],
|
103
105
|
Course,
|
104
106
|
mapping[:courses][:conflict_target].to_sym,
|
107
|
+
import_args: @options
|
105
108
|
)
|
106
109
|
end
|
107
110
|
|
@@ -111,6 +114,7 @@ module CanvasSync
|
|
111
114
|
mapping[:enrollments][:report_columns],
|
112
115
|
Enrollment,
|
113
116
|
mapping[:enrollments][:conflict_target].to_sym,
|
117
|
+
import_args: @options
|
114
118
|
)
|
115
119
|
end
|
116
120
|
|
@@ -120,6 +124,7 @@ module CanvasSync
|
|
120
124
|
mapping[:sections][:report_columns],
|
121
125
|
Section,
|
122
126
|
mapping[:sections][:conflict_target].to_sym,
|
127
|
+
import_args: @options
|
123
128
|
)
|
124
129
|
end
|
125
130
|
|
@@ -129,6 +134,7 @@ module CanvasSync
|
|
129
134
|
mapping[:xlist][:report_columns],
|
130
135
|
Section,
|
131
136
|
mapping[:xlist][:conflict_target].to_sym,
|
137
|
+
import_args: @options
|
132
138
|
)
|
133
139
|
end
|
134
140
|
|
@@ -138,6 +144,7 @@ module CanvasSync
|
|
138
144
|
mapping[:groups][:report_columns],
|
139
145
|
Group,
|
140
146
|
mapping[:groups][:conflict_target].to_sym,
|
147
|
+
import_args: @options
|
141
148
|
)
|
142
149
|
end
|
143
150
|
|
@@ -148,6 +155,7 @@ module CanvasSync
|
|
148
155
|
mapping[:group_memberships][:report_columns],
|
149
156
|
GroupMembership,
|
150
157
|
mapping[:group_memberships][:conflict_target].to_sym,
|
158
|
+
import_args: @options
|
151
159
|
)
|
152
160
|
end
|
153
161
|
end
|
@@ -8,15 +8,16 @@ module CanvasSync
|
|
8
8
|
# @param options [Hash]
|
9
9
|
class SubmissionsProcessor < ReportProcessor
|
10
10
|
def self.process(report_file_path, _options, report_id)
|
11
|
-
new(report_file_path)
|
11
|
+
new(report_file_path, _options)
|
12
12
|
end
|
13
13
|
|
14
|
-
def initialize(report_file_path)
|
14
|
+
def initialize(report_file_path, options)
|
15
15
|
CanvasSync::Importers::BulkImporter.import(
|
16
16
|
report_file_path,
|
17
17
|
mapping[:submissions][:report_columns],
|
18
18
|
Submission,
|
19
19
|
mapping[:submissions][:conflict_target].to_sym,
|
20
|
+
import_args: options
|
20
21
|
)
|
21
22
|
end
|
22
23
|
end
|
data/lib/canvas_sync/version.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
RSpec.describe CanvasSync::Jobs::ForkGather do
|
4
4
|
describe '#perform' do
|
5
5
|
let!(:job_log) { CanvasSync::JobLog.create!(job_id: 'BLAH', fork_count: 3) }
|
6
|
-
let(:job_chain) { {jobs: [],
|
6
|
+
let(:job_chain) { {jobs: [], fork_state: { forking_path: ['BLAH'], pre_fork_globals: [{}] }} }
|
7
7
|
|
8
8
|
it 'decrements fork_count' do
|
9
9
|
CanvasSync::Jobs::ForkGather.perform_now(job_chain, {})
|
@@ -21,16 +21,16 @@ RSpec.describe CanvasSync::Jobs::ForkGather do
|
|
21
21
|
CanvasSync::Jobs::ForkGather.perform_now(job_chain, {})
|
22
22
|
end
|
23
23
|
|
24
|
-
it 'continues if no
|
25
|
-
job_chain[:
|
24
|
+
it 'continues if no forking_path is specified' do
|
25
|
+
job_chain[:fork_state].delete(:forking_path)
|
26
26
|
expect(CanvasSync).to receive(:invoke_next)
|
27
27
|
CanvasSync::Jobs::ForkGather.perform_now(job_chain, {})
|
28
28
|
end
|
29
29
|
|
30
|
-
it 'pops the most-recent
|
30
|
+
it 'pops the most-recent forking_path enrty' do
|
31
31
|
job_log.update!(fork_count: 1)
|
32
32
|
expect(CanvasSync).to receive(:invoke_next) do |*args|
|
33
|
-
expect(args[0][:
|
33
|
+
expect(args[0][:fork_state][:forking_path]).to eq []
|
34
34
|
end
|
35
35
|
CanvasSync::Jobs::ForkGather.perform_now(job_chain, {})
|
36
36
|
end
|
@@ -47,8 +47,8 @@ RSpec.describe CanvasSync::Jobs::ForkGather do
|
|
47
47
|
{ job: 'CanvasSync::Jobs::ForkGather' },
|
48
48
|
{ job: 'CanvasSync::Jobs::ReportChecker' },
|
49
49
|
],
|
50
|
-
|
51
|
-
|
50
|
+
fork_state: {
|
51
|
+
forking_path: ['BLAH'],
|
52
52
|
}
|
53
53
|
}
|
54
54
|
}
|
@@ -65,8 +65,8 @@ RSpec.describe CanvasSync::Jobs::ForkGather do
|
|
65
65
|
expect(CanvasSync::Jobs::ForkGather.handle_branch_error(error, job_chain: job_chain)).to be nil
|
66
66
|
end
|
67
67
|
|
68
|
-
it 'does nothing if no
|
69
|
-
job_chain[:
|
68
|
+
it 'does nothing if no forking_path is present' do
|
69
|
+
job_chain[:fork_state][:forking_path] = []
|
70
70
|
expect(CanvasSync::Jobs::ForkGather.handle_branch_error(error, job_chain: job_chain)).to be nil
|
71
71
|
end
|
72
72
|
end
|
@@ -16,7 +16,7 @@ RSpec.describe CanvasSync::Jobs::SyncProvisioningReportJob do
|
|
16
16
|
|
17
17
|
expect(CanvasSync::Jobs::ReportStarter).to receive(:perform_later)
|
18
18
|
.with(
|
19
|
-
expected_job_chain,
|
19
|
+
hash_including(expected_job_chain),
|
20
20
|
'proservices_provisioning_csv',
|
21
21
|
{
|
22
22
|
parameters: {
|
@@ -36,7 +36,7 @@ RSpec.describe CanvasSync::Jobs::SyncProvisioningReportJob do
|
|
36
36
|
|
37
37
|
expect(CanvasSync::Jobs::ReportStarter).to receive(:perform_later)
|
38
38
|
.with(
|
39
|
-
expected_job_chain_2,
|
39
|
+
hash_including(expected_job_chain_2),
|
40
40
|
'proservices_provisioning_csv',
|
41
41
|
{
|
42
42
|
parameters: {
|
@@ -15,7 +15,7 @@ RSpec.describe CanvasSync::Jobs::SyncSimpleTableJob do
|
|
15
15
|
|
16
16
|
expect(CanvasSync::Jobs::ReportStarter).to receive(:perform_later)
|
17
17
|
.with(
|
18
|
-
expected_job_chain,
|
18
|
+
hash_including(expected_job_chain),
|
19
19
|
'proservices_provisioning_csv',
|
20
20
|
{
|
21
21
|
"parameters[include_deleted]" => true,
|
@@ -20,6 +20,9 @@ class Account < ApplicationRecord
|
|
20
20
|
primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
|
21
21
|
has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_account_id
|
22
22
|
|
23
|
+
scope :active, -> { where.not(workflow_state: 'deleted') }
|
24
|
+
# scope :should_canvas_sync, -> { active } # Optional - uses .active if not given
|
25
|
+
|
23
26
|
api_syncable({
|
24
27
|
name: :name,
|
25
28
|
workflow_state: :workflow_state,
|
@@ -0,0 +1,14 @@
|
|
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 Pseudonym < ApplicationRecord
|
10
|
+
include CanvasSync::Record
|
11
|
+
|
12
|
+
validates :canvas_id, uniqueness: true, presence: true
|
13
|
+
belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
14
|
+
end
|
@@ -11,6 +11,7 @@ class User < ApplicationRecord
|
|
11
11
|
include CanvasSync::Concerns::ApiSyncable
|
12
12
|
|
13
13
|
validates :canvas_id, uniqueness: true, presence: true
|
14
|
+
has_many :pseudonyms, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
14
15
|
has_many :enrollments, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
15
16
|
has_many :admins, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
16
17
|
has_many :admin_roles, through: :admins, source: :role
|
@@ -0,0 +1,24 @@
|
|
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 CreatePseudonyms < ActiveRecord::Migration[5.1]
|
10
|
+
def change
|
11
|
+
create_table :pseudonyms do |t|
|
12
|
+
t.bigint :canvas_id, null: false
|
13
|
+
t.bigint :canvas_user_id
|
14
|
+
t.string :sis_id
|
15
|
+
t.string :unique_id
|
16
|
+
t.string :workflow_state
|
17
|
+
|
18
|
+
t.timestamps
|
19
|
+
end
|
20
|
+
|
21
|
+
add_index :pseudonyms, :canvas_id, unique: true
|
22
|
+
add_index :pseudonyms, :canvas_user_id
|
23
|
+
end
|
24
|
+
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: 2020_10_16_181346) do
|
14
14
|
|
15
15
|
# These are extensions that must be enabled in order to support this database
|
16
16
|
enable_extension "plpgsql"
|
@@ -83,7 +83,7 @@ ActiveRecord::Schema.define(version: 2020_04_16_214248) do
|
|
83
83
|
t.index ["canvas_id"], name: "index_assignments_on_canvas_id", unique: true
|
84
84
|
end
|
85
85
|
|
86
|
-
create_table "canvas_sync_job_logs", force: :cascade do |t|
|
86
|
+
create_table "canvas_sync_job_logs", id: :serial, force: :cascade do |t|
|
87
87
|
t.datetime "started_at"
|
88
88
|
t.datetime "completed_at"
|
89
89
|
t.string "exception"
|
@@ -92,8 +92,8 @@ ActiveRecord::Schema.define(version: 2020_04_16_214248) do
|
|
92
92
|
t.string "status"
|
93
93
|
t.text "metadata"
|
94
94
|
t.text "job_arguments"
|
95
|
-
t.datetime "created_at"
|
96
|
-
t.datetime "updated_at"
|
95
|
+
t.datetime "created_at"
|
96
|
+
t.datetime "updated_at"
|
97
97
|
t.string "job_id"
|
98
98
|
t.integer "fork_count"
|
99
99
|
t.index ["job_id"], name: "index_canvas_sync_job_logs_on_job_id"
|
@@ -191,6 +191,18 @@ ActiveRecord::Schema.define(version: 2020_04_16_214248) do
|
|
191
191
|
t.index ["canvas_id"], name: "index_groups_on_canvas_id", unique: true
|
192
192
|
end
|
193
193
|
|
194
|
+
create_table "pseudonyms", force: :cascade do |t|
|
195
|
+
t.bigint "canvas_id", null: false
|
196
|
+
t.bigint "canvas_user_id"
|
197
|
+
t.string "sis_id"
|
198
|
+
t.string "unique_id"
|
199
|
+
t.string "workflow_state"
|
200
|
+
t.datetime "created_at", null: false
|
201
|
+
t.datetime "updated_at", null: false
|
202
|
+
t.index ["canvas_id"], name: "index_pseudonyms_on_canvas_id", unique: true
|
203
|
+
t.index ["canvas_user_id"], name: "index_pseudonyms_on_canvas_user_id"
|
204
|
+
end
|
205
|
+
|
194
206
|
create_table "roles", force: :cascade do |t|
|
195
207
|
t.integer "canvas_id", null: false
|
196
208
|
t.string "label"
|
@@ -225,6 +237,7 @@ ActiveRecord::Schema.define(version: 2020_04_16_214248) do
|
|
225
237
|
t.bigint "canvas_assignment_id"
|
226
238
|
t.bigint "canvas_user_id"
|
227
239
|
t.datetime "submitted_at"
|
240
|
+
t.datetime "due_at"
|
228
241
|
t.datetime "graded_at"
|
229
242
|
t.float "score"
|
230
243
|
t.float "points_possible"
|