Reduce SQL queries for score runs
Fixes CODEOCEAN-JR
This commit is contained in:
@ -3,13 +3,20 @@
|
|||||||
module FileParameters
|
module FileParameters
|
||||||
def reject_illegal_file_attributes(exercise, params)
|
def reject_illegal_file_attributes(exercise, params)
|
||||||
if 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|
|
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
|
next true if file.nil? || file.hidden || file.read_only
|
||||||
# avoid that public files from other contexts can be created
|
# 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` 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 == 'Exercise' && file.context_id != exercise.id
|
||||||
next true if file.context_type == 'Submission' && file.context.user != current_user
|
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'
|
next true if file.context_type == 'CommunitySolution' && controller_name != 'community_solutions'
|
||||||
|
|
||||||
false
|
false
|
||||||
|
@ -12,8 +12,9 @@ module SubmissionParameters
|
|||||||
end
|
end
|
||||||
submission_params = merge_user(submission_params)
|
submission_params = merge_user(submission_params)
|
||||||
files_attributes = submission_params[:files_attributes]
|
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[:files_attributes] = reject_illegal_file_attributes(exercise, files_attributes)
|
||||||
|
submission_params[:exercise] = exercise
|
||||||
submission_params
|
submission_params
|
||||||
end
|
end
|
||||||
private :submission_params
|
private :submission_params
|
||||||
|
@ -517,7 +517,7 @@ class Exercise < ApplicationRecord
|
|||||||
0
|
0
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
files.teacher_defined_assessments.sum(:weight)
|
@maximum_score ||= files.teacher_defined_assessments.sum(:weight)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ describe FileParameters do
|
|||||||
|
|
||||||
describe '#reject_illegal_file_attributes!' do
|
describe '#reject_illegal_file_attributes!' do
|
||||||
def file_accepted?(file)
|
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)
|
filtered_files = controller.send(:reject_illegal_file_attributes, hello_world, files)
|
||||||
files.eql?(filtered_files)
|
files.eql?(filtered_files)
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user