canvas_sync 0.3.11 → 0.3.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88b9c94d7b3d1ab3d2a2249ed687faa4b68e88d780f3c2c61344aa896488dba6
4
- data.tar.gz: 6912ce81b3a87b97233764d8874d84ae60aa1c4e168beba9b41f8c996d96c2ce
3
+ metadata.gz: 6c6eec06420fbb476e980bf7c1aae7d9f8679eb6b98558de1cb7765f5df13a12
4
+ data.tar.gz: 60963185f828d72df3e2a24d3bb3d1d4cf4dde73c0e2a9ce38f0c2147c178d70
5
5
  SHA512:
6
- metadata.gz: 233214ceff623a94e72c60ab5d31879c23776623fb13498b8dacc63281e587dc4d3cf0b71eab17113395752785b3d93c644cb591dc8cbaceaf950ca77203d7e8
7
- data.tar.gz: d4397f49130c1691d20bb1d421d8f91f4d90325de932ab0b52d8be0fb2eb230eef258f04329f598dadb942f0020f106b42481703bd9077dd968e57dee374bbc8
6
+ metadata.gz: 45c726b97e96b370c84fa2393d4d4378a22f145bf3b7f4544c4f78f1aff2a0a0b40b76e3b9d5c5e920e3ff423f6da0e5b8893f6744f05de69dcbfdabe5ea42d4
7
+ data.tar.gz: 02d4f57c81e21724da088b3bf877b88a507895da1fd595335a0f42581d82e3875646084ce229f0d58d6c5ad72b4e13e68712e1befab589bea2673193b3e7c9de
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ task :update_test_schema do
11
11
  puts "Updating test models and migration files..."
12
12
  stream_command("spec/dummy/bin/rails generate canvas_sync:install --models all --force")
13
13
  puts "Updating the test database and schema..."
14
- stream_command("cd spec/dummy; bundle exec rake db:drop; bundle exec rake db:migrate")
14
+ stream_command("cd spec/dummy; bundle exec rake db:drop; bundle exec rake db:create; bundle exec rake db:migrate")
15
15
  end
16
16
 
17
17
  def stream_command(cmd)
@@ -7,18 +7,19 @@ require "canvas_sync/jobs/report_starter"
7
7
  require "canvas_sync/jobs/report_checker"
8
8
  require "canvas_sync/jobs/report_processor_job"
9
9
  require "canvas_sync/jobs/sync_provisioning_report_job"
10
+ require "canvas_sync/jobs/sync_assignments_job"
10
11
  require "canvas_sync/jobs/sync_terms_job"
11
12
  require "canvas_sync/jobs/sync_users_job"
12
13
  require "canvas_sync/jobs/sync_roles_job"
13
14
  require "canvas_sync/jobs/sync_admins_job"
14
15
 
15
- Dir[File.dirname(__FILE__) + "/canvas_sync/processors/*.rb"].each {|file| require file }
16
- Dir[File.dirname(__FILE__) + "/canvas_sync/importers/*.rb"].each {|file| require file }
17
- Dir[File.dirname(__FILE__) + "/canvas_sync/generators/*.rb"].each {|file| require file }
16
+ Dir[File.dirname(__FILE__) + "/canvas_sync/processors/*.rb"].each { |file| require file }
17
+ Dir[File.dirname(__FILE__) + "/canvas_sync/importers/*.rb"].each { |file| require file }
18
+ Dir[File.dirname(__FILE__) + "/canvas_sync/generators/*.rb"].each { |file| require file }
18
19
 
19
20
  module CanvasSync
20
- SUPPORTED_MODELS = %w(users courses terms enrollments sections roles admins xlist)
21
- SUPPORTED_LIVE_EVENTS = %w(course enrollment submission assignment user syllabus grade)
21
+ SUPPORTED_MODELS = %w[users courses terms enrollments sections assignments roles admins xlist].freeze
22
+ SUPPORTED_LIVE_EVENTS = %w[course enrollment submission assignment user syllabus grade].freeze
22
23
 
23
24
  # Runs a standard provisioning sync job with no extra report types.
24
25
  # Terms will be synced first using the API. If you are syncing users/roles/admins
@@ -101,7 +102,11 @@ module CanvasSync
101
102
  models = models - ['admins']
102
103
  end
103
104
 
