canvas_sync 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +5 -5
  2. data/lib/canvas_sync.rb +2 -0
  3. data/lib/canvas_sync/generators/templates/migrations/create_group_memberships.rb +18 -0
  4. data/lib/canvas_sync/generators/templates/migrations/create_groups.rb +23 -0
  5. data/lib/canvas_sync/generators/templates/models/account.rb +1 -0
  6. data/lib/canvas_sync/generators/templates/models/course.rb +1 -0
  7. data/lib/canvas_sync/generators/templates/models/group.rb +19 -0
  8. data/lib/canvas_sync/generators/templates/models/group_membership.rb +17 -0
  9. data/lib/canvas_sync/generators/templates/models/user.rb +1 -0
  10. data/lib/canvas_sync/jobs/sync_provisioning_report_job.rb +2 -0
  11. data/lib/canvas_sync/processors/model_mappings.yml +59 -0
  12. data/lib/canvas_sync/processors/provisioning_report_processor.rb +19 -0
  13. data/lib/canvas_sync/version.rb +1 -1
  14. data/spec/canvas_sync/models/accounts_spec.rb +3 -0
  15. data/spec/canvas_sync/models/course_spec.rb +4 -0
  16. data/spec/canvas_sync/models/group_membership_spec.rb +26 -0
  17. data/spec/canvas_sync/models/group_spec.rb +26 -0
  18. data/spec/canvas_sync/models/user_spec.rb +2 -0
  19. data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +20 -0
  20. data/spec/dummy/app/models/account.rb +1 -0
  21. data/spec/dummy/app/models/course.rb +1 -0
  22. data/spec/dummy/app/models/group.rb +25 -0
  23. data/spec/dummy/app/models/group_membership.rb +23 -0
  24. data/spec/dummy/app/models/user.rb +1 -0
  25. data/spec/dummy/db/migrate/20200415171620_create_groups.rb +29 -0
  26. data/spec/dummy/db/migrate/20200416214248_create_group_memberships.rb +24 -0
  27. data/spec/dummy/db/schema.rb +30 -1
  28. data/spec/factories/group_factory.rb +8 -0
  29. data/spec/factories/group_membership_factory.rb +6 -0
  30. data/spec/support/fixtures/reports/group_memberships.csv +3 -0
  31. data/spec/support/fixtures/reports/groups.csv +3 -0
  32. metadata +28 -13
  33. data/spec/dummy/db/test.sqlite3 +0 -0
  34. data/spec/dummy/log/development.log +0 -1248
  35. data/spec/dummy/log/test.log +0 -43258
  36. data/spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv +0 -3
  37. data/spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 5c8386afbd924c0148b5c2158d23ea7acd5b0b85349da51312103e1ea9368c54
4
- data.tar.gz: 051471b40b5a464b66df8ca7ae482874f2791c55604e28f7fe9ce54cb07f875a
2
+ SHA1:
3
+ metadata.gz: 6dc939cb0559d835965e4b61416fa79f19fdb0a4
4
+ data.tar.gz: 9e075f746f42ae230ed6219c8e16b00b77526748
5
5
  SHA512:
