canvas_sync 0.3.11 → 0.3.12

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 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