104
- jobs.push({ job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: term_scope, models: models } })
105
+ jobs.push(job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: term_scope, models: models })
106
+
107
+ if models.include?("assignments")
108
+ jobs.push(job: CanvasSync::Jobs::SyncAssignmentsJob.to_s, options: {})
109
+ end
105
110
 
106
111
  global_options = { legacy_support: legacy_support }
107
112
  global_options[:account_id] = account_id if account_id.present?
@@ -0,0 +1,6 @@
1
+ <%= autogenerated_model_warning %>
2
+
3
+ class Assignment < ApplicationRecord
4
+ validates :canvas_assignment_id, uniqueness: true, presence: true
5
+ belongs_to :context, polymorphic: true, optional: true, primary_key: :canvas_course_id
6
+ end
@@ -5,4 +5,5 @@ class Course < ApplicationRecord
5
5
  belongs_to :term, foreign_key: :canvas_term_id, primary_key: :canvas_term_id, optional: true
6
6
  has_many :enrollments, primary_key: :canvas_course_id, foreign_key: :canvas_course_id
7
7
  has_many :sections, primary_key: :canvas_course_id, foreign_key: :canvas_course_id
8
+ has_many :assignments, as: :context, primary_key: :canvas_course_id
8
9
  end
@@ -0,0 +1,31 @@
1
+ <%= autogenerated_migration_warning %>
2
+
3
+ class CreateAssignments < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :assignments do |t|
6
+ t.bigint :canvas_assignment_id, null: false
7
+ t.string :title
8
+ t.text :description
9
+ t.datetime :due_at
10
+ t.datetime :unlock_at
11
+ t.datetime :lock_at
12
+ t.integer :points_possible
13
+ t.integer :min_score
14
+ t.integer :max_score
15
+ t.integer :mastery_score
16
+ t.string :grading_type
17
+ t.string :submission_types
18
+ t.string :workflow_state
19
+ t.integer :context_id
20
+ t.string :context_type
21
+ t.integer :assignment_group_id
22
+ t.integer :grading_scheme_id
23
+ t.integer :grading_standard_id
24
+
25
+ t.timestamps
26
+ end
27
+
28
+ add_index :assignments, :canvas_assignment_id, unique: true
29
+ add_index :assignments, [:context_id, :context_type]
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ module CanvasSync
2
+ module Jobs
3
+ class SyncAssignmentsJob < ReportStarter
4
+ # Syncs Assignments
5
+ #
6
+ # Starts a report processor for the assignment report
7
+ # (the proserv_assignment_export_csv report must be enabled)
8
+ #
9
+ # @param job_chain [Hash]
10
+ # @param options [Hash]
11
+ def perform(job_chain, _options)
12
+ report_params = if job_chain[:global_options][:term_id].present?
13
+ { enrollment_term_id: job_chain[:global_options][:term_id] }
14
+ else
15
+ {}
16
+ end
17
+
18
+ super(
19
+ job_chain,
20
+ "proserv_assignment_export_csv",
21
+ report_params,
22
+ CanvasSync::Processors::AssignmentsProcessor.to_s,
23
+ {},
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "./report_processor"
2
+
3
+ module CanvasSync
4
+ module Processors
5
+ # Processes an assignments report using the bulk importer.
6
+ #
7
+ # @param report_file_path [String]
8
+ # @param options [Hash]
9
+ class AssignmentsProcessor < ReportProcessor
10
+ def self.process(report_file_path, _options)
11
+ new(report_file_path)
12
+ end
13
+
14
+ def initialize(report_file_path)
15
+ CanvasSync::Importers::BulkImporter.import(
16
+ report_file_path,
17
+ mapping[:assignments][:report_columns],
18
+ Assignment,
19
+ mapping[:assignments][:conflict_target].to_sym,
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
@@ -128,3 +128,61 @@ xlist:
128
128
  canvas_nonxlist_course_id:
129
129
  database_column_name: canvas_nonxlist_course_id
130
130
  type: integer
131
+
132
+ assignments:
133
+ conflict_target: id
134
+ report_columns:
135
+ id:
136
+ database_column_name: :canvas_assignment_id
137
+ type: integer
138
+ title:
139
+ database_column_name: title
140
+ type: string
141
+ description:
142
+ database_column_name: description
143
+ type: text
144
+ due_at:
145
+ database_column_name: due_at
146
+ type: datetime
147
+ unlock_at:
148
+ database_column_name: unlock_at
149
+ type: datetime
150
+ lock_at:
151
+ database_column_name: lock_at
152
+ type: datetime
153
+ points_possible:
154
+ database_column_name: points_possible
155
+ type: integer
156
+ min_score:
157
+ database_column_name: min_score
158
+ type: integer
159
+ max_score:
160
+ database_column_name: max_score
161
+ type: integer
162
+ mastery_score:
163
+ database_column_name: mastery_score
164
+ type: integer
165
+ grading_type:
166
+ database_column_name: grading_type
167
+ type: string
168
+ submission_types:
169
+ database_column_name: submission_types
170
+ type: string
171
+ workflow_state:
172
+ database_column_name: workflow_state
173
+ type: string
174
+ context_id:
175
+ database_column_name: context_id
176
+ type: integer
177
+ context_type:
178
+ database_column_name: context_type
179
+ type: string
180
+ assignment_group_id:
181
+ database_column_name: assignment_group_id
182
+ type: integer
183
+ grading_scheme_id:
184
+ database_column_name: grading_scheme_id
185
+ type: integer
186
+ grading_standard_id:
187
+ database_column_name: grading_standard_id
188
+ type: integer
@@ -1,11 +1,11 @@
1
- require 'csv'
2
- require 'activerecord-import'
3
- require 'zip'
4
- require 'yaml'
1
+ require "csv"
2
+ require "activerecord-import"
3
+ require "zip"
4
+ require_relative "./report_processor"
5
5
 
6
6
  module CanvasSync
7
7
  module Processors
8
- class ProvisioningReportProcessor
8
+ class ProvisioningReportProcessor < ReportProcessor
9
9
  # Processes a provisioning report using the bulk importer.
10
10
  #
11
11
  # options must contain a models key. If there is only one model
@@ -101,20 +101,6 @@ module CanvasSync
101
101
  mapping[:xlist][:conflict_target].to_sym
102
102
  )
103
103
  end
104
-
105
- def mapping
106
- @mapping ||= begin
107
- mapping = YAML::load_file(File.join(__dir__, 'model_mappings.yml')).deep_symbolize_keys!
108
- override_filepath = Rails.root.join("config/canvas_sync_provisioning_mapping.yml")
109
-
110
- if File.file?(override_filepath)
111
- override = YAML::load_file(override_filepath).deep_symbolize_keys!
112
- mapping = mapping.merge(override)
113
- end
114
-
115
- mapping
116
- end
117
- end
118
104
  end
119
105
  end
120
106
  end
@@ -0,0 +1,22 @@
1
+ require "yaml"
2
+
3
+ module CanvasSync
4
+ module Processors
5
+ # Base report processing class
6
+ class ReportProcessor
7
+ def mapping
8
+ @mapping ||= begin
9
+ mapping = YAML.load_file(File.join(__dir__, "model_mappings.yml")).deep_symbolize_keys!
10
+ override_filepath = Rails.root.join("config/canvas_sync_provisioning_mapping.yml")
11
+
12
+ if File.file?(override_filepath)
13
+ override = YAML.load_file(override_filepath).deep_symbolize_keys!
14
+ mapping = mapping.merge(override)
15
+ end
16
+
17
+ mapping
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = '0.3.11'
2
+ VERSION = '0.3.12'
3
3
  end
@@ -106,6 +106,21 @@ RSpec.describe CanvasSync do
106
106
  })
