From cde9026af3d0204fab156185f0cf100385d78700 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 1 Apr 2026 22:50:38 +0800 Subject: [PATCH 1/4] fix: participants filters and optimized querying for participants table to use preload instead --- app/controllers/courses_controller.rb | 36 +++++++++--------- app/controllers/participants_controller.rb | 38 +++++++++++-------- app/helpers/courses_helper.rb | 30 ++++----------- .../courses/_participants_table.html.erb | 2 +- 4 files changed, 49 insertions(+), 57 deletions(-) diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 827fb9f5..e2355beb 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -7,43 +7,41 @@ class CoursesController < ApplicationController def show authorize @course + # query for all projects_instances, owner_type and owner_id for participants table + @course.projects.includes(project_instances: { enrolment: :user }).load + @projects_by_owner = @course.projects.index_by { |p| [p.owner_type, p.owner_id] } + @student_list = @course.students @description = @course.course_description @lecturers = @course.lecturers - @group_list = @course.grouped? ? @course.project_groups.to_a : [] @lecturer_enrolment = @course.enrolments.find_by(user: current_user, role: :lecturer) @current_user_enrolment = @course.enrolments.find_by(user: current_user) @topic_list = policy_scope(@course.topics, policy_scope_class: TopicPolicy::Scope) @my_topics = @topic_list.where(owner: current_user) - # SET STUDENT PROJECTS - projects_ownerships = @course.projects.approved - .where(owner_type: 'User') - .pluck('owner_id') - - @students_with_projects = @student_list.select do |student| - projects_ownerships.include?(student.id) - end - - @students_without_projects = @student_list.reject do |student| - projects_ownerships.include?(student.id) - end + # set students projects + projects_ownerships = @course.projects.approved.where(owner_type: 'User').pluck('owner_id') - @filtered_group_list = filtered_group_list - @filtered_student_list = filtered_student_list - @my_student_projects = [] - @incoming_proposals = [] + @students_with_projects = @student_list.select { |s| projects_ownerships.include?(s.id) } + @students_without_projects = @student_list.reject { |s| projects_ownerships.include?(s.id) } if @course.grouped? @group = current_user.project_groups.find_by(course: @course) - - @project = (@course.projects.find_by(owner_type: 'ProjectGroup', owner_id: @group.id) if @group) + @project = @projects_by_owner[['ProjectGroup', @group.id]] if @group + @group_list = @course.project_groups.includes(project_group_members: :user).to_a else @group = nil @project = @course.projects.find_by(owner_type: 'User', owner_id: current_user.id) + @group_list = [] end + + @filtered_group_list = filtered_group_list + @filtered_student_list = filtered_student_list + @my_student_projects = [] + @incoming_proposals = [] + @current_status = @project&.current_status || 'not_submitted' if @current_user_enrolment&.coordinator? diff --git a/app/controllers/participants_controller.rb b/app/controllers/participants_controller.rb index 6da93d9b..084a665e 100644 --- a/app/controllers/participants_controller.rb +++ b/app/controllers/participants_controller.rb @@ -1,36 +1,44 @@ class ParticipantsController < ApplicationController def index @course = Course.find(params[:course_id]) - @student_list = @course.students - @group_list = @course.grouped? ? @course.project_groups.to_a : [] + authorize @course - @filtered_group_list = filtered_group_list - @filtered_student_list = filtered_student_list + # query for all projects_instances, owner_type and owner_id for participants table + @course.projects.includes(project_instances: { enrolment: :user }).load + @projects_by_owner = @course.projects.index_by { |p| [p.owner_type, p.owner_id] - projects_ownerships = @course.projects.approved - .where(owner_type: 'User') - .pluck('owner_id') + @student_list = @course.students - @students_with_projects = @student_list.select do |student| - projects_ownerships.include?(student.id) + if @course.grouped? + @group_list = @course.project_groups.includes(project_group_members: :user).to_a + else + @group_list = [] end - @students_without_projects = @student_list.reject do |student| - projects_ownerships.include?(student.id) + projects_ownerships = @course.projects.approved.where(owner_type: 'User').pluck('owner_id') + + @filtered_group_list = filtered_group_list + @filtered_student_list = filtered_student_list + + @students_with_projects = @student_list.select { |s| projects_ownerships.include?(s.id) } + @students_without_projects = @student_list.reject { |s| projects_ownerships.include?(s.id) } end end private def filtered_group_list - return @group_list unless params[:status_filter].present? && params[:status_filter] != 'all' - - @course.groups_with_status(params[:status_filter], @group_list) + group_list = if params[:status_filter].present? && params[:status_filter] != 'all' + @course.groups_with_status(params[:status_filter], @group_list) + else + @group_list + end + group_list.sort_by(&:group_name) end def filtered_student_list return @student_list unless params[:status_filter].present? && params[:status_filter] != 'all' - @course.students_with_status(params[:status_filter], @student_list, @students_with_projects, @students_without_projects, @course) + @course.students_with_status(params[:status_filter], @student_list) end end diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb index 991fc8f1..600e973b 100644 --- a/app/helpers/courses_helper.rb +++ b/app/helpers/courses_helper.rb @@ -1,39 +1,25 @@ module CoursesHelper - def group_project_for(group, course) - @group_projects_cache ||= {} - @group_projects_cache[group.id] ||= course.projects - .find_by(owner_type: 'ProjectGroup', owner_id: group.id) + def group_project_for(group, _course) + @projects_by_owner[['ProjectGroup', group.id]] end - def student_project_for(student, course) - @student_projects_cache ||= {} - @student_projects_cache[student.id] ||= course.projects - .find_by(owner_type: 'User', owner_id: student.id) + def student_project_for(student, _course) + @projects_by_owner[['User', student.id]] end def group_status(group, course) - project = group_project_for(group, course) - return 'not_submitted' unless project - - project.current_status + group_project_for(group, course)&.current_status || 'not_submitted' end def student_status(student, course) - project = student_project_for(student, course) - return 'not_submitted' unless project - - project.current_status + student_project_for(student, course)&.current_status || 'not_submitted' end def participants_exceed?(course) - return false unless course.students.present? - - course.students.count > Rails.application.config.participants_threshold + course.students.size > Rails.application.config.participants_threshold end def supervisors_exceed?(course) - return false unless course.supervisors.present? - - course.supervisors.count > Rails.application.config.supervisors_threshold + course.supervisors.size > Rails.application.config.supervisors_threshold end end diff --git a/app/views/courses/_participants_table.html.erb b/app/views/courses/_participants_table.html.erb index 4e5baa24..715e0412 100644 --- a/app/views/courses/_participants_table.html.erb +++ b/app/views/courses/_participants_table.html.erb @@ -98,7 +98,7 @@ <%# 2. Members List %>