canvas_sync 0.17.32 → 0.17.35

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: ac101dc1c7a2d590408677aac25218ac20b762d993413c57ae9f8164b50fb3ad
4
- data.tar.gz: c1d4785903974a78e8efc0612e5b36b0c342c6fb8bcfb615616c1e6002cb2186
3
+ metadata.gz: 43e293e4d64336d70983fbf6eedffb1279252c7d95dfe7a525aa1fa2da5f5463
4
+ data.tar.gz: b13c557e206b4ea989ff962ad385b0fef0862e67a07626eb8a661faae8c96fd2
5
5
  SHA512:
6
- metadata.gz: 61f0685f874a9476d8130923b191e7ee1389fcf1cd7374f7b482c11c1e073b30a69796f43b02894cfd37800f7d2240e52d5e48291e8b0f8f8c3698d4f3e84938
7
- data.tar.gz: d2a76163cf0a26ba32a96811c1d9e5ac63b6cc7bb23255a27416562e71bd25ee7ae1d57c0d8b21c8043701c9f76eed219469cf48c82883d68d403f938d4f6b0a
6
+ metadata.gz: 1866a0aafdc8eac4471c5e498055a64690f99982218d06a0ea14ac5ad8a496df1db6add14012d967a8de61efcdced32a1ec14aa7d5dc07c2a0299dc837cd6f0e
7
+ data.tar.gz: e16462ec03aa1a207871ab2dee9d0075a349aa09aaa7c8014833e9c4f3abe684a62e124fbdc5a76bd5340b913add521ec4304eae0f449b95c624358c4504c8f3
@@ -88,7 +88,7 @@ module CanvasSync::Concerns
88
88
  end
89
89
 
90
90
  def unlink_column(key)
91
- @map_def.delete(key)
91
+ @map_def[:report_columns].delete(key)
92
92
  end
93
93
 
94
94
  def link_column(m, type: nil, &blk)
@@ -29,27 +29,46 @@ module CanvasSync
29
29
  }
30
30
  }
31
31
 
32
+ initializer 'canvas_sync.global_methods' do
33
+ next if defined?(canvas_sync_client)
34
+
35
+ require 'panda_pal'
36
+
37
+ def canvas_sync_client(account_id = nil)
38
+ Bearcat::Client.new(
39
+ prefix: current_organization.canvas_url,
40
+ token: current_organization.canvas_api_token,
41
+ master_rate_limit: (Rails.env.production? && !!defined?(Redis) && ENV['REDIS_URL'].present?),
42
+ )
43
+ end
44
+ rescue LoadError
45
+ end
46
+
32
47
  initializer :integrate_pandapal do
33
48
  require 'panda_pal'
34
49
 
35
- if PandaPal::Organization.respond_to?(:scheduled_task)
36
- if PandaPal::Organization.respond_to?(:define_setting)
37
- PandaPal::Organization.define_setting(:canvas_sync, {
38
- type: 'Hash',
39
- required: false,
40
- properties: {
41
- job_log_retention: { **RETENTION_TYPE },
42
- sync_batch_retention: { **RETENTION_TYPE },
43
- }
44
- })
45
- end
50
+ Rails.application.reloader.to_prepare do
51
+ if PandaPal::Organization.respond_to?(:scheduled_task)
52
+ if PandaPal::Organization.respond_to?(:define_setting)
53
+ PandaPal::Organization.define_setting(:canvas_sync, {
54
+ type: 'Hash',
55
+ required: false,
56
+ properties: {
57
+ job_log_retention: { **RETENTION_TYPE },
58
+ sync_batch_retention: { **RETENTION_TYPE },
59
+ }
60
+ })
61
+ end
46
62
 
47
- PandaPal::Organization.scheduled_task '0 0 3 * * *', :clean_canvas_sync_logs do
48
- job_log_retention = ChronicDuration.parse(settings.dig(:canvas_sync, :job_log_retention) || '3 months', keep_zero: true).seconds.ago
49
- JobLog.where('updated_at < ?', job_log_retention).delete_all
63
+ unless PandaPal::Organization.task_scheduled?(:clean_canvas_sync_logs)
64
+ PandaPal::Organization.scheduled_task '0 0 3 * * *', :clean_canvas_sync_logs do
65
+ job_log_retention = ChronicDuration.parse(settings.dig(:canvas_sync, :job_log_retention) || '3 months', keep_zero: true).seconds.ago
66
+ JobLog.where('updated_at < ?', job_log_retention).delete_all
50
67
 
