Skip to content

Commit db0bf46

Browse files
ccutrerlukfugl
authored andcommitted
clean up course account associations
closes CNVS-3417 test plan: * after the migrations are run, ensure that every section has at least one entry in CourseAccountAssociations in the database * smoke test SIS imports Change-Id: I261cad633788efbf4b0c64db34436ef695856fee Reviewed-on: https://gerrit.instructure.com/17256 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jacob Fugal <jacob@instructure.com>
1 parent e9ee3df commit db0bf46

18 files changed

Lines changed: 180 additions & 148 deletions

app/models/course.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (C) 2011 - 2012 Instructure, Inc.
2+
# Copyright (C) 2011 - 2013 Instructure, Inc.
33
#
44
# This file is part of Canvas.
55
#
@@ -334,16 +334,17 @@ def self.update_account_associations(courses_or_course_ids, opts = {})
334334
course_ids = courses.map(&:id)
335335
else
336336
course_ids = courses_or_course_ids
337-
courses = Course.find(:all, :conditions => {:id => course_ids }, :include => { :course_sections => :nonxlist_course })
337+
courses = Course.find(:all, :conditions => {:id => course_ids }, :include => { :course_sections => [:course, :nonxlist_course] })
338338
end
339339
course_ids_to_update_user_account_associations = []
340340
CourseAccountAssociation.transaction do
341341
current_associations = {}
342342
to_delete = []
343343
CourseAccountAssociation.find(:all, :conditions => { :course_id => course_ids }).each do |aa|
344344
key = [aa.course_section_id, aa.account_id]
345-
# duplicates
346345
current_course_associations = current_associations[aa.course_id] ||= {}
346+
# duplicates. the unique index prevents these now, but this code
347+
# needs to hang around for the migration itself
347348
if current_course_associations.has_key?(key)
348349
to_delete << aa.id
349350
next
@@ -359,7 +360,7 @@ def self.update_account_associations(courses_or_course_ids, opts = {})
359360
(course.course_sections + [nil]).each do |section|
360361
next if section && !section.active?
361362
section.course = course if section
362-
starting_account_ids = [course.account_id, section.try(:account_id), section.try(:nonxlist_course).try(:account_id)].compact.uniq
363+
starting_account_ids = [course.account_id, section.try(:course).try(:account_id), section.try(:nonxlist_course).try(:account_id)].compact.uniq
363364

364365
account_ids_with_depth = User.calculate_account_associations_from_accounts(starting_account_ids, account_chain_cache).map
365366

@@ -1652,7 +1653,7 @@ def default_section(opts = {})
16521653
section = course_sections.build
16531654
section.default_section = true
16541655
section.course = self
1655-
section.root_account = self.root_account
1656+
section.root_account_id = self.root_account_id
16561657
section.save unless new_record?
16571658
end
16581659
section

app/models/course_section.rb

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (C) 2011 Instructure, Inc.
2+
# Copyright (C) 2011 - 2013 Instructure, Inc.
33
#
44
# This file is part of Canvas.
55
#
@@ -24,7 +24,6 @@ class CourseSection < ActiveRecord::Base
2424
belongs_to :course
2525
belongs_to :nonxlist_course, :class_name => 'Course'
2626
belongs_to :root_account, :class_name => 'Account'
27-
belongs_to :account
2827
has_many :enrollments, :include => :user, :conditions => ['enrollments.workflow_state != ?', 'deleted'], :dependent => :destroy
2928
has_many :all_enrollments, :class_name => 'Enrollment'
3029
has_many :students, :through => :student_enrollments, :source => :user
@@ -98,17 +97,19 @@ def touch_all_enrollments
9897
end
9998

10099
def set_update_account_associations_if_changed
101-
@should_update_account_associations = self.account_id_changed? || self.course_id_changed? || self.nonxlist_course_id_changed?
102-
@should_update_account_associations = false if self.new_record? && self.account_id.nil?
100+
@should_update_account_associations = self.course_id_changed? || self.nonxlist_course_id_changed?
103101
true
104102
end
105103

106104
def update_account_associations_if_changed
107-
send_later_if_production(:update_account_associations) if @should_update_account_associations && !Course.skip_updating_account_associations?
105+
if @should_update_account_associations && !Course.skip_updating_account_associations?
106+
Course.send_later_if_production(:update_account_associations,
107+
[self.course_id, self.course_id_was, self.nonxlist_course_id, self.nonxlist_course_id_was].compact.uniq)
108+
end
108109
end
109110

110111
def update_account_associations
111-
Course.update_account_associations([self.course, self.nonxlist_course].compact)
112+
Course.update_account_associations([self.course_id, self.nonxlist_course_id].compact)
112113
end
113114

114115
def verify_unique_sis_source_id
@@ -128,7 +129,6 @@ def section_code
128129

129130
def infer_defaults
130131
self.root_account_id ||= (self.course.root_account_id rescue nil) || Account.default.id
131-
self.assert_course unless self.course
132132
raise "Course required" unless self.course
133133
self.root_account_id = self.course.root_account_id || Account.default.id
134134
# This is messy, and I hate it.
@@ -160,10 +160,6 @@ def display_name
160160
@section_display_name ||= self.name || self.section_code
161161
end
162162