6
- metadata.gz: '00742595c4797ba758ef98ab8b034545eb2193a2cae92dfc585e720c7cd9adef663ba0aadcae2c7085e19497ff74461c6d5553d49114f42dac520c8fe48ca448'
7
- data.tar.gz: d8c7eb61e630bb65ea9aa2e86b86c03c2c1f87c151e127314c938f7d1b2438c90dfc5f5ddcc4cb74fe0b525bc4ef9c03dfb140d09fc10045b2f7f56b41524e43
6
+ metadata.gz: c4acb86d39b2aaf09ee9de7ae33d689bc28570babd3086098634fa85e0cca9f8144b22193e3b0d1e21c659e31c807e00899b670d0e52f8549e214b899aae17e2
7
+ data.tar.gz: a18ac0d166e5e61b24f0a00a0284db3c73ea9bf5ea642f4ac11ccbab0a7b436222d68e4930ed2c3f75d517fe0ef9ebb1bb4752019ea29c988f9ab27e92388f70
@@ -23,6 +23,8 @@ module CanvasSync
23
23
  SUPPORTED_MODELS = %w[
24
24
  users
25
25
  courses
26
+ groups
27
+ group_memberships
26
28
  accounts
27
29
  terms
28
30
  enrollments
@@ -0,0 +1,18 @@
1
+ # <%= autogenerated_migration_warning %>
2
+
3
+ class CreateGroupMemberships < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :group_memberships do |t|
6
+ t.bigint :canvas_id, null: false
7
+ t.bigint :canvas_user_id, null: false
8
+ t.bigint :canvas_group_id, null: false
9
+ t.string :group_sis_id
10
+ t.string :user_sis_id
11
+ t.string :workflow_state
12
+
13
+ t.timestamps
14
+ end
15
+
16
+ add_index :group_memberships, :canvas_id, unique: true
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ # <%= autogenerated_migration_warning %>
2
+
3
+ class CreateGroups < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :groups do |t|
6
+ t.bigint :canvas_id, null: false
7
+ t.string :sis_id
8
+ t.bigint :canvas_group_category_id
9
+ t.string :group_category_sis_id
10
+ t.bigint :canvas_account_id
11
+ t.bigint :canvas_course_id
12
+ t.string :name
13
+ t.string :workflow_state
14
+ t.bigint :context_id
15
+ t.string :context_type
16
+ t.integer :max_membership
17
+
18
+ t.timestamps
19
+ end
20
+
21
+ add_index :groups, :canvas_id, unique: true
22
+ end
23
+ end
@@ -12,6 +12,7 @@ class Account < ApplicationRecord
12
12
  primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
13
13
  has_many :sub_accounts, class_name: 'Account',
14
14
  primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
15
+ has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_account_id
15
16
 
16
17
  api_syncable({
17
18
  name: :name,
@@ -11,6 +11,7 @@ class Course < ApplicationRecord
11
11
  has_many :assignments, as: :context, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
12
12
  has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_course_id
13
13
  has_many :assignment_groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
14
+ has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
14
15
 
15
16
  api_syncable({
16
17
  sis_id: :sis_course_id,
@@ -0,0 +1,19 @@
1
+ # <%= autogenerated_model_warning %>
2
+
3
+ class Group < ApplicationRecord
4
+ include CanvasSync::Record
5
+ include CanvasSync::Concerns::ApiSyncable
6
+
7
+ validates :canvas_id, uniqueness: true, presence: true
8
+ belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
9
+ belongs_to :account, primary_key: :canvas_id, foreign_key: :canvas_account_id, optional: true
10
+ has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_group_id
11
+
12
+ api_syncable({
13
+ canvas_id: :id,
14
+ name: :name,
15
+ canvas_course_id: :course_id,
16
+ sis_id: :sis_group_id,
17
+ workflow_state: ->(r){ 'available' },
18
+ }, -> (api) { api.group(canvas_id) })
19
+ end
@@ -0,0 +1,17 @@
1
+ # <%= autogenerated_model_warning %>
2
+
3
+ class GroupMembership < ApplicationRecord
4
+ include CanvasSync::Record
5
+ include CanvasSync::Concerns::ApiSyncable
6
+
7
+ validates :canvas_id, uniqueness: true, presence: true
8
+ belongs_to :group, primary_key: :canvas_id, foreign_key: :canvas_group_id
9
+ belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id
10
+
11
+ api_syncable({
12
+ canvas_id: :id,
13
+ canvas_group_id: :group_id,
14
+ canvas_user_id: :user_id,
15
+ workflow_state: :workflow_state,
16
+ }, -> (api) { api.group_membership(canvas_group_id, canvas_id) })
17
+ end
@@ -9,6 +9,7 @@ class User < ApplicationRecord
9
9
  has_many :admins, primary_key: :canvas_id, foreign_key: :canvas_user_id
10
10
  has_many :admin_roles, through: :admins, source: :role
11
11
  has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_user_id
12
+ has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_user_id
12
13
 
13
14
  api_syncable({
14
15
  sis_id: :sis_user_id,
@@ -49,6 +49,8 @@ module CanvasSync
49
49
  }
50
50
 
51
51
  options[:models].each do |model|
52
+ # group_membership is the only model param that is singular :(
53
+ model = 'group_membership' if model == 'group_memberships'
52
54
  params[model] = true
53
55
  end
54
56
 
@@ -326,3 +326,62 @@ context_module_items:
326
326
  assignment_id:
327
327
  database_column_name: canvas_assignment_id
328
328
  type: integer
329
+
330
+ groups:
331
+ conflict_target: canvas_group_id
332
+ report_columns:
333
+ canvas_group_id:
334
+ database_column_name: canvas_id
335
+ type: integer
336
+ group_id:
337
+ database_column_name: sis_id
338
+ type: string
339
+ canvas_group_category_id:
340
+ database_column_name: canvas_group_category_id
341
+ type: integer
342
+ group_category_id:
343
+ database_column_name: group_category_sis_id
344
+ type: integer
345
+ canvas_account_id:
346
+ database_column_name: canvas_account_id
347
+ type: integer
348
+ canvas_course_id:
349
+ database_column_name: canvas_course_id
350
+ type: integer
351
+ name:
352
+ database_column_name: name
353
+ type: string
354
+ status:
355
+ database_column_name: workflow_state
356
+ type: string
357
+ context_id:
358
+ database_column_name: context_id
359
+ type: integer
360
+ context_type:
361
+ database_column_name: context_type
362
+ type: string
363
+ max_membership:
364
+ database_column_name: max_membership
365
+ type: integer
366
+
367
+ group_memberships:
368
+ conflict_target: canvas_group_membership_id
369
+ report_columns:
370
+ canvas_group_membership_id:
371
+ database_column_name: canvas_id
372
+ type: integer
373
+ canvas_group_id:
374
+ database_column_name: canvas_group_id
375
+ type: integer
376
+ group_id:
377
+ database_column_name: group_sis_id
378
+ type: string
379
+ canvas_user_id:
380
+ database_column_name: canvas_user_id
381
+ type: integer
382
+ user_id:
383
+ database_column_name: user_sis_id
384
+ type: string
385
+ status:
386
+ database_column_name: workflow_state
387
+ type: string
@@ -122,6 +122,25 @@ module CanvasSync
122
122
  mapping[:xlist][:conflict_target].to_sym,
123
123
  )
124
124
  end
125
+
126
+ def bulk_process_groups(report_file_path)
127
+ CanvasSync::Importers::BulkImporter.import(
128
+ report_file_path,
129
+ mapping[:groups][:report_columns],
130
+ Group,
131
+ mapping[:groups][:conflict_target].to_sym,
132
+ )
133
+ end
134
+
135
+ # Note that group membership is singular because we override the model name param in sync_provisioning_report_job
136
+ def bulk_process_group_membership(report_file_path)
137
+ CanvasSync::Importers::BulkImporter.import(
138
+ report_file_path,
139
+ mapping[:group_memberships][:report_columns],
140
+ GroupMembership,
141
+ mapping[:group_memberships][:conflict_target].to_sym,
142
+ )
143
+ end
125
144
  end
126
145
  end
127
146
  end
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.13.0".freeze
2
+ VERSION = "0.14.0".freeze
3
3
  end
@@ -8,4 +8,7 @@ RSpec.describe Account, type: :model do
8
8
  it { should validate_uniqueness_of(:canvas_id) }
9
9
  end
10
10
 
11
+ describe 'associations' do
12
+ it { should have_many(:groups) }
13
+ end
11
14
  end
@@ -41,5 +41,9 @@ RSpec.describe Course, type: :model do
41
41
  it do
42
42
  should have_many(:submissions)
43
43
  end
44
+
45
+ it do
46
+ should have_many(:groups)
47
+ end
44
48
  end
45
49
  end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GroupMembership, type: :model do
4
+ let(:subject) {
5
+ FactoryGirl.create(:group_membership, group: FactoryGirl.create(:group), user: FactoryGirl.create(:user))
6
+ }
7
+
8
+ describe 'validations' do
9
+ it { should validate_presence_of(:canvas_id) }
10
+ it { should validate_uniqueness_of(:canvas_id) }
11
+ end
12
+
13
+ describe 'associations' do
14
+ it do
15
+ should belong_to(:group)
16
+ .with_primary_key(:canvas_id)
17
+ .with_foreign_key(:canvas_group_id)
18
+ end
19
+
20
+ it do
21
+ should belong_to(:user)
22
+ .with_primary_key(:canvas_id)
23
+ .with_foreign_key(:canvas_user_id)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Group, type: :model do
4
+ let(:subject) { FactoryGirl.create(:group) }
5
+
6
+ describe 'validations' do
7
+ it { should validate_presence_of(:canvas_id) }
8
+ it { should validate_uniqueness_of(:canvas_id) }
9
+ end
10
+
11
+ describe 'associations' do
12
+ it { should have_many(:group_memberships) }
13
+
14
+ it do
15
+ should belong_to(:course)
16
+ .with_primary_key(:canvas_id)
17
+ .with_foreign_key(:canvas_course_id)
18
+ end
19
+
20
+ it do
21
+ should belong_to(:account)
22
+ .with_primary_key(:canvas_id)
23
+ .with_foreign_key(:canvas_account_id)
24
+ end
25
+ end
26
+ end
@@ -9,6 +9,8 @@ RSpec.describe User, type: :model do
9
9
  end
10
10
 
11
11
  describe 'associations' do
12
+ it { should have_many(:group_memberships) }
13
+
12
14
  it do
13
15
  should have_many(:enrollments)
14
16
  .with_primary_key(:canvas_id)
@@ -42,6 +42,26 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
42
42
  expect(cross_listed_section.canvas_nonxlist_course_id).to eq 2
43
43
  end
44
44
 
45
+ it 'processes groups' do
46
+ expect {
47
+ subject.process('spec/support/fixtures/reports/groups.csv', { models: ['groups'] }, 1)
48
+ }.to change { Group.count }.by(2)
49
+ group = Group.find_by_name('Group1')
50
+ expect(group.workflow_state).to eq 'available'
51
+ expect(group.canvas_account_id).to eq 1
52
+ expect(group.canvas_id).to eq 50
53
+ end
54
+
55
+ it 'processes group memberships' do
56
+ expect {
57
+ subject.process('spec/support/fixtures/reports/group_memberships.csv', { models: ['group_membership'] }, 1)
58
+ }.to change { GroupMembership.count }.by(2)
59
+ group = GroupMembership.find_by_canvas_id(50)
60
+ expect(group.workflow_state).to eq 'accepted'
61
+ expect(group.canvas_group_id).to eq 1
62
+ expect(group.canvas_user_id).to eq 10
63
+ end
64
+
45
65
  context 'options[:models] is multiple models' do
46
66
  it 'extracts the ZIP and processes each model' do
47
67
  user_count = User.count
@@ -18,6 +18,7 @@ class Account < ApplicationRecord
18
18
  primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
19
19
  has_many :sub_accounts, class_name: 'Account',
20
20
  primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
21
+ has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_account_id
21
22
 
22
23
  api_syncable({
23
24
  name: :name,
@@ -17,6 +17,7 @@ class Course < ApplicationRecord
17
17
  has_many :assignments, as: :context, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
18
18
  has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_course_id
19
19
  has_many :assignment_groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
20
+ has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
20
21
 
21
22
  api_syncable({
22
23
  sis_id: :sis_course_id,
@@ -0,0 +1,25 @@
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 Group < ApplicationRecord
10
+ include CanvasSync::Record
11
+ include CanvasSync::Concerns::ApiSyncable
12
+
13
+ validates :canvas_id, uniqueness: true, presence: true
14
+ belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
15
+ belongs_to :account, primary_key: :canvas_id, foreign_key: :canvas_account_id, optional: true
16
+ has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_group_id
17
+
18
+ api_syncable({
19
+ canvas_id: :id,
20
+ name: :name,
21
+ canvas_course_id: :course_id,
22
+ sis_id: :sis_group_id,
23
+ workflow_state: ->(r){ 'available' },
24
+ }, -> (api) { api.group(canvas_id) })
25
+ end
@@ -0,0 +1,23 @@
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 GroupMembership < ApplicationRecord
10
+ include CanvasSync::Record
11
+ include CanvasSync::Concerns::ApiSyncable
12
+
13
+ validates :canvas_id, uniqueness: true, presence: true
14
+ belongs_to :group, primary_key: :canvas_id, foreign_key: :canvas_group_id
15
+ belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id
16
+
17
+ api_syncable({
18
+ canvas_id: :id,
19
+ canvas_group_id: :group_id,
20
+ canvas_user_id: :user_id,
21
+ workflow_state: :workflow_state,
22
+ }, -> (api) { api.group_membership(canvas_group_id, canvas_id) })
23
+ end
@@ -15,6 +15,7 @@ class User < ApplicationRecord
15
15
  has_many :admins, primary_key: :canvas_id, foreign_key: :canvas_user_id
16
16
  has_many :admin_roles, through: :admins, source: :role
17
17
  has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_user_id
18
+ has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_user_id
18
19
 
19
20
  api_syncable({
20
21
  sis_id: :sis_user_id,
@@ -0,0 +1,29 @@
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 CreateGroups < ActiveRecord::Migration[5.1]
10
+ def change
11
+ create_table :groups do |t|
12
+ t.bigint :canvas_id, null: false
13
+ t.string :sis_id
14
+ t.bigint :canvas_group_category_id
15
+ t.string :group_category_sis_id
16
+ t.bigint :canvas_account_id
17
+ t.bigint :canvas_course_id
18
+ t.string :name
19
+ t.string :workflow_state
20
+ t.bigint :context_id
21
+ t.string :context_type
22
+ t.integer :max_membership
23
+
24
+ t.timestamps
25
+ end
26
+
27
+ add_index :groups, :canvas_id, unique: true
28
+ end
29
+ end