107
107
  end
108
108
  end
109
+
110
+ context "we are syncing assignments" do
111
+ it "appends the SyncAssignmentsJob" do
112
+ chain = CanvasSync.default_provisioning_report_chain(%w[users enrollments assignments])
113
+
114
+ expect(chain).to eq(
115
+ jobs: [
116
+ { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
117
+ { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: nil, models: %w[users enrollments assignments] } },
118
+ { job: CanvasSync::Jobs::SyncAssignmentsJob.to_s, options: {} },
119
+ ],
120
+ global_options: { legacy_support: false },
121
+ )
122
+ end
123
+ end
109
124
  end
110
125
  end
111
126
  end
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe CanvasSync::Jobs::SyncAssignmentsJob do
4
+ describe "#perform" do
5
+ context "a term id is in the global_options" do
6
+ it "enqueues a ReportStarter for the proserv_assignment_export_csv for the given term" do
7
+ expect_any_instance_of(Bearcat::Client).to receive(:start_report)
8
+ .with("self", "proserv_assignment_export_csv", enrollment_term_id: 1)
9
+ .and_return("id" => 1)
10
+
11
+ expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
12
+
13
+ CanvasSync::Jobs::SyncAssignmentsJob.perform_now({ jobs: [], global_options: { term_id: 1 } }, {})
14
+ end
15
+ end
16
+
17
+ context "no term id is specified" do
18
+ it "enqueues a ReportStarter for the proserv_assignment_export_csv for all terms" do
19
+ expect_any_instance_of(Bearcat::Client).to receive(:start_report)
20
+ .with("self", "proserv_assignment_export_csv", {})
21
+ .and_return("id" => 1)
22
+
23
+ expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
24
+
25
+ CanvasSync::Jobs::SyncAssignmentsJob.perform_now({ jobs: [], global_options: {} }, {})
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Assignment, type: :model do
4
+ let(:subject) { FactoryGirl.create(:assignment) }
5
+
6
+ describe "validations" do
7
+ it { should validate_presence_of(:canvas_assignment_id) }
8
+ it { should validate_uniqueness_of(:canvas_assignment_id) }
9
+ end
10
+
11
+ describe "associations" do
12
+ describe "context" do
13
+ let!(:other_course) { FactoryGirl.create(:course) }
14
+ let!(:matching_course) { FactoryGirl.create(:course) }
15
+
16
+ before do
17
+ subject.update_attributes(context_type: "Course", context_id: matching_course.canvas_course_id)
18
+ end
19
+
20
+ it "should belong to courses where the context_type is Course and context_id is the canvas_course_id" do
21
+ expect(subject.context).to eq(matching_course)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -26,5 +26,10 @@ RSpec.describe Course, type: :model do
26
26
  .with_primary_key(:canvas_course_id)