163-
def assert_course
164-
self.course ||= Course.create!(:name => self.name || self.section_code, :root_account => self.root_account)
165-
end
166-
167163
def move_to_course(course, *opts)
168164
return self if self.course_id == course.id
169165
old_course = self.course

app/models/enrollment.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (C) 2011 - 2012 Instructure, Inc.
2+
# Copyright (C) 2011 - 2013 Instructure, Inc.
33
#
44
# This file is part of Canvas.
55
#
@@ -430,7 +430,7 @@ def associated_user_name
430430

431431
def assert_section
432432
self.course_section ||= self.course.default_section if self.course
433-
self.root_account_id = self.course_section.root_account_id rescue nil
433+
self.root_account_id = self.course.root_account_id rescue nil
434434
end
435435

436436
def infer_privileges

config/initializers/dropped_columns.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (C) 2011 Instructure, Inc.
2+
# Copyright (C) 2011 - 2013 Instructure, Inc.
33
#
44
# This file is part of Canvas.
55
#
@@ -28,7 +28,7 @@ class ActiveRecord::Base
2828
'calendar_events' => %w(calendar_event_repeat_id for_repeat_on),
2929
'content_tags' => %w(sequence_position context_module_association_id),
3030
'conversation_messages' => %w(context_message_id),
31-
'course_sections' => %w(sis_cross_listed_section_id sis_cross_listed_section_sis_batch_id sticky_xlist sis_name students_can_participate_before_start_at section_organization_name long_section_code),
31+
'course_sections' => %w(sis_cross_listed_section_id sis_cross_listed_section_sis_batch_id sticky_xlist sis_name students_can_participate_before_start_at section_organization_name long_section_code account_id),
3232
'courses' => %w(section hidden_tabs sis_name sis_course_code hashtag allow_student_assignment_edits),
3333
'discussion_topics' => %w(authorization_list_id),
3434
'enrollment_terms' => %w(sis_data sis_name),
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class DropAccountIdFromCourseSections < ActiveRecord::Migration
2+
tag :postdeploy
3+
4+
def self.up
5+
remove_column :course_sections, :account_id
6+
end
7+
8+
def self.down
9+
add_column :course_sections, :account_id, :integer, :limit => 8
10+
end
11+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class AddUniqueIndexOnCourseAccountAssociations < ActiveRecord::Migration
2+
tag :predeploy
3+
self.transactional = false
4+
5+
def self.up
6+
# clean up any dups first
7+
course_ids = CourseAccountAssociation.find(:all, :select => 'DISTINCT course_id',
8+
:group => 'course_id, course_section_id, account_id', :having => 'COUNT(*) > 1').map(&:course_id)
9+
Course.update_account_associations(course_ids)
10+
11+
add_index :course_account_associations, [:course_id, :course_section_id, :account_id], :unique => true, :concurrently => true, :name => 'index_caa_on_course_id_and_section_id_and_account_id'
12+
remove_index :course_account_associations, :course_id
13+
end
14+
15+
def self.down
16+
add_index :course_account_associations, :course_id, :concurrently => true
17+
remove_index :course_account_associations, 'index_caa_on_course_id_and_section_id_and_account_id'
18+
end
19+
end
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class RecalculateCourseAccountAssociations < ActiveRecord::Migration
2+
tag :postdeploy
3+
4+
def self.up
5+
# a bug was fixed in Course.update_account_associations; we need to recalculate them all
6+
DataFixup::RecalculateCourseAccountAssociations.send_later_if_production(:run)
7+
end
8+
end

doc/api/sis_csv.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -310,12 +310,6 @@ interface, this is called the SIS ID.</td>
310310
<td>date</td>
311311
<td>The section end date The format should be in ISO 8601: YYYY-MM-DDTHH:MM:SSZ</td>
312312
</tr>
313-
<tr>
314-
<td>account_id</td>
315-
<td>text</td>
316-
<td>The account identifier from accounts.csv, if none is specified the course will be attached
317-
to the root account</td>
318-
</tr>
319313
</table>
320314

321315
<p>If the start_date is set, it will override the course and term start dates. If the end_date is
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module DataFixup::RecalculateCourseAccountAssociations
2+
def self.run
3+
Course.active.scoped(:joins => :root_account, :conditions => "accounts.workflow_state<>'deleted'").find_in_batches do |batch|
4+
Course.send(:with_exclusive_scope) do
5+
Course.update_account_associations(batch)
6+
end
7+
end
8+
end
9+
end

lib/sis/csv/section_importer.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (C) 2011 Instructure, Inc.
2+
# Copyright (C) 2011 - 2013 Instructure, Inc.
33
#
44
# This file is part of Canvas.
55
#
@@ -44,7 +44,7 @@ def process(csv)
4444
end
4545

4646
begin
47-
importer.add_section(row['section_id'], row['course_id'], row['name'], row['status'], start_date, end_date, row['account_id'])
47+
importer.add_section(row['section_id'], row['course_id'], row['name'], row['status'], start_date, end_date)
4848
rescue ImportError => e
4949
add_warning(csv, "#{e}")
5050
end

0 commit comments

Comments
 (0)