51
- sync_batch_retention = ChronicDuration.parse(settings.dig(:canvas_sync, :sync_batch_retention) || '6 months', keep_zero: true).seconds.ago
52
- SyncBatch.where('updated_at < ?', sync_batch_retention).delete_all
68
+ sync_batch_retention = ChronicDuration.parse(settings.dig(:canvas_sync, :sync_batch_retention) || '6 months', keep_zero: true).seconds.ago
69
+ SyncBatch.where('updated_at < ?', sync_batch_retention).delete_all
70
+ end
71
+ end
53
72
  end
54
73
  end
55
74
  rescue LoadError
@@ -0,0 +1,30 @@
1
+ # <%= autogenerated_migration_warning %>
2
+
3
+ class CreateLearningOutcomes < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :learning_outcomes do |t|
6
+ t.bigint :canvas_id, null: false
7
+ t.integer :canvas_context_id
8
+ t.string :canvas_context_type
9
+ t.string :name
10
+ t.string :friendly_name
11
+ t.string :workflow_state
12
+ t.datetime :canvas_created_at
13
+ t.datetime :canvas_updated_at
14
+ t.string :migration_id
15
+ t.string :vendor_guid
16
+ t.string :low_grade
17
+ t.string :high_grade
18
+ t.string :calculation_method
19
+ t.string :calculation_int
20
+ t.integer :outcome_import_id
21
+ t.integer :root_account_ids, array: true, default: []
22
+ t.text :description
23
+
24
+ t.timestamps
25
+ end
26
+
27
+ add_index :learning_outcomes, :canvas_id, unique: true
28
+ add_index :learning_outcomes, [:canvas_context_id, :canvas_context_type], name: "index_learning_outcomes_on_context"
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # # <%= autogenerated_migration_warning %>
4
+
5
+ class LearningOutcome < ApplicationRecord
6
+ include CanvasSync::Record
7
+ include CanvasSync::Concerns::ApiSyncable
8
+
9
+ belongs_to :context, polymorphic: true, optional: true, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
10
+
11
+ api_syncable({
12
+ canvas_id: :id,
13
+ canvas_context_id: :context_id,
14
+ canvas_context_type: :context_type,
15
+ name: :title,
16
+ friendly_name: :display_name,
17
+ vendor_guid: :vendor_guid,
18
+ calculation_method: :calculation_method,
19
+ calculation_int: :calculation_int,
20
+ description: :description
21
+ }, ->(api) { api.get("/api/v1/outcomes/#{canvas_id}") })
22
+ end
@@ -453,6 +453,23 @@ module CanvasSync
453
453
  end
454
454
  end
455
455
 
456
+ def uget(key)
457
+ Batch.redis do |r|
458
+ case r.type(key)
459
+ when 'string'
460
+ r.get(key)
461
+ when 'list'
462
+ r.lrange(key, 0, -1)
463
+ when 'hash'
464
+ r.hgetall(key)
465
+ when 'set'
466
+ r.smembers(key)
467
+ when 'zset'
468
+ r.smembers(key, 0, -1)
469
+ end
470
+ end
471
+ end
472
+
456
473
  def method_missing(method_name, *arguments, &block)
457
474
  Batch.redis do |r|
458
475
  r.send(method_name, *arguments, &block)
@@ -27,7 +27,7 @@ module CanvasSync
27
27
 
28
28
  if clazz && object = Object.const_get(clazz)
29
29
  target = target == :instance ? object.new : object
30
- if target.respond_to?(method)
30
+ if target.respond_to?(method, true)
31
31
  target.send(method, status, opts)
32
32
  else
33
33
  Batch.logger.warn("Invalid callback method #{definition} - #{target.to_s} does not respond to #{method}")
@@ -44,7 +44,7 @@ module CanvasSync
44
44
  wrapper.on(checkin_event, "#{self.class.to_s}.job_checked_in", pool_id: pid)
