Fix read-only error on posting submissions

With post policies active, we update an assignment's muted status
dynamically based on whether it has any remaining unposted submissions.
When the last student in a course took a quiz, we were attempting to set
the assignment's muted status to false, but another piece of code
attempted to save changes to the associated quiz, resulting in an error
to the effect that the quiz was marked as read-only. When we're only
muting/unmuting by way of posting/hiding submissions, don't attempt to
save changes to the quiz.

fixes GRADE-2306

Test plan:
- Have new gradebook/post policies enabled
- Have a course with a small number of students
- Create a quiz
  - Take the quiz with all but one student
  - As the last student, take the quiz (to switch the assignment's muted
    from true to false)
  - It should complete successfully and not cause an error

Change-Id: I8c97d02033f86158d66ce98b7ad9b32ce8edb43c
Reviewed-on: https://gerrit.instructure.com/201553
Reviewed-by: Derek Bender <djbender@instructure.com>
Reviewed-by: Jeremy Neander <jneander@instructure.com>
Tested-by: Jenkins
Product-Review: Keith Garner <kgarner@instructure.com>
QA-Review: James Butters <jbutters@instructure.com>
This commit is contained in:
Adrian Packel 2019-07-17 10:58:22 -05:00
parent 49bd2bb55c
commit 9972fe7428
3 changed files with 45 additions and 3 deletions

View File

@ -57,7 +57,7 @@ class Assignment < ActiveRecord::Base
anonymous_instructor_annotations
].freeze
attr_accessor :previous_id, :copying, :user_submitted
attr_accessor :previous_id, :copying, :user_submitted, :grade_posting_in_progress
attr_reader :assignment_changed
attr_writer :updating_user
@ -921,7 +921,9 @@ class Assignment < ActiveRecord::Base
end
def update_submittable
return true if self.deleted?
# If we're updating the assignment's muted status as part of posting
# grades, don't bother doing this
return true if self.deleted? || grade_posting_in_progress
if self.submission_types == "online_quiz" && @saved_by != :quiz
quiz = Quizzes::Quiz.where(assignment_id: self).first || self.context.quizzes.build
quiz.assignment_id = self.id

View File

@ -128,6 +128,14 @@ module Mutable
# With post policies active, an assignment is considered "muted" if it has any
# unposted submissions.
has_unposted_submissions = submissions.active.unposted.exists?
update!(muted: has_unposted_submissions) if muted? != has_unposted_submissions
if muted? != has_unposted_submissions
# Set grade_posting_in_progress so we don't attempt to save changes to
# this assignment's associated quiz/discussion topic/whatever in the
# process of muting
self.grade_posting_in_progress = true
update!(muted: has_unposted_submissions)
self.grade_posting_in_progress = false
end
end
end

View File

@ -316,6 +316,38 @@ describe Assignment do
end
end
end
describe "#update_submittable" do
before(:each) do
Timecop.freeze(1.day.ago) do
assignment_quiz([], course: @course)
end
end
let(:assignment) { @assignment }
let(:quiz) { @quiz }
context "for an assignment with an associated quiz" do
it "updates the quiz when the assignment is updated normally" do
expect {
assignment.update!(title: "a new and even better title")
}.to change { quiz.reload.updated_at }
end
context "when post policies are enabled" do
before(:each) do
@course.enable_feature!(:new_gradebook)
PostPolicy.enable_feature!
end
it "does not attempt to update the quiz when posting/hiding changes the assignment's muted status" do
expect {
assignment.hide_submissions(submission_ids: assignment.submissions.pluck(:id))
}.not_to change { quiz.reload.updated_at }
end
end
end
end
end
describe "scope: expects_submissions" do