27
27
  .with_foreign_key(:canvas_course_id)
28
28
  end
29
+
30
+ it do
31
+ should have_many(:assignments)
32
+ .with_primary_key(:canvas_course_id)
33
+ end
29
34
  end
30
35
  end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe CanvasSync::Processors::AssignmentsProcessor do
4
+ let(:subject) { CanvasSync::Processors::AssignmentsProcessor }
5
+
6
+ describe "#process" do
7
+ it "inserts assignments" do
8
+ expect {
9
+ subject.process("spec/support/fixtures/reports/assignments.csv", {})
10
+ }.to change { Assignment.count }.by(2)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
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 Assignment < ApplicationRecord
10
+ validates :canvas_assignment_id, uniqueness: true, presence: true
11
+ belongs_to :context, polymorphic: true, optional: true, primary_key: :canvas_course_id
12
+ end
@@ -11,4 +11,5 @@ class Course < ApplicationRecord
11
11
  belongs_to :term, foreign_key: :canvas_term_id, primary_key: :canvas_term_id, optional: true
12
12
  has_many :enrollments, primary_key: :canvas_course_id, foreign_key: :canvas_course_id
13
13
  has_many :sections, primary_key: :canvas_course_id, foreign_key: :canvas_course_id
14
+ has_many :assignments, as: :context, primary_key: :canvas_course_id
14
15
  end
@@ -0,0 +1,37 @@
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 CreateAssignments < ActiveRecord::Migration[5.1]
10
+ def change
11
+ create_table :assignments do |t|
12
+ t.bigint :canvas_assignment_id, null: false
13
+ t.string :title
14
+ t.text :description
15
+ t.datetime :due_at
16
+ t.datetime :unlock_at
17
+ t.datetime :lock_at
18
+ t.integer :points_possible
19
+ t.integer :min_score
20
+ t.integer :max_score
21
+ t.integer :mastery_score
22
+ t.string :grading_type
23
+ t.string :submission_types
24
+ t.string :workflow_state
25
+ t.integer :context_id
26
+ t.string :context_type
27
+ t.integer :assignment_group_id
28
+ t.integer :grading_scheme_id
29
+ t.integer :grading_standard_id
30
+
31
+ t.timestamps
32
+ end
33
+
34
+ add_index :assignments, :canvas_assignment_id, unique: true
35
+ add_index :assignments, [:context_id, :context_type]
36
+ end
37
+ end