45
45
  wrapper.jobs {}
46
46
 
47
- job_desc = job_desc.with_indifferent_access
47
+ job_desc = job_desc.symbolize_keys
48
48
  job_desc = job_desc.merge!(
49
49
  job: job_desc[:job].to_s,
50
50
  pool_wrapper_batch: wrapper.bid,
@@ -149,7 +149,7 @@ module CanvasSync
149
149
  if current_count < limit
150
150
  job_desc = pop_job_from_pool
151
151
  if job_desc.present?
152
- Batch.new(job_desc['pool_wrapper_batch']).jobs do
152
+ Batch.new(job_desc[:pool_wrapper_batch]).jobs do
153
153
  ChainBuilder.enqueue_job(job_desc)
154
154
  end
155
155
  jobs_added += 1
@@ -170,7 +170,7 @@ module CanvasSync
170
170
  def push_job_to_pool(job_desc)
171
171
  jobs_key = "#{redis_key}-jobs"
172
172
  # This allows duplicate jobs when a Redis Set is used
173
- job_desc['_pool_random_key_'] = SecureRandom.urlsafe_base64(10)
173
+ job_desc[:_pool_random_key_] = SecureRandom.urlsafe_base64(10)
174
174
  job_json = JSON.unparse(ActiveJob::Arguments.serialize([job_desc]))
175
175
  order = self.order
176
176
 
@@ -204,7 +204,7 @@ module CanvasSync
204
204
 
205
205
  return nil unless job_json.present?
206
206
 
207
- ActiveJob::Arguments.deserialize(JSON.parse(job_json))[0]
207
+ ActiveJob::Arguments.deserialize(JSON.parse(job_json))[0]&.symbolize_keys
208
208
  end
209
209
 
210
210
  def self.redis(&blk)
@@ -12,7 +12,7 @@ module CanvasSync::JobBatches::Sidekiq
12
12
  end
13
13
 
14
14
  def drain_zset(key)
15
- items, _ = Batch.redis do |r|
15
+ items, _ = CanvasSync::JobBatches::Batch.redis do |r|
16
16
  r.multi do |r|
17
17
  r.zrange(key, 0, -1)
18
18
  r.zremrangebyrank(key, 0, -1)
@@ -10,6 +10,16 @@
10
10
  <th colspan="2" scope=row><%= t('Batch') %></td>
11
11
  <td><%= @batch.bid %></td>
12
12
  </tr>
13
+ <tr>
14
+ <th colspan="2" scope=row><%= t('Parent') %></td>
15
+ <td>
16
+ <% if @batch.parent_bid.present? %>
17
+ <a href="<%= root_path %>batches/<%= @batch.parent_bid %>"><%= @batch.parent_bid %></a>
18
+ <% else %>
19
+ ROOT
20
+ <% end %>
21
+ </td>
22
+ </tr>
13
23
  <tr>
14
24
  <th colspan="2" scope=row><%= t('Started') %></td>
15
25
  <td><%= safe_relative_time(@batch.created_at.to_f) %></td>
@@ -509,3 +509,58 @@ content_migrations:
509
509
  canvas_root_account_id:
510
510
  database_column_name: canvas_root_account_id
511
511
  type: integer
512
+
513
+ learning_outcomes:
514
+ conflict_target: learning_outcome_id
515
+ report_columns:
516
+ learning_outcome_id:
517
+ database_column_name: canvas_id
518
+ type: integer
519
+ context_id:
520
+ database_column_name: canvas_context_id
521
+ type: integer
522
+ context_type:
523
+ database_column_name: canvas_context_type
524
+ type: string
525
+ name:
526
+ database_column_name: name
527
+ type: string
528
+ friendly_name:
529
+ database_column_name: friendly_name
530
+ type: string
531
+ workflow_state:
532
+ database_column_name: workflow_state
533
+ type: string
534
+ created_at:
535
+ database_column_name: canvas_created_at
536
+ type: datetime
537
+ updated_at:
538
+ database_column_name: canvas_updated_at
539
+ type: datetime
540
+ migration_id:
541
+ database_column_name: migration_id
542
+ type: string
543
+ vendor_guid:
544
+ database_column_name: vendor_guid
545
+ type: string
546
+ low_grade:
547
+ database_column_name: low_grade
548
+ type: string
549
+ high_grade:
550
+ database_column_name: high_grade
551
+ type: string
552
+ calculation_method:
553
+ database_column_name: calculation_method
554
+ type: string
555
+ calculation_int:
556
+ database_column_name: calculation_int
557
+ type: integer
558
+ outcome_import_id:
559
+ database_column_name: outcome_import_id
560
+ type: integer
561
+ root_account_ids:
562
+ database_column_name: root_account_ids
563
+ type: integer
564
+ description:
565
+ database_column_name: description
566
+ type: string
@@ -116,6 +116,13 @@ module CanvasSync
116
116
  def bulk_process_group_membership(report_file_path)
117
117
  do_bulk_import(report_file_path, GroupMembership, options: @options)
118
118
  end
119
+
120
+ def bulk_process_learning_outcomes(report_file_path)
121
+ do_bulk_import(report_file_path, LearningOutcome, options: @options) do |row|
122
+ row[:root_account_ids] = JSON.parse row[:root_account_ids]
123
+ row
124
+ end
125
+ end
119
126
  end
120
127
  end
121
128
  end
@@ -12,14 +12,15 @@ module CanvasSync
12
12
  model.try(:get_sync_mapping, key) || mapping[key || CanvasSync::Concerns::SyncMapping::Mapping.normalize_model_name(model)]
13
13
  end
14
14
 
15
- def do_bulk_import(report_file_path, model, options: {}, mapping_key: nil)
15
+ def do_bulk_import(report_file_path, model, options: {}, mapping_key: nil, &blk)
16
16
  m = mapping_for(model, mapping_key)
17
17
  CanvasSync::Importers::BulkImporter.import(
18
18
  report_file_path,
19
19
  m[:report_columns],
20
20
  model,
21
21
  m[:conflict_target],
22
- import_args: options
22
+ import_args: options,
23
+ &blk
23
24
  )
24
25
  end
25
26
  end
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.17.32".freeze
2
+ VERSION = "0.17.35".freeze
3
3
  end
data/lib/canvas_sync.rb CHANGED
@@ -45,6 +45,7 @@ module CanvasSync
45
45
  grading_periods
46
46
  grading_period_groups
47
47
  content_migrations
48
+ learning_outcomes
48
49
  ].freeze
