Reduce SQL queries for score runs

Fixes CODEOCEAN-JR
This commit is contained in:
Sebastian Serth
2023-03-14 00:47:02 +01:00
parent 4a28d4c5a3
commit 939b31967f
4 changed files with 14 additions and 6 deletions

View File

@ -3,13 +3,20 @@
module FileParameters
def reject_illegal_file_attributes(exercise, params)
if exercise && params
# We only want to load the files once, to avoid multiple database queries.
# Further, we use `unscope` to avoid that the `order` scope is applied
files = CodeOcean::File.unscope(:order).where(id: params.values.pluck(:file_id))
params.reject do |_, file_attributes|
file = CodeOcean::File.find_by(id: file_attributes[:file_id])
# This mechanism seems cumbersome, but we cannot use an index here.
# The ordering of the files is not guaranteed to be the same as the ordering of the file attributes.
file = files.find {|f| f.id == file_attributes[:file_id].to_i }
next true if file.nil? || file.hidden || file.read_only
# avoid that public files from other contexts can be created
# `next` is similar to an early return and will proceed with the next iteration of the loop
next true if file.context_type == 'Exercise' && file.context != exercise
next true if file.context_type == 'Submission' && file.context.user != current_user
next true if file.context_type == 'Exercise' && file.context_id != exercise.id
next true if file.context_type == 'Submission' && (file.context.user_id != current_user.id || file.context.user_type != current_user.class.name)
next true if file.context_type == 'CommunitySolution' && controller_name != 'community_solutions'
false

View File

@ -12,8 +12,9 @@ module SubmissionParameters
end
submission_params = merge_user(submission_params)
files_attributes = submission_params[:files_attributes]
exercise = Exercise.find_by(id: submission_params[:exercise_id])
exercise = @exercise || Exercise.find_by(id: submission_params[:exercise_id])
submission_params[:files_attributes] = reject_illegal_file_attributes(exercise, files_attributes)
submission_params[:exercise] = exercise
submission_params
end
private :submission_params

View File

@ -517,7 +517,7 @@ class Exercise < ApplicationRecord
0
end
else
files.teacher_defined_assessments.sum(:weight)
@maximum_score ||= files.teacher_defined_assessments.sum(:weight)
end
end

View File

@ -12,7 +12,7 @@ describe FileParameters do
describe '#reject_illegal_file_attributes!' do
def file_accepted?(file)
files = [[0, attributes_for(:file, context: hello_world, file_id: file.id)]]
files = {'0': attributes_for(:file, context: hello_world, file_id: file.id)}
filtered_files = controller.send(:reject_illegal_file_attributes, hello_world, files)
files.eql?(filtered_files)
end