From 1845c3e51cadae17aeb643d446e5fb90b4a8bad4 Mon Sep 17 00:00:00 2001 From: SOO Date: Fri, 3 Apr 2026 19:30:20 +0800 Subject: [PATCH 1/7] enrolment_to_supervisor --- app/controllers/courses_controller.rb | 4 +- app/controllers/projects_controller.rb | 18 ++++---- app/models/project.rb | 13 ++---- app/models/project_instance.rb | 8 +--- app/policies/project_policy.rb | 2 +- .../courses/_participants_table.html.erb | 12 ++--- app/views/courses/profile.html.erb | 4 +- app/views/projects/_project_header.html.erb | 4 +- db/seeds.rb | 44 +++++++++---------- 9 files changed, 49 insertions(+), 60 deletions(-) diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 827fb9f5..80ee9872 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -49,10 +49,10 @@ def show if @current_user_enrolment&.coordinator? supervisor_enrolment = @lecturer_enrolment || @current_user_enrolment @my_student_projects = @course.projects.supervised_by(supervisor_enrolment).approved - @incoming_proposals = @course.projects.where(enrolment: supervisor_enrolment).proposals + @incoming_proposals = @course.projects.where(supervisor: supervisor_enrolment).proposals elsif @current_user_enrolment&.lecturer? @my_student_projects = @course.projects.supervised_by(@current_user_enrolment).approved - @incoming_proposals = @course.projects.where(enrolment: @current_user_enrolment).proposals + @incoming_proposals = @course.projects.where(supervisor: @current_user_enrolment).proposals end # SET LECTURER CAPACITY diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index dc557126..dc278d2f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -163,7 +163,7 @@ def create @project = Project.create!( course: @course, owner: @course.grouped? ? group : current_user, - enrolment: supervisor_enrolment + supervisor: supervisor_enrolment ) # Get title @@ -176,7 +176,7 @@ def create version: 1, title: title_value, created_by: current_user, - enrolment: supervisor_enrolment, + supervisor: supervisor_enrolment, source_topic: topic || nil, last_edit_time: Time.current, last_edit_by: current_user.id @@ -196,8 +196,8 @@ def create end GeneralMailer.with( - email_address: @project.supervisor.email_address, - supervisor_username: @project.supervisor.username, + email_address: @project.supervisor.user.email_address, + supervisor_username: @project.supervisor.user.username, owner_name: @course.grouped? ? @project.owner.group_name : @project.owner.username, course: @course, project: @project @@ -211,13 +211,13 @@ def update has_supervisor_comment = false @project.project_instances.last.comments.each do |comment| - if comment.user_id == @project.supervisor.id + if comment.user_id == @project.supervisor.user.id has_supervisor_comment = true break end end - previous_supervisor_id = @project.supervisor.id + previous_supervisor_id = @project.supervisor.user.id new_instance_created = false begin @@ -287,7 +287,7 @@ def update end @project.project_instances.last.update!( - enrolment: supervisor_enrolment + supervisor: supervisor_enrolment ) end rescue StandardError @@ -295,9 +295,9 @@ def update return end - if previous_supervisor_id != @project.supervisor.id || new_instance_created + if previous_supervisor_id != @project.supervisor.user.id || new_instance_created GeneralMailer.with( - supervisor_username: @project.supervisor.username, + supervisor_username: @project.supervisor.user.username, owner_name: @course.grouped? ? @project.owner.group_name : @project.owner.username, course: @course, project: @project diff --git a/app/models/project.rb b/app/models/project.rb index 1ab9e0e3..ddd76789 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2,7 +2,7 @@ class Project < ApplicationRecord enum :ownership_type, { student: 0, project_group: 1, lecturer: 2 } default_scope { where(ownership_type: %i[student project_group]) } - belongs_to :enrolment + belongs_to :supervisor, class_name: 'Enrolment', foreign_key: 'enrolment_id' belongs_to :course belongs_to :owner, polymorphic: true @@ -22,7 +22,7 @@ class Project < ApplicationRecord scope :proposals, -> { where(status: %i[pending redo rejected]) } # Enrolment (supervisor) filters - scope :supervised_by, ->(enrolment) { where(enrolment: enrolment) } + scope :supervised_by, ->(supervisor) { where(supervisor: supervisor) } scope :owned_by_user_or_groups, lambda { |user, groups| where(owner: [user] + groups.to_a) @@ -32,13 +32,6 @@ class Project < ApplicationRecord before_validation :set_ownership_type - def supervisor - return nil unless enrolment_id.present? - - enrolment = Enrolment.find_by(id: enrolment_id) - enrolment&.user - end - def member if ownership.owner.is_a?(ProjectGroup) ownership.owner.users @@ -72,7 +65,7 @@ def instance_to_edit(created_by:, has_supervisor_comment:) project_instances.build( version: project_instances.count + 1, created_by: created_by, - enrolment: enrolment + supervisor: supervisor ) else # If approved and pending (no supervisor comment) dont create new instance diff --git a/app/models/project_instance.rb b/app/models/project_instance.rb index bdf749a6..7207848e 100644 --- a/app/models/project_instance.rb +++ b/app/models/project_instance.rb @@ -4,7 +4,7 @@ class ProjectInstance < ApplicationRecord default_scope { where(project_instance_type: :project) } belongs_to :project - belongs_to :enrolment + belongs_to :supervisor, class_name: 'Enrolment', foreign_key: 'enrolment_id' has_many :comments, as: :location, dependent: :destroy @@ -22,10 +22,6 @@ class ProjectInstance < ApplicationRecord validates :version, presence: true, numericality: { only_integer: true, greater_than: 0 } validates :title, presence: true - def supervisor - enrolment&.user - end - private def update_parent_project @@ -33,7 +29,7 @@ def update_parent_project project.update( status: status, - enrolment: enrolment + supervisor: supervisor ) end diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index a80ade00..b803250b 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -74,7 +74,7 @@ def project_owner end def assigned_supervisor - record.supervisor == user + record.supervisor.user == user end def has_unrestricted_student_access diff --git a/app/views/courses/_participants_table.html.erb b/app/views/courses/_participants_table.html.erb index 4e5baa24..7e10e639 100644 --- a/app/views/courses/_participants_table.html.erb +++ b/app/views/courses/_participants_table.html.erb @@ -207,14 +207,14 @@ font-bold text-gray-600 shrink-0 group-hover/sup:bg-blue-100 group-hover/sup:text-gray-700 transition-colors "> - <%= supervisor.username.first.upcase %> + <%= supervisor.user.username.first.upcase %> - <%= supervisor.username %> + title="<%= supervisor.user.username %>"> + <%= supervisor.user.username %> <% end %> <% else %> @@ -360,14 +360,14 @@ font-bold text-gray-600 shrink-0 group-hover/sup:bg-blue-100 group-hover/sup:text-gray-700 transition-colors "> - <%= supervisor.username.first.upcase %> + <%= supervisor.user.username.first.upcase %> - <%= supervisor.username %> + title="<%= supervisor.user.username %>"> + <%= supervisor.user.username %> <% end %> <% else %> diff --git a/app/views/courses/profile.html.erb b/app/views/courses/profile.html.erb index dd5a1ac5..5543ab76 100644 --- a/app/views/courses/profile.html.erb +++ b/app/views/courses/profile.html.erb @@ -250,9 +250,9 @@ justify-center text-xs font-bold text-gray-700 shrink-0 " > - <%= @supervisor.username.first.upcase %> + <%= @supervisor.user.username.first.upcase %> - <%= @supervisor.username %> + <%= @supervisor.user.username %> <% end %> diff --git a/app/views/projects/_project_header.html.erb b/app/views/projects/_project_header.html.erb index 7ae47f1d..5c228cd2 100644 --- a/app/views/projects/_project_header.html.erb +++ b/app/views/projects/_project_header.html.erb @@ -133,7 +133,7 @@ <%= link_to course_lecturer_path(course, current_instance.supervisor), class: "flex items-center justify-start gap-2 group/sup underline decoration-transparent transition-colors duration-300 ease-in-out hover:decoration-current" do %> - <%= current_instance.supervisor.username %> + <%= current_instance.supervisor.user.username %> <% end %> @@ -183,7 +183,7 @@
<%# Coordinator Approval Form %> - <% if current_user == project.supervisor && current_version == latest_version %> + <% if current_user == project.supervisor.user && current_version == latest_version %>
<%= form_with url: change_status_course_project_path(course, project), method: :patch, local: true, class: "flex items-center gap-1 sm:gap-2 min-w-0 justify-end" do |f| %> <% statuses = Project.statuses.keys.without("not_submitted") %> diff --git a/db/seeds.rb b/db/seeds.rb index 7fdda3f4..51b3eb61 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -604,56 +604,56 @@ group_1_project = Project.create!( course: course_with_groups, - enrolment: lecturer_1_lecturer_enrolment, + supervisor: lecturer_1_lecturer_enrolment, owner: group_1, ownership_type: :project_group ) group_2_project = Project.create!( course: course_with_groups, - enrolment: lecturer_1_lecturer_enrolment, + supervisor: lecturer_1_lecturer_enrolment, owner: group_2, ownership_type: :project_group ) group_3_project = Project.create!( course: course_with_groups, - enrolment: lecturer_1_lecturer_enrolment, + supervisor: lecturer_1_lecturer_enrolment, owner: group_3, ownership_type: :project_group ) group_4_project = Project.create!( course: course_with_groups, - enrolment: lecturer_1_lecturer_enrolment, + supervisor: lecturer_1_lecturer_enrolment, owner: group_4, ownership_type: :project_group ) student_1_project = Project.create!( course: course_no_groups, - enrolment: lecturer_1_lecturer_enrolment_no_groups, + supervisor: lecturer_1_lecturer_enrolment_no_groups, owner: student1, ownership_type: :student ) student_2_project = Project.create!( course: course_no_groups, - enrolment: lecturer_1_lecturer_enrolment_no_groups, + supervisor: lecturer_1_lecturer_enrolment_no_groups, owner: student2, ownership_type: :student ) student_3_project = Project.create!( course: course_no_groups, - enrolment: lecturer_1_lecturer_enrolment_no_groups, + supervisor: lecturer_1_lecturer_enrolment_no_groups, owner: student3, ownership_type: :student ) student_4_project = Project.create!( course: course_no_groups, - enrolment: lecturer_1_lecturer_enrolment_no_groups, + supervisor: lecturer_1_lecturer_enrolment_no_groups, owner: student4, ownership_type: :student ) @@ -809,7 +809,7 @@ created_by: student1, title: 'Difficult Group Project 1', status: :pending, - enrolment: lecturer_2_lecturer_enrolment + supervisor: lecturer_2_lecturer_enrolment ) group_1_instance_2 = ProjectInstance.create!( @@ -818,7 +818,7 @@ created_by: student1, title: 'Difficult Group Project 2', status: :redo, - enrolment: lecturer_2_lecturer_enrolment + supervisor: lecturer_2_lecturer_enrolment ) group_1_instance_3 = ProjectInstance.create!( @@ -827,7 +827,7 @@ created_by: student1, title: 'Difficult Group Project 3', status: :rejected, - enrolment: lecturer_3_lecturer_enrolment + supervisor: lecturer_3_lecturer_enrolment ) group_1_instance_4 = ProjectInstance.create!( @@ -836,7 +836,7 @@ created_by: student1, title: 'Difficult Group Project 4', status: :approved, - enrolment: lecturer_1_lecturer_enrolment + supervisor: lecturer_1_lecturer_enrolment ) group_2_instance_1 = ProjectInstance.create!( @@ -845,7 +845,7 @@ created_by: student4, title: 'Difficult Group Project Group 2', status: :rejected, - enrolment: lecturer_1_lecturer_enrolment + supervisor: lecturer_1_lecturer_enrolment ) group_3_instance_1 = ProjectInstance.create!( @@ -854,7 +854,7 @@ created_by: student7, title: 'Difficult Group Project Group 3', status: :redo, - enrolment: lecturer_1_lecturer_enrolment + supervisor: lecturer_1_lecturer_enrolment ) group_4_instance_1 = ProjectInstance.create!( @@ -863,7 +863,7 @@ created_by: student10, title: 'Difficult Group Project Group 4', status: :pending, - enrolment: lecturer_1_lecturer_enrolment + supervisor: lecturer_1_lecturer_enrolment ) student_1_project_instance_1 = ProjectInstance.create!( @@ -872,7 +872,7 @@ created_by: student1, title: 'Student 1 Project', status: :pending, - enrolment: lecturer_3_lecturer_enrolment_no_groups + supervisor: lecturer_3_lecturer_enrolment_no_groups ) student_1_project_instance_2 = ProjectInstance.create!( @@ -881,7 +881,7 @@ created_by: student1, title: 'Student 1 Project 2', status: :rejected, - enrolment: lecturer_3_lecturer_enrolment_no_groups + supervisor: lecturer_3_lecturer_enrolment_no_groups ) student_1_project_instance_3 = ProjectInstance.create!( @@ -890,7 +890,7 @@ created_by: student1, title: 'Student 1 Project 3', status: :redo, - enrolment: lecturer_2_lecturer_enrolment_no_groups + supervisor: lecturer_2_lecturer_enrolment_no_groups ) student_1_project_instance_4 = ProjectInstance.create!( @@ -899,7 +899,7 @@ created_by: student1, title: 'Student 1 Project 4', status: :approved, - enrolment: lecturer_1_lecturer_enrolment_no_groups + supervisor: lecturer_1_lecturer_enrolment_no_groups ) student_2_project_instance_1 = ProjectInstance.create!( @@ -908,7 +908,7 @@ created_by: student2, title: 'Student 2 Project', status: :pending, - enrolment: lecturer_1_lecturer_enrolment_no_groups + supervisor: lecturer_1_lecturer_enrolment_no_groups ) student_3_project_instance_1 = ProjectInstance.create!( @@ -917,7 +917,7 @@ created_by: student3, title: 'Student 3 Project', status: :redo, - enrolment: lecturer_1_lecturer_enrolment_no_groups + supervisor: lecturer_1_lecturer_enrolment_no_groups ) student_4_project_instance_1 = ProjectInstance.create!( @@ -926,7 +926,7 @@ created_by: student4, title: 'Student 4 Project', status: :rejected, - enrolment: lecturer_1_lecturer_enrolment_no_groups + supervisor: lecturer_1_lecturer_enrolment_no_groups ) # Create Project Instance Fields From 75106d9474f061e2e042e34128b143a5dec582c8 Mon Sep 17 00:00:00 2001 From: SOO Date: Sun, 5 Apr 2026 20:59:46 +0800 Subject: [PATCH 2/7] patched test as well --- test/factories/project_instances.rb | 2 +- test/factories/projects.rb | 2 +- test/models/project_instance_test.rb | 18 +++++++++--------- test/models/project_test.rb | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/test/factories/project_instances.rb b/test/factories/project_instances.rb index 6d00c3e2..ba2bde47 100644 --- a/test/factories/project_instances.rb +++ b/test/factories/project_instances.rb @@ -1,7 +1,7 @@ FactoryBot.define do factory :project_instance do association :project - association :enrolment + association :supervisor, factory: :enrolment association :created_by, factory: :user version { 1 } status { :pending } diff --git a/test/factories/projects.rb b/test/factories/projects.rb index 1b5eddc4..995f89ff 100644 --- a/test/factories/projects.rb +++ b/test/factories/projects.rb @@ -1,7 +1,7 @@ FactoryBot.define do factory :project do association :course - association :enrolment + association :supervisor, factory: :enrolment owner { association :user } owner_type { 'User' } status { :pending } diff --git a/test/models/project_instance_test.rb b/test/models/project_instance_test.rb index 4b9136eb..93217bbc 100644 --- a/test/models/project_instance_test.rb +++ b/test/models/project_instance_test.rb @@ -5,13 +5,13 @@ class ProjectInstanceTest < ActiveSupport::TestCase @course = FactoryBot.create(:course) @user = FactoryBot.create(:user, is_staff: false) @enrolment = FactoryBot.create(:enrolment, user: @user, course: @course, role: :student) - @project = FactoryBot.create(:project, course: @course, owner: @user, enrolment: @enrolment) + @project = FactoryBot.create(:project, course: @course, owner: @user, supervisor: @enrolment) end test 'project instance created with happy paths' do instance = ProjectInstance.create!( project: @project, - enrolment: @enrolment, + supervisor: @enrolment, created_by: @user, version: 1, title: 'Test Project Title' @@ -25,7 +25,7 @@ class ProjectInstanceTest < ActiveSupport::TestCase test 'saving project instance updates the parent project status happy path' do ProjectInstance.create!( project: @project, - enrolment: @enrolment, + supervisor: @enrolment, created_by: @user, version: 1, title: 'Test Project Title' @@ -36,12 +36,12 @@ class ProjectInstanceTest < ActiveSupport::TestCase test 'saving an older instance does not overwrite parent project status sad path' do instance_v1 = ProjectInstance.create!( - project: @project, enrolment: @enrolment, + project: @project, supervisor: @enrolment, created_by: @user, version: 1, title: 'Test Project Title', status: :pending ) ProjectInstance.create!( - project: @project, enrolment: @enrolment, + project: @project, supervisor: @enrolment, created_by: @user, version: 2, title: 'Test Project Title 2', status: :approved ) @@ -53,12 +53,12 @@ class ProjectInstanceTest < ActiveSupport::TestCase test 'current_instance returns the instance with the highest version' do ProjectInstance.create!( - project: @project, enrolment: @enrolment, + project: @project, supervisor: @enrolment, created_by: @user, version: 1, title: 'Test Project Title' ) instance_v2 = ProjectInstance.create!( - project: @project, enrolment: @enrolment, + project: @project, supervisor: @enrolment, created_by: @user, version: 2, title: 'Test Project Title 2' ) @@ -82,13 +82,13 @@ class ProjectInstanceTest < ActiveSupport::TestCase test 'cannot create two instances with the same version for the same project' do ProjectInstance.create!( - project: @project, enrolment: @enrolment, + project: @project, supervisor: @enrolment, created_by: @user, version: 1, title: 'First' ) assert_raises ActiveRecord::RecordNotUnique do ProjectInstance.create!( - project: @project, enrolment: @enrolment, + project: @project, supervisor: @enrolment, created_by: @user, version: 1, title: 'Duplicate' ) end diff --git a/test/models/project_test.rb b/test/models/project_test.rb index 93899e5f..f9a6e960 100644 --- a/test/models/project_test.rb +++ b/test/models/project_test.rb @@ -7,8 +7,8 @@ class ProjectTest < ActiveSupport::TestCase @lecturer = create(:user, is_staff: true) @student_enrolment = create(:enrolment, :student, user: @student, course: @course) @lecturer_enrolment = create(:enrolment, :lecturer, user: @lecturer, course: @course) - @project = create(:project, course: @course, owner: @student, enrolment: @lecturer_enrolment) - @instance = create(:project_instance, project: @project, enrolment: @lecturer_enrolment, created_by: @student, version: 1) + @project = create(:project, course: @course, owner: @student, supervisor: @lecturer_enrolment) + @instance = create(:project_instance, project: @project, supervisor: @lecturer_enrolment, created_by: @student, version: 1) end test 'instance_to_edit returns new instance when project is rejected' do From 7b89c97046ba2a568fb0af30e07ed5f58fd360e2 Mon Sep 17 00:00:00 2001 From: SOO Date: Thu, 9 Apr 2026 22:50:03 +0800 Subject: [PATCH 3/7] supervisor to supervisor_enrolment --- app/controllers/courses_controller.rb | 4 ++-- app/controllers/projects_controller.rb | 18 +++++++++--------- app/models/project.rb | 10 +++++++--- app/models/project_instance.rb | 8 ++++++-- app/policies/project_policy.rb | 2 +- app/views/courses/_participants_table.html.erb | 12 ++++++------ app/views/courses/profile.html.erb | 4 ++-- app/views/projects/_project_header.html.erb | 4 ++-- 8 files changed, 35 insertions(+), 27 deletions(-) diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 80ee9872..e17e039e 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -49,10 +49,10 @@ def show if @current_user_enrolment&.coordinator? supervisor_enrolment = @lecturer_enrolment || @current_user_enrolment @my_student_projects = @course.projects.supervised_by(supervisor_enrolment).approved - @incoming_proposals = @course.projects.where(supervisor: supervisor_enrolment).proposals + @incoming_proposals = @course.projects.where(supervisor_enrolment: supervisor_enrolment).proposals elsif @current_user_enrolment&.lecturer? @my_student_projects = @course.projects.supervised_by(@current_user_enrolment).approved - @incoming_proposals = @course.projects.where(supervisor: @current_user_enrolment).proposals + @incoming_proposals = @course.projects.where(supervisor_enrolment: @current_user_enrolment).proposals end # SET LECTURER CAPACITY diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index dc278d2f..8e14be58 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -163,7 +163,7 @@ def create @project = Project.create!( course: @course, owner: @course.grouped? ? group : current_user, - supervisor: supervisor_enrolment + supervisor_enrolment: supervisor_enrolment ) # Get title @@ -176,7 +176,7 @@ def create version: 1, title: title_value, created_by: current_user, - supervisor: supervisor_enrolment, + supervisor_enrolment: supervisor_enrolment, source_topic: topic || nil, last_edit_time: Time.current, last_edit_by: current_user.id @@ -196,8 +196,8 @@ def create end GeneralMailer.with( - email_address: @project.supervisor.user.email_address, - supervisor_username: @project.supervisor.user.username, + email_address: @project.supervisor.email_address, + supervisor_username: @project.supervisor.username, owner_name: @course.grouped? ? @project.owner.group_name : @project.owner.username, course: @course, project: @project @@ -211,13 +211,13 @@ def update has_supervisor_comment = false @project.project_instances.last.comments.each do |comment| - if comment.user_id == @project.supervisor.user.id + if comment.user_id == @project.supervisor.id has_supervisor_comment = true break end end - previous_supervisor_id = @project.supervisor.user.id + previous_supervisor_id = @project.supervisor.id new_instance_created = false begin @@ -287,7 +287,7 @@ def update end @project.project_instances.last.update!( - supervisor: supervisor_enrolment + supervisor_enrolment: supervisor_enrolment ) end rescue StandardError @@ -295,9 +295,9 @@ def update return end - if previous_supervisor_id != @project.supervisor.user.id || new_instance_created + if previous_supervisor_id != @project.supervisor.id || new_instance_created GeneralMailer.with( - supervisor_username: @project.supervisor.user.username, + supervisor_username: @project.supervisor.username, owner_name: @course.grouped? ? @project.owner.group_name : @project.owner.username, course: @course, project: @project diff --git a/app/models/project.rb b/app/models/project.rb index ddd76789..a4f74866 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2,7 +2,7 @@ class Project < ApplicationRecord enum :ownership_type, { student: 0, project_group: 1, lecturer: 2 } default_scope { where(ownership_type: %i[student project_group]) } - belongs_to :supervisor, class_name: 'Enrolment', foreign_key: 'enrolment_id' + belongs_to :supervisor_enrolment, class_name: 'Enrolment', foreign_key: 'enrolment_id' belongs_to :course belongs_to :owner, polymorphic: true @@ -22,7 +22,7 @@ class Project < ApplicationRecord scope :proposals, -> { where(status: %i[pending redo rejected]) } # Enrolment (supervisor) filters - scope :supervised_by, ->(supervisor) { where(supervisor: supervisor) } + scope :supervised_by, ->(supervisor_enrolment) { where(supervisor_enrolment: supervisor_enrolment) } scope :owned_by_user_or_groups, lambda { |user, groups| where(owner: [user] + groups.to_a) @@ -32,6 +32,10 @@ class Project < ApplicationRecord before_validation :set_ownership_type + def supervisor + self.supervisor_enrolment.user + end + def member if ownership.owner.is_a?(ProjectGroup) ownership.owner.users @@ -65,7 +69,7 @@ def instance_to_edit(created_by:, has_supervisor_comment:) project_instances.build( version: project_instances.count + 1, created_by: created_by, - supervisor: supervisor + supervisor_enrolment: supervisor_enrolment ) else # If approved and pending (no supervisor comment) dont create new instance diff --git a/app/models/project_instance.rb b/app/models/project_instance.rb index 7207848e..c5671591 100644 --- a/app/models/project_instance.rb +++ b/app/models/project_instance.rb @@ -4,7 +4,7 @@ class ProjectInstance < ApplicationRecord default_scope { where(project_instance_type: :project) } belongs_to :project - belongs_to :supervisor, class_name: 'Enrolment', foreign_key: 'enrolment_id' + belongs_to :supervisor_enrolment, class_name: 'Enrolment', foreign_key: 'enrolment_id' has_many :comments, as: :location, dependent: :destroy @@ -22,6 +22,10 @@ class ProjectInstance < ApplicationRecord validates :version, presence: true, numericality: { only_integer: true, greater_than: 0 } validates :title, presence: true + def supervisor + self.supervisor_enrolment.user + end + private def update_parent_project @@ -29,7 +33,7 @@ def update_parent_project project.update( status: status, - supervisor: supervisor + supervisor_enrolment: supervisor_enrolment ) end diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index b803250b..a80ade00 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -74,7 +74,7 @@ def project_owner end def assigned_supervisor - record.supervisor.user == user + record.supervisor == user end def has_unrestricted_student_access diff --git a/app/views/courses/_participants_table.html.erb b/app/views/courses/_participants_table.html.erb index 7e10e639..4e5baa24 100644 --- a/app/views/courses/_participants_table.html.erb +++ b/app/views/courses/_participants_table.html.erb @@ -207,14 +207,14 @@ font-bold text-gray-600 shrink-0 group-hover/sup:bg-blue-100 group-hover/sup:text-gray-700 transition-colors "> - <%= supervisor.user.username.first.upcase %> + <%= supervisor.username.first.upcase %>
- <%= supervisor.user.username %> + title="<%= supervisor.username %>"> + <%= supervisor.username %> <% end %> <% else %> @@ -360,14 +360,14 @@ font-bold text-gray-600 shrink-0 group-hover/sup:bg-blue-100 group-hover/sup:text-gray-700 transition-colors "> - <%= supervisor.user.username.first.upcase %> + <%= supervisor.username.first.upcase %>
- <%= supervisor.user.username %> + title="<%= supervisor.username %>"> + <%= supervisor.username %> <% end %> <% else %> diff --git a/app/views/courses/profile.html.erb b/app/views/courses/profile.html.erb index 5543ab76..dd5a1ac5 100644 --- a/app/views/courses/profile.html.erb +++ b/app/views/courses/profile.html.erb @@ -250,9 +250,9 @@ justify-center text-xs font-bold text-gray-700 shrink-0 " > - <%= @supervisor.user.username.first.upcase %> + <%= @supervisor.username.first.upcase %> - <%= @supervisor.user.username %> + <%= @supervisor.username %> <% end %> diff --git a/app/views/projects/_project_header.html.erb b/app/views/projects/_project_header.html.erb index 5c228cd2..7ae47f1d 100644 --- a/app/views/projects/_project_header.html.erb +++ b/app/views/projects/_project_header.html.erb @@ -133,7 +133,7 @@ <%= link_to course_lecturer_path(course, current_instance.supervisor), class: "flex items-center justify-start gap-2 group/sup underline decoration-transparent transition-colors duration-300 ease-in-out hover:decoration-current" do %> - <%= current_instance.supervisor.user.username %> + <%= current_instance.supervisor.username %> <% end %> @@ -183,7 +183,7 @@
<%# Coordinator Approval Form %> - <% if current_user == project.supervisor.user && current_version == latest_version %> + <% if current_user == project.supervisor && current_version == latest_version %>
<%= form_with url: change_status_course_project_path(course, project), method: :patch, local: true, class: "flex items-center gap-1 sm:gap-2 min-w-0 justify-end" do |f| %> <% statuses = Project.statuses.keys.without("not_submitted") %> From daca74d6c4e580e0e290dbbfc0c4e6ffed38e02a Mon Sep 17 00:00:00 2001 From: SOO Date: Thu, 9 Apr 2026 22:54:20 +0800 Subject: [PATCH 4/7] conflicts but no conflicts? --- db/seeds.rb | 44 ++++++++++++++-------------- test/factories/project_instances.rb | 2 +- test/factories/projects.rb | 2 +- test/models/project_instance_test.rb | 18 ++++++------ test/models/project_test.rb | 4 +-- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index 51b3eb61..90e705cc 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -604,56 +604,56 @@ group_1_project = Project.create!( course: course_with_groups, - supervisor: lecturer_1_lecturer_enrolment, + supervisor_enrolment: lecturer_1_lecturer_enrolment, owner: group_1, ownership_type: :project_group ) group_2_project = Project.create!( course: course_with_groups, - supervisor: lecturer_1_lecturer_enrolment, + supervisor_enrolment: lecturer_1_lecturer_enrolment, owner: group_2, ownership_type: :project_group ) group_3_project = Project.create!( course: course_with_groups, - supervisor: lecturer_1_lecturer_enrolment, + supervisor_enrolment: lecturer_1_lecturer_enrolment, owner: group_3, ownership_type: :project_group ) group_4_project = Project.create!( course: course_with_groups, - supervisor: lecturer_1_lecturer_enrolment, + supervisor_enrolment: lecturer_1_lecturer_enrolment, owner: group_4, ownership_type: :project_group ) student_1_project = Project.create!( course: course_no_groups, - supervisor: lecturer_1_lecturer_enrolment_no_groups, + supervisor_enrolment: lecturer_1_lecturer_enrolment_no_groups, owner: student1, ownership_type: :student ) student_2_project = Project.create!( course: course_no_groups, - supervisor: lecturer_1_lecturer_enrolment_no_groups, + supervisor_enrolment: lecturer_1_lecturer_enrolment_no_groups, owner: student2, ownership_type: :student ) student_3_project = Project.create!( course: course_no_groups, - supervisor: lecturer_1_lecturer_enrolment_no_groups, + supervisor_enrolment: lecturer_1_lecturer_enrolment_no_groups, owner: student3, ownership_type: :student ) student_4_project = Project.create!( course: course_no_groups, - supervisor: lecturer_1_lecturer_enrolment_no_groups, + supervisor_enrolment: lecturer_1_lecturer_enrolment_no_groups, owner: student4, ownership_type: :student ) @@ -809,7 +809,7 @@ created_by: student1, title: 'Difficult Group Project 1', status: :pending, - supervisor: lecturer_2_lecturer_enrolment + supervisor_enrolment: lecturer_2_lecturer_enrolment ) group_1_instance_2 = ProjectInstance.create!( @@ -818,7 +818,7 @@ created_by: student1, title: 'Difficult Group Project 2', status: :redo, - supervisor: lecturer_2_lecturer_enrolment + supervisor_enrolment: lecturer_2_lecturer_enrolment ) group_1_instance_3 = ProjectInstance.create!( @@ -827,7 +827,7 @@ created_by: student1, title: 'Difficult Group Project 3', status: :rejected, - supervisor: lecturer_3_lecturer_enrolment + supervisor_enrolment: lecturer_3_lecturer_enrolment ) group_1_instance_4 = ProjectInstance.create!( @@ -836,7 +836,7 @@ created_by: student1, title: 'Difficult Group Project 4', status: :approved, - supervisor: lecturer_1_lecturer_enrolment + supervisor_enrolment: lecturer_1_lecturer_enrolment ) group_2_instance_1 = ProjectInstance.create!( @@ -845,7 +845,7 @@ created_by: student4, title: 'Difficult Group Project Group 2', status: :rejected, - supervisor: lecturer_1_lecturer_enrolment + supervisor_enrolment: lecturer_1_lecturer_enrolment ) group_3_instance_1 = ProjectInstance.create!( @@ -854,7 +854,7 @@ created_by: student7, title: 'Difficult Group Project Group 3', status: :redo, - supervisor: lecturer_1_lecturer_enrolment + supervisor_enrolment: lecturer_1_lecturer_enrolment ) group_4_instance_1 = ProjectInstance.create!( @@ -863,7 +863,7 @@ created_by: student10, title: 'Difficult Group Project Group 4', status: :pending, - supervisor: lecturer_1_lecturer_enrolment + supervisor_enrolment: lecturer_1_lecturer_enrolment ) student_1_project_instance_1 = ProjectInstance.create!( @@ -872,7 +872,7 @@ created_by: student1, title: 'Student 1 Project', status: :pending, - supervisor: lecturer_3_lecturer_enrolment_no_groups + supervisor_enrolment: lecturer_3_lecturer_enrolment_no_groups ) student_1_project_instance_2 = ProjectInstance.create!( @@ -881,7 +881,7 @@ created_by: student1, title: 'Student 1 Project 2', status: :rejected, - supervisor: lecturer_3_lecturer_enrolment_no_groups + supervisor_enrolment: lecturer_3_lecturer_enrolment_no_groups ) student_1_project_instance_3 = ProjectInstance.create!( @@ -890,7 +890,7 @@ created_by: student1, title: 'Student 1 Project 3', status: :redo, - supervisor: lecturer_2_lecturer_enrolment_no_groups + supervisor_enrolment: lecturer_2_lecturer_enrolment_no_groups ) student_1_project_instance_4 = ProjectInstance.create!( @@ -899,7 +899,7 @@ created_by: student1, title: 'Student 1 Project 4', status: :approved, - supervisor: lecturer_1_lecturer_enrolment_no_groups + supervisor_enrolment: lecturer_1_lecturer_enrolment_no_groups ) student_2_project_instance_1 = ProjectInstance.create!( @@ -908,7 +908,7 @@ created_by: student2, title: 'Student 2 Project', status: :pending, - supervisor: lecturer_1_lecturer_enrolment_no_groups + supervisor_enrolment: lecturer_1_lecturer_enrolment_no_groups ) student_3_project_instance_1 = ProjectInstance.create!( @@ -917,7 +917,7 @@ created_by: student3, title: 'Student 3 Project', status: :redo, - supervisor: lecturer_1_lecturer_enrolment_no_groups + supervisor_enrolment: lecturer_1_lecturer_enrolment_no_groups ) student_4_project_instance_1 = ProjectInstance.create!( @@ -926,7 +926,7 @@ created_by: student4, title: 'Student 4 Project', status: :rejected, - supervisor: lecturer_1_lecturer_enrolment_no_groups + supervisor_enrolment: lecturer_1_lecturer_enrolment_no_groups ) # Create Project Instance Fields diff --git a/test/factories/project_instances.rb b/test/factories/project_instances.rb index ba2bde47..9f605bea 100644 --- a/test/factories/project_instances.rb +++ b/test/factories/project_instances.rb @@ -1,7 +1,7 @@ FactoryBot.define do factory :project_instance do association :project - association :supervisor, factory: :enrolment + association :supervisor_enrolment, factory: :enrolment association :created_by, factory: :user version { 1 } status { :pending } diff --git a/test/factories/projects.rb b/test/factories/projects.rb index 995f89ff..170f0db7 100644 --- a/test/factories/projects.rb +++ b/test/factories/projects.rb @@ -1,7 +1,7 @@ FactoryBot.define do factory :project do association :course - association :supervisor, factory: :enrolment + association :supervisor_enrolment, factory: :enrolment owner { association :user } owner_type { 'User' } status { :pending } diff --git a/test/models/project_instance_test.rb b/test/models/project_instance_test.rb index 93217bbc..f101cbc4 100644 --- a/test/models/project_instance_test.rb +++ b/test/models/project_instance_test.rb @@ -5,13 +5,13 @@ class ProjectInstanceTest < ActiveSupport::TestCase @course = FactoryBot.create(:course) @user = FactoryBot.create(:user, is_staff: false) @enrolment = FactoryBot.create(:enrolment, user: @user, course: @course, role: :student) - @project = FactoryBot.create(:project, course: @course, owner: @user, supervisor: @enrolment) + @project = FactoryBot.create(:project, course: @course, owner: @user, supervisor_enrolment: @enrolment) end test 'project instance created with happy paths' do instance = ProjectInstance.create!( project: @project, - supervisor: @enrolment, + supervisor_enrolment: @enrolment, created_by: @user, version: 1, title: 'Test Project Title' @@ -25,7 +25,7 @@ class ProjectInstanceTest < ActiveSupport::TestCase test 'saving project instance updates the parent project status happy path' do ProjectInstance.create!( project: @project, - supervisor: @enrolment, + supervisor_enrolment: @enrolment, created_by: @user, version: 1, title: 'Test Project Title' @@ -36,12 +36,12 @@ class ProjectInstanceTest < ActiveSupport::TestCase test 'saving an older instance does not overwrite parent project status sad path' do instance_v1 = ProjectInstance.create!( - project: @project, supervisor: @enrolment, + project: @project, supervisor_enrolment: @enrolment, created_by: @user, version: 1, title: 'Test Project Title', status: :pending ) ProjectInstance.create!( - project: @project, supervisor: @enrolment, + project: @project, supervisor_enrolment: @enrolment, created_by: @user, version: 2, title: 'Test Project Title 2', status: :approved ) @@ -53,12 +53,12 @@ class ProjectInstanceTest < ActiveSupport::TestCase test 'current_instance returns the instance with the highest version' do ProjectInstance.create!( - project: @project, supervisor: @enrolment, + project: @project, supervisor_enrolment: @enrolment, created_by: @user, version: 1, title: 'Test Project Title' ) instance_v2 = ProjectInstance.create!( - project: @project, supervisor: @enrolment, + project: @project, supervisor_enrolment: @enrolment, created_by: @user, version: 2, title: 'Test Project Title 2' ) @@ -82,13 +82,13 @@ class ProjectInstanceTest < ActiveSupport::TestCase test 'cannot create two instances with the same version for the same project' do ProjectInstance.create!( - project: @project, supervisor: @enrolment, + project: @project, supervisor_enrolment: @enrolment, created_by: @user, version: 1, title: 'First' ) assert_raises ActiveRecord::RecordNotUnique do ProjectInstance.create!( - project: @project, supervisor: @enrolment, + project: @project, supervisor_enrolment: @enrolment, created_by: @user, version: 1, title: 'Duplicate' ) end diff --git a/test/models/project_test.rb b/test/models/project_test.rb index f9a6e960..b5ee5872 100644 --- a/test/models/project_test.rb +++ b/test/models/project_test.rb @@ -7,8 +7,8 @@ class ProjectTest < ActiveSupport::TestCase @lecturer = create(:user, is_staff: true) @student_enrolment = create(:enrolment, :student, user: @student, course: @course) @lecturer_enrolment = create(:enrolment, :lecturer, user: @lecturer, course: @course) - @project = create(:project, course: @course, owner: @student, supervisor: @lecturer_enrolment) - @instance = create(:project_instance, project: @project, supervisor: @lecturer_enrolment, created_by: @student, version: 1) + @project = create(:project, course: @course, owner: @student, supervisor_enrolment: @lecturer_enrolment) + @instance = create(:project_instance, project: @project, supervisor_enrolment: @lecturer_enrolment, created_by: @student, version: 1) end test 'instance_to_edit returns new instance when project is rejected' do From 369bae794c30a26a935b49fe30783152911e608e Mon Sep 17 00:00:00 2001 From: SOO Date: Thu, 9 Apr 2026 23:04:25 +0800 Subject: [PATCH 5/7] more tests --- test/system/projects/change_status_test.rb | 4 ++-- test/system/projects/project_versioning_test.rb | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/system/projects/change_status_test.rb b/test/system/projects/change_status_test.rb index b2023074..de27fdb2 100644 --- a/test/system/projects/change_status_test.rb +++ b/test/system/projects/change_status_test.rb @@ -11,8 +11,8 @@ class ChangeStatusTest < ApplicationSystemTestCase @lecturer_enrolment = create(:enrolment, user: @lecturer, course: @course, role: :lecturer) @other_student_enrolment = create(:enrolment, user: @other_student, course: @course, role: :student) - @project = create(:project, course: @course, owner: @student, enrolment: @lecturer_enrolment) - @instance = create(:project_instance, project: @project, enrolment: @lecturer_enrolment, created_by: @student, version: 1, status: :pending) + @project = create(:project, course: @course, owner: @student, supervisor_enrolment: @lecturer_enrolment) + @instance = create(:project_instance, project: @project, supervisor_enrolment: @lecturer_enrolment, created_by: @student, version: 1, status: :pending) end test 'supervisor can change project status happy path' do diff --git a/test/system/projects/project_versioning_test.rb b/test/system/projects/project_versioning_test.rb index ab824359..b7861ebc 100644 --- a/test/system/projects/project_versioning_test.rb +++ b/test/system/projects/project_versioning_test.rb @@ -9,9 +9,9 @@ class ProjectVersioningTest < ApplicationSystemTestCase @student_enrolment = create(:enrolment, :student, user: @student, course: @course) @lecturer_enrolment = create(:enrolment, :lecturer, user: @lecturer, course: @course) - @project = create(:project, course: @course, owner: @student, enrolment: @lecturer_enrolment) - @instance_1 = create(:project_instance, project: @project, enrolment: @lecturer_enrolment, created_by: @student, version: 1, status: :pending) - @instance_2 = create(:project_instance, project: @project, enrolment: @lecturer_enrolment, created_by: @student, version: 2, status: :pending) + @project = create(:project, course: @course, owner: @student, supervisor_enrolment: @lecturer_enrolment) + @instance_1 = create(:project_instance, project: @project, supervisor_enrolment: @lecturer_enrolment, created_by: @student, version: 1, status: :pending) + @instance_2 = create(:project_instance, project: @project, supervisor_enrolment: @lecturer_enrolment, created_by: @student, version: 2, status: :pending) end test 'defaults to latest version on page load' do From 4ccdf1cb959fce2530fe63098c60c8c3853359eb Mon Sep 17 00:00:00 2001 From: SOO Date: Fri, 10 Apr 2026 18:11:50 +0800 Subject: [PATCH 6/7] fixed bad preload query --- app/controllers/courses_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 13408454..19db1623 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -8,7 +8,7 @@ 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 + @course.projects.includes(project_instances: { supervisor_enrolment: :user }).load @projects_by_owner = @course.projects.index_by { |p| [p.owner_type, p.owner_id] } @student_list = @course.students From 771d4d7c869d52c31d38bf2a99c0114564dfadcf Mon Sep 17 00:00:00 2001 From: SOO Date: Fri, 10 Apr 2026 18:16:52 +0800 Subject: [PATCH 7/7] another one --- app/controllers/courses_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 699bb105..99028a51 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -262,7 +262,7 @@ def profile @course = Course.find(params[:id]) @grouped = @course.grouped - @course.projects.includes(project_instances: { enrolment: :user }).load + @course.projects.includes(project_instances: { supervisor_enrolment: :user }).load @projects_by_owner = @course.projects.index_by { |p| [p.owner_type, p.owner_id] } if @participant_type == 'group'