49
50
 
50
51
  SUPPORTED_TERM_SCOPE_MODELS = %w[
@@ -104,6 +104,12 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
104
104
  expect(obj.workflow_state).to eq 'active'
105
105
  end
106
106
 
107
+ it 'processes learning_outcomes' do
108
+ expect {
109
+ subject.process('spec/support/fixtures/reports/learning_outcomes.csv', { models: ['learning_outcomes'] }, 1)
110
+ }.to change { LearningOutcome.count }.by(2)
111
+ end
112
+
107
113
  it 'model with composite key behaves as expected' do
108
114
  expect {
109
115
  subject.process('spec/support/fixtures/reports/user_observers.csv', { models: ['user_observers'] }, 1)
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # # #
4
+ # AUTO GENERATED MIGRATION
5
+ # This migration was auto generated by the CanvasSync Gem.
6
+ # You can add new columns to this table, but removing or
7
+ # re-naming ones created here may break Canvas Syncing.
8
+ #
9
+
10
+
11
+ class LearningOutcome < ApplicationRecord
12
+ include CanvasSync::Record
13
+ include CanvasSync::Concerns::ApiSyncable
14
+
15
+ belongs_to :context, polymorphic: true, optional: true, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
16
+
17
+ api_syncable({
18
+ canvas_id: :id,
19
+ canvas_context_id: :context_id,
20
+ canvas_context_type: :context_type,
21
+ name: :title,
22
+ friendly_name: :display_name,
23
+ vendor_guid: :vendor_guid,
24
+ calculation_method: :calculation_method,
25
+ calculation_int: :calculation_int,
26
+ description: :description
27
+ }, ->(api) { api.get("/api/v1/outcomes/#{canvas_id}") })
28
+ end
@@ -0,0 +1,36 @@
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 CreateLearningOutcomes < ActiveRecord::Migration[5.1]
10
+ def change
11
+ create_table :learning_outcomes do |t|
12
+ t.bigint :canvas_id, null: false
13
+ t.integer :canvas_context_id
14
+ t.string :canvas_context_type
15
+ t.string :name
16
+ t.string :friendly_name
17
+ t.string :workflow_state
18
+ t.datetime :canvas_created_at
19
+ t.datetime :canvas_updated_at
20
+ t.string :migration_id
21
+ t.string :vendor_guid
22
+ t.string :low_grade
23
+ t.string :high_grade
24
+ t.string :calculation_method
25
+ t.string :calculation_int
26
+ t.integer :outcome_import_id
27
+ t.integer :root_account_ids, array: true, default: []
28
+ t.text :description
29
+
30
+ t.timestamps
31
+ end
32
+
33
+ add_index :learning_outcomes, :canvas_id, unique: true
34
+ add_index :learning_outcomes, [:canvas_context_id, :canvas_context_type], name: "index_learning_outcomes_on_context"
35
+ end
36
+ end
@@ -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: 2022_03_08_072643) do
13
+ ActiveRecord::Schema.define(version: 2022_07_12_210559) do
14
14
 
15
15
  # These are extensions that must be enabled in order to support this database
16
16
  enable_extension "plpgsql"
@@ -246,6 +246,30 @@ ActiveRecord::Schema.define(version: 2022_03_08_072643) do
246
246
  t.index ["canvas_id"], name: "index_groups_on_canvas_id", unique: true
247
247
  end
248
248
 
249
+ create_table "learning_outcomes", force: :cascade do |t|
250
+ t.bigint "canvas_id", null: false
251
+ t.integer "canvas_context_id"
252
+ t.string "canvas_context_type"
253
+ t.string "name"
254
+ t.string "friendly_name"
255
+ t.string "workflow_state"
256
+ t.datetime "canvas_created_at"
257
+ t.datetime "canvas_updated_at"
258
+ t.string "migration_id"
259
+ t.string "vendor_guid"
260
+ t.string "low_grade"
261
+ t.string "high_grade"
262
+ t.string "calculation_method"
263
+ t.string "calculation_int"
264
+ t.integer "outcome_import_id"
265
+ t.integer "root_account_ids", default: [], array: true
266
+ t.text "description"
267
+ t.datetime "created_at", null: false
268
+ t.datetime "updated_at", null: false
269
+ t.index ["canvas_context_id", "canvas_context_type"], name: "index_learning_outcomes_on_context"
270
+ t.index ["canvas_id"], name: "index_learning_outcomes_on_canvas_id", unique: true
271
+ end
272
+
249
273
  create_table "pseudonyms", force: :cascade do |t|
250
274
  t.bigint "canvas_id", null: false
251
275
  t.bigint "canvas_user_id"
@@ -0,0 +1,3 @@
1
+ learning_outcome_id,context_id,context_type,name,friendly_name,workflow_state,created_at,updated_at,migration_id,vendor_guid,low_grade,high_grade,calculation_method,calculation_int,outcome_import_id,root_account_ids,description
2
+ 1,1,Course,Course Outcome,"",active,2021-08-12 21:11:40 UTC,2021-08-13 01:05:40 UTC,,,,,decaying_average,65,,[1],<p>description</p>
3
+ 2,1,Account,Account Outcome,Friendly Name,active,2021-08-12 21:11:40 UTC,2021-08-13 01:05:40 UTC,,,,,decaying_average,65,,[1],<p>description</p>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canvas_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.32
4
+ version: 0.17.35
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Collings
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-26 00:00:00.000000000 Z
11
+ date: 2022-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -390,6 +390,7 @@ files:
390
390
  - lib/canvas_sync/generators/templates/migrations/create_grading_periods.rb
391
391
  - lib/canvas_sync/generators/templates/migrations/create_group_memberships.rb
392
392
  - lib/canvas_sync/generators/templates/migrations/create_groups.rb
393
+ - lib/canvas_sync/generators/templates/migrations/create_learning_outcomes.rb
393
394
  - lib/canvas_sync/generators/templates/migrations/create_pseudonyms.rb
394
395
  - lib/canvas_sync/generators/templates/migrations/create_roles.rb
395
396
  - lib/canvas_sync/generators/templates/migrations/create_sections.rb
@@ -410,6 +411,7 @@ files:
410
411
  - lib/canvas_sync/generators/templates/models/grading_period_group.rb
411
412
  - lib/canvas_sync/generators/templates/models/group.rb
412
413
  - lib/canvas_sync/generators/templates/models/group_membership.rb
414
+ - lib/canvas_sync/generators/templates/models/learning_outcome.rb
413
415
  - lib/canvas_sync/generators/templates/models/pseudonym.rb
414
416
  - lib/canvas_sync/generators/templates/models/role.rb
415
417
  - lib/canvas_sync/generators/templates/models/section.rb
@@ -551,6 +553,7 @@ files:
551
553
  - spec/dummy/app/models/grading_period_group.rb
552
554
  - spec/dummy/app/models/group.rb
553
555
  - spec/dummy/app/models/group_membership.rb
556
+ - spec/dummy/app/models/learning_outcome.rb
554
557
  - spec/dummy/app/models/pseudonym.rb
555
558
  - spec/dummy/app/models/role.rb
556
559
  - spec/dummy/app/models/section.rb
@@ -620,6 +623,7 @@ files:
620
623
  - spec/dummy/db/migrate/20210907233330_create_grading_periods.rb
621
624
  - spec/dummy/db/migrate/20211001184920_create_grading_period_groups.rb
622
625
  - spec/dummy/db/migrate/20220308072643_create_content_migrations.rb
626
+ - spec/dummy/db/migrate/20220712210559_create_learning_outcomes.rb
623
627
  - spec/dummy/db/schema.rb
624
628
  - spec/dummy/log/development.log
625
629
  - spec/dummy/log/test.log
@@ -671,6 +675,7 @@ files:
671
675
  - spec/support/fixtures/reports/grading_periods.csv
672
676
  - spec/support/fixtures/reports/group_memberships.csv
673
677
  - spec/support/fixtures/reports/groups.csv
678
+ - spec/support/fixtures/reports/learning_outcomes.csv
674
679
  - spec/support/fixtures/reports/provisioning_csv
675
680
  - spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
676
681
  - spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
@@ -697,7 +702,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
697
702
  - !ruby/object:Gem::Version
698
703
  version: '0'
699
704
  requirements: []
700
- rubygems_version: 3.0.3
705
+ rubygems_version: 3.1.6
701
706
  signing_key:
702
707
  specification_version: 4
703
708
  summary: Gem for generating Canvas models and migrations and syncing data from Canvas
@@ -759,6 +764,7 @@ test_files:
759
764
  - spec/dummy/app/models/grading_period_group.rb
760
765
  - spec/dummy/app/models/group.rb
761
766
  - spec/dummy/app/models/group_membership.rb
767
+ - spec/dummy/app/models/learning_outcome.rb
762
768
  - spec/dummy/app/models/pseudonym.rb
763
769
  - spec/dummy/app/models/role.rb
764
770
  - spec/dummy/app/models/section.rb
@@ -828,6 +834,7 @@ test_files:
828
834
  - spec/dummy/db/migrate/20210907233330_create_grading_periods.rb
829
835
  - spec/dummy/db/migrate/20211001184920_create_grading_period_groups.rb
830
836
  - spec/dummy/db/migrate/20220308072643_create_content_migrations.rb
837
+ - spec/dummy/db/migrate/20220712210559_create_learning_outcomes.rb
831
838
  - spec/dummy/db/schema.rb
832
839
  - spec/dummy/log/development.log
833
840
  - spec/dummy/log/test.log
@@ -879,6 +886,7 @@ test_files:
879
886
  - spec/support/fixtures/reports/grading_periods.csv
880
887
  - spec/support/fixtures/reports/group_memberships.csv
881
888
  - spec/support/fixtures/reports/groups.csv
889
+ - spec/support/fixtures/reports/learning_outcomes.csv
882
890
  - spec/support/fixtures/reports/provisioning_csv
883
891
  - spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
884
892
  - spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv