<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aagarw38</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aagarw38"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Aagarw38"/>
	<updated>2026-10-06T18:13:01Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160505</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160505"/>
		<updated>2024-12-04T03:08:25Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Pattern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
5. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
6. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Final design===&lt;br /&gt;
&lt;br /&gt;
The initial design proposed using the Facade and Repository patterns to improve the architecture of the TeamsParticipant refactoring. However, during implementation, we took a more direct approach for several reasons:&lt;br /&gt;
&lt;br /&gt;
1. '''Existing Code Structure:''' The codebase already had established patterns for controller-model interactions. The changes were made to align with these existing patterns, as seen in the invitation.rb and review_mapping_controller.rb modifications&lt;br /&gt;
&lt;br /&gt;
2. '''Minimal Benefit:''' The main goal was to fix the architectural inconsistency of teams being linked to users instead of participants. The proposed patterns would have added an extra layer of abstraction without providing &lt;br /&gt;
significant immediate benefits to this specific problem&lt;br /&gt;
&lt;br /&gt;
3. '''Future Considerations:''' While the Facade and Repository patterns could improve code organization and maintainability, they would be better implemented as part of a larger architectural refactoring effort. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
=== UI Testing===&lt;br /&gt;
&lt;br /&gt;
1. Created a new team for an assignment, sent an invite to another user and successfully accepted the invite, and added another user to the team, demonstrating the working of team-participants&lt;br /&gt;
&lt;br /&gt;
[[File:TeamsParticipantUIDemo.png|800px|center|border|]]&lt;br /&gt;
&lt;br /&gt;
2. Added a participant to an existing course&lt;br /&gt;
&lt;br /&gt;
[[File:CourseParticipantUIdemo.png|800px|center|border|]]&lt;br /&gt;
&lt;br /&gt;
===Sample Test Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Final Pull Request==&lt;br /&gt;
&lt;br /&gt;
The PR to Expertiza repo can be found here: &lt;br /&gt;
&lt;br /&gt;
 [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Project Demo==&lt;br /&gt;
&lt;br /&gt;
Click [https://vimeo.com/1035806635/f8dc0a1fc3 here] to view demo&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza]&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160504</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160504"/>
		<updated>2024-12-04T03:07:35Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Pattern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
5. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
6. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The initial design proposed using the Facade and Repository patterns to improve the architecture of the TeamsParticipant refactoring. However, during implementation, we took a more direct approach for several reasons:&lt;br /&gt;
&lt;br /&gt;
1. '''Existing Code Structure:''' The codebase already had established patterns for controller-model interactions. The changes were made to align with these existing patterns, as seen in the invitation.rb and review_mapping_controller.rb modifications&lt;br /&gt;
&lt;br /&gt;
2. '''Minimal Benefit:''' The main goal was to fix the architectural inconsistency of teams being linked to users instead of participants. The proposed patterns would have added an extra layer of abstraction without providing &lt;br /&gt;
                           significant immediate benefits to this specific problem&lt;br /&gt;
&lt;br /&gt;
3. '''Future Considerations:''' While the Facade and Repository patterns could improve code organization and maintainability, they would be better implemented as part of a larger architectural refactoring effort. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
=== UI Testing===&lt;br /&gt;
&lt;br /&gt;
1. Created a new team for an assignment, sent an invite to another user and successfully accepted the invite, and added another user to the team, demonstrating the working of team-participants&lt;br /&gt;
&lt;br /&gt;
[[File:TeamsParticipantUIDemo.png|800px|center|border|]]&lt;br /&gt;
&lt;br /&gt;
2. Added a participant to an existing course&lt;br /&gt;
&lt;br /&gt;
[[File:CourseParticipantUIdemo.png|800px|center|border|]]&lt;br /&gt;
&lt;br /&gt;
===Sample Test Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Final Pull Request==&lt;br /&gt;
&lt;br /&gt;
The PR to Expertiza repo can be found here: &lt;br /&gt;
&lt;br /&gt;
 [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Project Demo==&lt;br /&gt;
&lt;br /&gt;
Click [https://vimeo.com/1035806635/f8dc0a1fc3 here] to view demo&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza]&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160503</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160503"/>
		<updated>2024-12-04T03:07:07Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Pattern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
5. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
6. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The initial design proposed using the Facade and Repository patterns to improve the architecture of the TeamsParticipant refactoring. However, during implementation, we took a more direct approach for several reasons:&lt;br /&gt;
&lt;br /&gt;
1. '''Existing Code Structure:''' The codebase already had established patterns for controller-model interactions. The changes were made to align with these existing patterns, as seen in the invitation.rb and review_mapping_controller.rb modifications&lt;br /&gt;
&lt;br /&gt;
2. '''Minimal Benefit:''' The main goal was to fix the architectural inconsistency of teams being linked to users instead of participants. The proposed patterns would have added an extra layer of abstraction without providing significant immediate benefits to this specific problem&lt;br /&gt;
&lt;br /&gt;
3. '''Future Considerations:''' While the Facade and Repository patterns could improve code organization and maintainability, they would be better implemented as part of a larger architectural refactoring effort. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
=== UI Testing===&lt;br /&gt;
&lt;br /&gt;
1. Created a new team for an assignment, sent an invite to another user and successfully accepted the invite, and added another user to the team, demonstrating the working of team-participants&lt;br /&gt;
&lt;br /&gt;
[[File:TeamsParticipantUIDemo.png|800px|center|border|]]&lt;br /&gt;
&lt;br /&gt;
2. Added a participant to an existing course&lt;br /&gt;
&lt;br /&gt;
[[File:CourseParticipantUIdemo.png|800px|center|border|]]&lt;br /&gt;
&lt;br /&gt;
===Sample Test Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Final Pull Request==&lt;br /&gt;
&lt;br /&gt;
The PR to Expertiza repo can be found here: &lt;br /&gt;
&lt;br /&gt;
 [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Project Demo==&lt;br /&gt;
&lt;br /&gt;
Click [https://vimeo.com/1035806635/f8dc0a1fc3 here] to view demo&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza]&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160502</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160502"/>
		<updated>2024-12-04T03:05:46Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Pattern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
5. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
6. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The initial design proposed using the Facade and Repository patterns to improve the architecture of the TeamsParticipant refactoring. However, during implementation, we took a more direct approach for several reasons:&lt;br /&gt;
&lt;br /&gt;
===Existing Code Structure===&lt;br /&gt;
&lt;br /&gt;
The codebase already had established patterns for controller-model interactions. The changes were made to align with these existing patterns, as seen in the invitation.rb and review_mapping_controller.rb modifications&lt;br /&gt;
&lt;br /&gt;
===Minimal Benefit===&lt;br /&gt;
&lt;br /&gt;
The main goal was to fix the architectural inconsistency of teams being linked to users instead of participants. The proposed patterns would have added an extra layer of abstraction without providing significant immediate benefits to this specific problem&lt;br /&gt;
&lt;br /&gt;
===Future Considerations===&lt;br /&gt;
&lt;br /&gt;
While the Facade and Repository patterns could improve code organization and maintainability, they would be better implemented as part of a larger architectural refactoring effort. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
=== UI Testing===&lt;br /&gt;
&lt;br /&gt;
1. Created a new team for an assignment, sent an invite to another user and successfully accepted the invite, and added another user to the team, demonstrating the working of team-participants&lt;br /&gt;
&lt;br /&gt;
[[File:TeamsParticipantUIDemo.png|800px|center|border|]]&lt;br /&gt;
&lt;br /&gt;
2. Added a participant to an existing course&lt;br /&gt;
&lt;br /&gt;
[[File:CourseParticipantUIdemo.png|800px|center|border|]]&lt;br /&gt;
&lt;br /&gt;
===Sample Test Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Final Pull Request==&lt;br /&gt;
&lt;br /&gt;
The PR to Expertiza repo can be found here: &lt;br /&gt;
&lt;br /&gt;
 [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Project Demo==&lt;br /&gt;
&lt;br /&gt;
Click [https://vimeo.com/1035806635/f8dc0a1fc3 here] to view demo&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza]&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160352</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160352"/>
		<updated>2024-12-04T00:20:35Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Fianal Pull Request */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
5. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
6. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Final Pull Request==&lt;br /&gt;
&lt;br /&gt;
The PR to Expertiza repo can be found here: &lt;br /&gt;
&lt;br /&gt;
 [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160351</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160351"/>
		<updated>2024-12-04T00:19:20Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Goal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
5. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
6. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Fianal Pull Request==&lt;br /&gt;
&lt;br /&gt;
The PR to Expertiza repo can be found here: &lt;br /&gt;
&lt;br /&gt;
 [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160344</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160344"/>
		<updated>2024-12-04T00:14:58Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Fianal Pull Request */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Fianal Pull Request==&lt;br /&gt;
&lt;br /&gt;
The PR to Expertiza repo can be found here: &lt;br /&gt;
&lt;br /&gt;
 [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160343</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160343"/>
		<updated>2024-12-04T00:14:47Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Fianal PR */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Fianal Pull Request==&lt;br /&gt;
&lt;br /&gt;
The PR request to Expertiza repo can be found here: &lt;br /&gt;
&lt;br /&gt;
 [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160342</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160342"/>
		<updated>2024-12-04T00:14:26Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Fianal PR */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Fianal PR==&lt;br /&gt;
&lt;br /&gt;
The PR request to Expertiza repo can be found here: &lt;br /&gt;
&lt;br /&gt;
 [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160341</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160341"/>
		<updated>2024-12-04T00:13:49Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Fianal PR==&lt;br /&gt;
&lt;br /&gt;
The PR request to Expertiza repo can be found here: # [https://github.com/expertiza/expertiza/pull/2887 E2456. Refactor teams user.rb #2887]&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160337</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160337"/>
		<updated>2024-12-04T00:07:51Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Sample Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of changes that were made to the 200 refrences across all models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160335</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160335"/>
		<updated>2024-12-04T00:06:00Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Sample Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating all the table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across most models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160333</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160333"/>
		<updated>2024-12-04T00:05:01Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Integration Tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across most models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160331</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160331"/>
		<updated>2024-12-04T00:04:55Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Integration Tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
  describe 'edit method' do&lt;br /&gt;
    context 'when team with given id that exists' do&lt;br /&gt;
      it 'successfully returns the team with the given team id' do&lt;br /&gt;
        allow(Team).to receive(:find).and_return(team1)&lt;br /&gt;
        request_params = { id: team1.id }&lt;br /&gt;
        user_session = { user: ta }&lt;br /&gt;
        result = get :edit, params: request_params, session: user_session&lt;br /&gt;
        expect(result.status).to eq 200&lt;br /&gt;
        expect(controller.instance_variable_get(:@team)).to eq team1&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when team with given id does not exist' do&lt;br /&gt;
      it 'raises an ActiveRecord::RecordNotFound error' do&lt;br /&gt;
        expect {&lt;br /&gt;
          get :edit, params: { id: 999 }, session: { user: ta }&lt;br /&gt;
        }.to raise_error(ActiveRecord::RecordNotFound)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across most models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160328</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160328"/>
		<updated>2024-12-04T00:03:42Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Model Tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
  describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across most models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160327</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160327"/>
		<updated>2024-12-04T00:03:27Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Model Tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
describe '.remove_participant' do&lt;br /&gt;
    before do&lt;br /&gt;
      allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(team_participant)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when the team participant exists' do&lt;br /&gt;
      it 'destroys the team participant' do&lt;br /&gt;
        expect(team_participant).to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    context 'when the team participant does not exist' do&lt;br /&gt;
      before do&lt;br /&gt;
        allow(TeamsParticipant).to receive(:find_by).with(user_id: user.id, team_id: team.id).and_return(nil)&lt;br /&gt;
      end&lt;br /&gt;
  &lt;br /&gt;
      it 'does not call destroy' do&lt;br /&gt;
        expect(team_participant).not_to receive(:destroy)&lt;br /&gt;
        TeamsParticipant.remove_team_participant(user.id, team.id)&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across most models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160326</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160326"/>
		<updated>2024-12-04T00:01:48Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Sample Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
We went ahead with updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across most models, controllers and views throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160323</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160323"/>
		<updated>2024-12-03T23:59:45Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Affected Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
   7. invitation.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
   9. review_mapping_controller.rb&lt;br /&gt;
   10. pair_programming_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160322</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160322"/>
		<updated>2024-12-03T23:58:28Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Affected Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rb&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160319</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160319"/>
		<updated>2024-12-03T23:53:21Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Detailed Test Plan for TeamsParticipant Model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
'''Test 1.''' Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
'''Test 2.''' Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
'''Test 3.''' Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
'''Test 4.''' Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
'''Test 5.''' Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
'''Test 6.''' Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
'''Test 7.''' Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
'''Test 8.''' Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160317</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160317"/>
		<updated>2024-12-03T23:52:19Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Detailed Test Plan for TeamsParticipant Model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
Test 1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
Test 2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
Test 3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
Test 4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
Test 5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
Test 6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
Test 7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
Test 8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160313</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160313"/>
		<updated>2024-12-03T23:51:52Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Detailed Test Plan for TeamsParticipant Model */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
Test 1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160286</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160286"/>
		<updated>2024-12-03T23:37:53Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160164</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160164"/>
		<updated>2024-12-03T06:55:51Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Model Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160163</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160163"/>
		<updated>2024-12-03T06:54:47Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Integration Tests= */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
==Model Tests==&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==Integration Tests==&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160162</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160162"/>
		<updated>2024-12-03T06:54:42Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Model Tests= */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
==Model Tests==&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
==Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160161</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160161"/>
		<updated>2024-12-03T06:54:33Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
==Model Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Integration Tests===&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160160</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160160"/>
		<updated>2024-12-03T06:54:09Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
==Model Tests&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Integration Tests&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160159</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160159"/>
		<updated>2024-12-03T06:53:40Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
==Model Tests&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe TeamsParticipant do&lt;br /&gt;
   describe 'team membership management' do&lt;br /&gt;
     it 'handles invite acceptance' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                  user_id: invited_user_id)&lt;br /&gt;
       expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
&lt;br /&gt;
     it 'manages pair programming status' do&lt;br /&gt;
       team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                  user_id: current_user.id)&lt;br /&gt;
       expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   describe 'review mapping' do&lt;br /&gt;
     it 'correctly identifies team membership' do&lt;br /&gt;
       expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                     user_id: participant.user_id)).to be_truthy&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Integration Tests&lt;br /&gt;
&lt;br /&gt;
 RSpec.describe 'Team Operations' do&lt;br /&gt;
   context 'when handling invitations' do&lt;br /&gt;
     it 'updates team membership after invite acceptance' do&lt;br /&gt;
       expect {&lt;br /&gt;
         TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
       }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   context 'when managing reviews' do&lt;br /&gt;
     it 'correctly assigns reviewers' do&lt;br /&gt;
       participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
       expect(participant).to be_present&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160158</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160158"/>
		<updated>2024-12-03T06:52:39Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
==Model Tests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;RSpec.describe TeamsParticipant do&lt;br /&gt;
  describe 'team membership management' do&lt;br /&gt;
    it 'handles invite acceptance' do&lt;br /&gt;
      team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                 user_id: invited_user_id)&lt;br /&gt;
      expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'manages pair programming status' do&lt;br /&gt;
      team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                 user_id: current_user.id)&lt;br /&gt;
      expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  describe 'review mapping' do&lt;br /&gt;
    it 'correctly identifies team membership' do&lt;br /&gt;
      expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                    user_id: participant.user_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Integration Tests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;RSpec.describe 'Team Operations' do&lt;br /&gt;
  context 'when handling invitations' do&lt;br /&gt;
    it 'updates team membership after invite acceptance' do&lt;br /&gt;
      expect {&lt;br /&gt;
        TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
      }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  context 'when managing reviews' do&lt;br /&gt;
    it 'correctly assigns reviewers' do&lt;br /&gt;
      participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
      expect(participant).to be_present&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160157</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160157"/>
		<updated>2024-12-03T06:51:35Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
The test plan for the TeamsParticipant refactoring will verify both the model's core functionality and its integration with the invitation and review mapping systems.&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
==Model Tests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RSpec.describe TeamsParticipant do&lt;br /&gt;
  describe 'team membership management' do&lt;br /&gt;
    it 'handles invite acceptance' do&lt;br /&gt;
      team_participant = TeamsParticipant.find_by(team_id: original_team_id, &lt;br /&gt;
                                                 user_id: invited_user_id)&lt;br /&gt;
      expect(team_participant.update(team_id: new_team_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    it 'manages pair programming status' do&lt;br /&gt;
      team_participant = TeamsParticipant.find_by(team_id: params[:team_id], &lt;br /&gt;
                                                 user_id: current_user.id)&lt;br /&gt;
      expect(team_participant.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  describe 'review mapping' do&lt;br /&gt;
    it 'correctly identifies team membership' do&lt;br /&gt;
      expect(TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                                    user_id: participant.user_id)).to be_truthy&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Integration Tests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
RSpec.describe 'Team Operations' do&lt;br /&gt;
  context 'when handling invitations' do&lt;br /&gt;
    it 'updates team membership after invite acceptance' do&lt;br /&gt;
      expect {&lt;br /&gt;
        TeamsParticipant.create(team_id: new_team_id, user_id: invited_user_id)&lt;br /&gt;
      }.to change { TeamsParticipant.count }.by(1)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  context 'when managing reviews' do&lt;br /&gt;
    it 'correctly assigns reviewers' do&lt;br /&gt;
      participant = TeamsParticipant.where(team_id: team_id).first&lt;br /&gt;
      expect(participant).to be_present&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160155</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160155"/>
		<updated>2024-12-03T06:01:33Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Pattern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.handle_pair_programming(team_id, user_id)&lt;br /&gt;
    user = TeamsParticipant.find_by(team_id: team_id, user_id: user_id)&lt;br /&gt;
    user.update_attributes(pair_programming_status: &amp;quot;A&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160154</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160154"/>
		<updated>2024-12-03T06:00:29Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Pattern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160153</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160153"/>
		<updated>2024-12-03T06:00:05Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Pattern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.find_team_id(assignment_id, user_id)&lt;br /&gt;
    TeamsParticipant.find_team_id(assignment_id, user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.exists_for_team?(team_id, user_id)&lt;br /&gt;
    TeamsParticipant.exists?(team_id: team_id, &lt;br /&gt;
                            user_id: user_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_team_participants(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.get_participants_for_review(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).each do |team_user|&lt;br /&gt;
      yield team_user&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160145</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160145"/>
		<updated>2024-12-03T05:24:50Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Affected Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers/Workers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160144</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160144"/>
		<updated>2024-12-03T05:24:28Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Affected Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160143</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160143"/>
		<updated>2024-12-03T05:24:11Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Affected Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: &lt;br /&gt;
   1. course_team.rbTeam, Participant, User, TeamsParticipant&lt;br /&gt;
   2. mentor_management.rb&lt;br /&gt;
   3. mentored_team.rb&lt;br /&gt;
   4. review_response_map.rb&lt;br /&gt;
   5. signed_up_team.rb&lt;br /&gt;
   6. tag_prompt_deployment.rb&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   2. grades_controller.rb&lt;br /&gt;
   3. join_team_requests_controller.rb&lt;br /&gt;
   4. lottery_controller.rb&lt;br /&gt;
   5. popup_controller.rb&lt;br /&gt;
   6. sign_up_sheet_controller.rb&lt;br /&gt;
   7. student_teams_controller.rb&lt;br /&gt;
   8. suggestion_controller.rb&lt;br /&gt;
&lt;br /&gt;
   Helpers:&lt;br /&gt;
   1. assignment_helper.rb&lt;br /&gt;
   2. manage_team_helper.rb&lt;br /&gt;
   3. review_mapping_helper.rb&lt;br /&gt;
   4. sign_up_sheet_helper.rb&lt;br /&gt;
   5. teams_users_helper.rb&lt;br /&gt;
   6. mail_worker.rb&lt;br /&gt;
&lt;br /&gt;
   Views:&lt;br /&gt;
   1. assignments/edit/_calibration.html.erb&lt;br /&gt;
   2. bookmarks/list.html.erb&lt;br /&gt;
   3. popup/participants_popup.html.erb&lt;br /&gt;
   4. reports/_teammate_review_report.html.erb&lt;br /&gt;
   5. response/response.html.erb&lt;br /&gt;
   6. review_mapping/_list_review_mappings.html.erb&lt;br /&gt;
   7. sign_up_sheet/show_team.html.erb&lt;br /&gt;
   8. student_teams/_received_invitations.html.erb&lt;br /&gt;
   9. student_teams/view.html.erb&lt;br /&gt;
   10. submitted_content/_hyperlink.html.erb&lt;br /&gt;
   &lt;br /&gt;
   Key Methods: update_users_topic_after_invite_accept, find_team_id, team_empty&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160139</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160139"/>
		<updated>2024-12-03T05:12:21Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Affected Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
   Models: Team, Participant, User, TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
   Controllers: &lt;br /&gt;
   1. assessment360_controller.rb&lt;br /&gt;
   &lt;br /&gt;
   Key Methods: update_users_topic_after_invite_accept, find_team_id, team_empty&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160138</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160138"/>
		<updated>2024-12-03T04:55:11Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Migration Strategy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
1. Models: Team, Participant, User, TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
2. Controllers: ReviewMappingController, PairProgrammingController, InvitationController&lt;br /&gt;
&lt;br /&gt;
3. Key Methods: update_users_topic_after_invite_accept, find_team_id, team_empty&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160137</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160137"/>
		<updated>2024-12-03T04:55:04Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Affected Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
1. Models: Team, Participant, User, TeamsParticipant&lt;br /&gt;
&lt;br /&gt;
2. Controllers: ReviewMappingController, PairProgrammingController, InvitationController&lt;br /&gt;
&lt;br /&gt;
3. Key Methods: update_users_topic_after_invite_accept, find_team_id, team_empty&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160136</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160136"/>
		<updated>2024-12-03T04:38:29Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Affected Components===&lt;br /&gt;
&lt;br /&gt;
1. Models: Team, Participant, User, TeamsParticipant&lt;br /&gt;
2. Controllers: ReviewMappingController, PairProgrammingController, InvitationController&lt;br /&gt;
3. Key Methods: update_users_topic_after_invite_accept, find_team_id, team_empty&lt;br /&gt;
&lt;br /&gt;
===Migration Strategy===&lt;br /&gt;
1. Create new TeamsParticipant model and table&lt;br /&gt;
2. Implement parallel methods in TeamsParticipant&lt;br /&gt;
3. Update controllers to use TeamsParticipant&lt;br /&gt;
4. Migrate existing data&lt;br /&gt;
5. Remove TeamsUser dependencies&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160134</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160134"/>
		<updated>2024-12-03T04:08:39Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Purpose */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern.&lt;br /&gt;
&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160133</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=160133"/>
		<updated>2024-12-03T04:08:28Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class currently serves as a join model between Team and Participant classes, managing team memberships for assignments and courses. However, it creates an architectural inconsistency by linking teams directly to users rather than participants, even though participants are the primary entities associated with assignments and courses throughout the rest of the application. The refactoring initiative will replace the TeamsUser class with a new TeamsParticipant class, bringing several key improvements:&lt;br /&gt;
&lt;br /&gt;
1. Align team management with the application's existing participant-based pattern&lt;br /&gt;
2. Creates proper associations between teams and participants within assignment contexts.&lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159351</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159351"/>
		<updated>2024-11-13T01:41:28Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Goal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159349</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159349"/>
		<updated>2024-11-13T01:41:02Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Goal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
         1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants throughout the app.&lt;br /&gt;
&lt;br /&gt;
         2. '''Simplify Application Logic:''' Align the team related management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies.&lt;br /&gt;
&lt;br /&gt;
         3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change.&lt;br /&gt;
&lt;br /&gt;
         4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class.&lt;br /&gt;
&lt;br /&gt;
         5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance.&lt;br /&gt;
&lt;br /&gt;
         6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process.&lt;br /&gt;
&lt;br /&gt;
         7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159344</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159344"/>
		<updated>2024-11-13T01:37:59Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Goal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal for this refactoring project is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. '''Enhance Data Model Consistency:''' Modify the association between teams and users to reflect a more accurate relationship between teams and participants within the context of assignments or courses&lt;br /&gt;
&lt;br /&gt;
2. '''Simplify Application Logic:''' Align the team membership management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies&lt;br /&gt;
&lt;br /&gt;
3. '''Improve Code Maintainability:''' Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change&lt;br /&gt;
&lt;br /&gt;
4. '''Increase Modularity:''' Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class&lt;br /&gt;
&lt;br /&gt;
5. '''Enhance Database Structure:''' Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance&lt;br /&gt;
&lt;br /&gt;
6. '''Ensure Backward Compatibility:''' Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process&lt;br /&gt;
&lt;br /&gt;
7. '''Improve Testability:''' Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159342</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159342"/>
		<updated>2024-11-13T01:37:09Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Goal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal for this refactoring project is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
1. Enhance Data Model Consistency: Modify the association between teams and users to reflect a more accurate relationship between teams and participants within the context of assignments or courses&lt;br /&gt;
&lt;br /&gt;
2. Simplify Application Logic: Align the team membership management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies&lt;br /&gt;
&lt;br /&gt;
Improve Code Maintainability: Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change&lt;br /&gt;
&lt;br /&gt;
Increase Modularity: Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class&lt;br /&gt;
&lt;br /&gt;
Enhance Database Structure: Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance&lt;br /&gt;
&lt;br /&gt;
Ensure Backward Compatibility: Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process&lt;br /&gt;
&lt;br /&gt;
Improve Testability: Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159341</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159341"/>
		<updated>2024-11-13T01:36:37Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Goal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal for this refactoring project is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
&lt;br /&gt;
              Enhance Data Model Consistency: Modify the association between teams and users to reflect a more accurate relationship between teams and participants within the context of assignments or courses&lt;br /&gt;
&lt;br /&gt;
Simplify Application Logic: Align the team membership management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies&lt;br /&gt;
&lt;br /&gt;
Improve Code Maintainability: Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change&lt;br /&gt;
&lt;br /&gt;
Increase Modularity: Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class&lt;br /&gt;
&lt;br /&gt;
Enhance Database Structure: Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance&lt;br /&gt;
&lt;br /&gt;
Ensure Backward Compatibility: Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process&lt;br /&gt;
&lt;br /&gt;
Improve Testability: Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159340</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159340"/>
		<updated>2024-11-13T01:36:16Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Goal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal for this refactoring project is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
Enhance Data Model Consistency: Modify the association between teams and users to reflect a more accurate relationship between teams and participants within the context of assignments or courses&lt;br /&gt;
&lt;br /&gt;
Simplify Application Logic: Align the team membership management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies&lt;br /&gt;
&lt;br /&gt;
Improve Code Maintainability: Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change&lt;br /&gt;
&lt;br /&gt;
Increase Modularity: Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class&lt;br /&gt;
&lt;br /&gt;
Enhance Database Structure: Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance&lt;br /&gt;
&lt;br /&gt;
Ensure Backward Compatibility: Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process&lt;br /&gt;
&lt;br /&gt;
Improve Testability: Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159337</id>
		<title>CSC/ECE 517 Fall 2024 - E2456. Refactor teams user.rb (Phase 2 - Design Document)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2024_-_E2456._Refactor_teams_user.rb_(Phase_2_-_Design_Document)&amp;diff=159337"/>
		<updated>2024-11-13T01:34:11Z</updated>

		<summary type="html">&lt;p&gt;Aagarw38: /* Design Goal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
&lt;br /&gt;
Expertiza is a web application through which students can submit and peer-review learning objects (articles, code, web sites, etc).&lt;br /&gt;
The National Science Foundation supports the Expertiza project.&lt;br /&gt;
It is used in select courses at NC State and by professors at several other colleges and universities.&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is a [http://rubyonrails.org/ Ruby on Rails] based open source project.&lt;br /&gt;
&lt;br /&gt;
==Problem Statement==&lt;br /&gt;
&lt;br /&gt;
The TeamsUser class in the Expertiza repository serves as a join model between the Team and Participant classes, establishing a many-to-many relationship. Its primary purpose is to manage team memberships within the context of assignments or courses, facilitating functionalities such as retrieving a user's name, deleting users or teams, and managing participant associations.&lt;br /&gt;
&lt;br /&gt;
The primary issue with the TeamsUser class is that it associates teams directly with users rather than with participants. In the context of the application, participants are users who are specifically associated with an assignment or a course. Since teams are formed within the scope of assignments or courses, handling team memberships through participants is more appropriate. Almost everywhere else, an assignment uses Participant objects rather than User objects. The exception is when it comes to Teams. It would simplify the design to use TeamsParticipants instead of TeamsUsers. &lt;br /&gt;
&lt;br /&gt;
==Design Goal==&lt;br /&gt;
The primary design goal for this refactoring project is to improve the data model and overall architecture of the Expertiza application by replacing the TeamsUser class with a more appropriate TeamsParticipant class. This change aims to achieve the following objectives:&lt;br /&gt;
Enhance Data Model Consistency: Modify the association between teams and users to reflect a more accurate relationship between teams and participants within the context of assignments or courses1&lt;br /&gt;
.&lt;br /&gt;
Simplify Application Logic: Align the team membership management with the existing pattern of using Participant objects rather than User objects throughout the application, reducing exceptions and inconsistencies1&lt;br /&gt;
.&lt;br /&gt;
Improve Code Maintainability: Refactor the codebase to use TeamsParticipant consistently, updating all relevant models, views, and controllers to reflect this change1&lt;br /&gt;
.&lt;br /&gt;
Increase Modularity: Apply design patterns such as the Facade Pattern and Repository Pattern to better organize responsibilities and simplify the interface of the TeamsParticipant class1&lt;br /&gt;
.&lt;br /&gt;
Enhance Database Structure: Update the database schema to include appropriate foreign keys and indexes for the TeamsParticipant table, improving data integrity and query performance1&lt;br /&gt;
.&lt;br /&gt;
Ensure Backward Compatibility: Implement the changes in phases, allowing for a gradual transition from TeamsUser to TeamsParticipant while maintaining functionality throughout the refactoring process1&lt;br /&gt;
.&lt;br /&gt;
Improve Testability: Develop comprehensive test cases for the new TeamsParticipant model and update existing tests to reflect the changes in associations and logic1&lt;br /&gt;
.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
To manage the complexity and responsibilities of the TeamsParticipant class, the following design patterns can be applied here. Since TeamsParticipant is handling both join table duties and additional business logic, a combination of patterns could improve maintainability and flexibility.&lt;br /&gt;
&lt;br /&gt;
1. '''Facade Pattern''' for Simplifying Interface&lt;br /&gt;
&lt;br /&gt;
The TeamsParticipant class handles multiple responsibilities, from managing teams and participants to removing members and adding members who accepted invites. Applying the Facade Pattern can simplify its interface by offloading complex processes to service classes. For example, a TeamsParticipantService could manage team membership rules, while TeamsParticipantManager could handle table-related operations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamParticipantService&lt;br /&gt;
  def self.add_accepted_invitee_to_team(inviter_participant_id, invited_participant_id, assignment_id)&lt;br /&gt;
    participants_teams = TeamsParticipant.where(participant_id: inviter_participant_id)&lt;br /&gt;
    participants_teams.any? do |team|&lt;br /&gt;
      assigned_team = AssignmentTeam.find_by(id: team.team_id, parent_id: assignment_id)&lt;br /&gt;
      assigned_team&amp;amp;.add_member(Participant.find(invited_participant_id), assignment_id) if assigned_team&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, within TeamsParticipant, these actions could be delegated to the facade for simplicity and modularity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipant &amp;lt; ApplicationRecord&lt;br /&gt;
  # Other associations and methods&lt;br /&gt;
  &lt;br /&gt;
  def self.add_accepted_invitee_to_team(*args)&lt;br /&gt;
    TeamParticipantService.add_accepted_invitee_to_team(*args)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. '''Repository Pattern''' for Database Queries&lt;br /&gt;
&lt;br /&gt;
The Repository Pattern would be useful for separating data access logic since this class is heavily querying the database for create, update, find operations. This involves creating a TeamsParticipantRepository that encapsulates all finders and queries, improving modularity and making it easier to test and reuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
class TeamsParticipantRepository&lt;br /&gt;
  def self.find_team_participant(participant_id, team_id)&lt;br /&gt;
    TeamsParticipant.find_by(participant_id: participant_id, team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.first_participant_for_team(team_id)&lt;br /&gt;
    TeamsParticipant.find_by(team_id: team_id)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def self.team_empty?(team_id)&lt;br /&gt;
    TeamsParticipant.where(team_id: team_id).empty?&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Class Diagram==&lt;br /&gt;
[[File:ClassDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Sequence Diagram==&lt;br /&gt;
[[File:SequenceDiagram_TeamsParticipant.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Solutions/Details of Changes Made==&lt;br /&gt;
&lt;br /&gt;
===Phase 1 Improvements===&lt;br /&gt;
&lt;br /&gt;
* Renamed TeamsUser to TeamsParticipant to modify application logic to join Teams with Participants instead of Users&lt;br /&gt;
* Updated associations in immediate neighbor classes i.e Teams, Users and Participants to ensure correctness and consistency in the data model&lt;br /&gt;
* Renamed method names for increased readability and removed redundant methods from the TeamsParticipant class&lt;br /&gt;
* Refactored methods: &amp;lt;code&amp;gt;add_accepted_invitee_to_team&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;find_team_id&amp;lt;/code&amp;gt; for efficiency and reducing complexity, improving overall maintainability of the codebase&lt;br /&gt;
* Renamed TeamUserNode to TeamParticipantNode for correctness, to align with the new design of Participation association in TeamsParticipant&lt;br /&gt;
* Added migrations to add foreign key for Participant in TeamsParticipant table and updated indexes for the same&lt;br /&gt;
&lt;br /&gt;
===Phase 2 Plan===&lt;br /&gt;
&lt;br /&gt;
* Update associations in all the models that were previously using TeamsUser to implement them with TeamsParticipant&lt;br /&gt;
* Modify implementations of all models, views, and controllers to use Participant with TeamsParticipant class instead of User&lt;br /&gt;
* This future involves modifying queries to retrieve participant and user objects that are passed to the TeamsParticipant class as commands to their methods&lt;br /&gt;
* Deprecate user_id foreign key from TeamsParticipant to completely remove the association of User from TeamsParticant, only linking Participants to Teams&lt;br /&gt;
* Update all the test cases to work with this implementation, including updating associations and mocking DB calls&lt;br /&gt;
&lt;br /&gt;
==Files Added/Modified==&lt;br /&gt;
&lt;br /&gt;
As part of the refactoring process, we need to update all references and method calls related to the TeamsParticipant table and the teams_participant class throughout the repository. This refactor will involve over 200 instances across various files.&lt;br /&gt;
&lt;br /&gt;
The required changes will follow the pattern shown in the attached modifications for models and controllers.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_model_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_mapping_controller_changes2.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_programming_controller_changes.png|1000px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Test Plan==&lt;br /&gt;
&lt;br /&gt;
We added a new spec file for the teams_participant model, which was previously missing, and fixed issues in the team_participant_controller_spec. Additionally, we resolved model and controller tests for direct associations with Team, User, and Participant.&lt;br /&gt;
&lt;br /&gt;
===Detailed '''Test Plan''' for &amp;lt;code&amp;gt;TeamsParticipant&amp;lt;/code&amp;gt; Model===&lt;br /&gt;
&lt;br /&gt;
1. Associations&lt;br /&gt;
&lt;br /&gt;
 Verify correct associations:&lt;br /&gt;
  * Belongs to participant&lt;br /&gt;
  * Belongs to team&lt;br /&gt;
  * Has one team_participant_node (dependent: destroy)&lt;br /&gt;
&lt;br /&gt;
2. Method: &amp;lt;code&amp;gt;#name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  Returns participant’s name.&lt;br /&gt;
  Appends &amp;quot;(Mentor)&amp;quot; if participant is a mentor.&lt;br /&gt;
&lt;br /&gt;
3. Method: &amp;lt;code&amp;gt;#delete&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Calls methods for cleanup:&lt;br /&gt;
  * remove_team_participant_node&lt;br /&gt;
  * remove_team_if_participants_empty&lt;br /&gt;
  * remove_teams_participant_instance&lt;br /&gt;
 Destroys itself and associated TeamParticipantNode.&lt;br /&gt;
 Deletes the team if it’s the last participant.&lt;br /&gt;
&lt;br /&gt;
4. Method: &amp;lt;code&amp;gt;.remove_participant&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Destroys TeamsParticipant if it exists.&lt;br /&gt;
 Does nothing if it doesn’t exist.&lt;br /&gt;
&lt;br /&gt;
5. Method: &amp;lt;code&amp;gt;.first_participant_for_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Retrieves the first participant for a given team ID.&lt;br /&gt;
&lt;br /&gt;
6. Method: &amp;lt;code&amp;gt;.team_empty?&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns true if team has no participants; false otherwise.&lt;br /&gt;
&lt;br /&gt;
7. Method: &amp;lt;code&amp;gt;.add_accepted_invitee_to_team&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Adds a participant to the team, returning true if successful.&lt;br /&gt;
&lt;br /&gt;
8. Method: &amp;lt;code&amp;gt;.team_id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 Returns team ID if participant is assigned to a team.&lt;br /&gt;
 Returns nil if not assigned.&lt;br /&gt;
&lt;br /&gt;
===Sample Changes===&lt;br /&gt;
&lt;br /&gt;
In the next phase, we’ll modify various associations, references, database calls, and methods related to the teams_participant model. This will involve updating table references as needed, adjusting or adding mocks for methods, and revising database queries involving the TeamsParticipant table.&lt;br /&gt;
&lt;br /&gt;
Below are examples of similar changes that need to be implemented across all model and controller specs throughout the repository.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''invitation_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Invitation_spec1.png|800px|center|]]&lt;br /&gt;
[[File:Invitation_spec2.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''review_mapping_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Review_map_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;'''pair_programming_controller_spec.rb'''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Pair_prog_controller_spec.png|800px|center|]]&lt;br /&gt;
&lt;br /&gt;
==Next Steps==&lt;br /&gt;
&lt;br /&gt;
Next, we’ll update all references and associations of TeamsUser to TeamsParticipant across the repository. This process includes adding and modifying existing test cases and implementing necessary database mocks. Currently, the TeamsParticipant table still holds foreign keys for users, as other models access TeamsParticipant through users.&lt;br /&gt;
&lt;br /&gt;
This can be further improved by replacing direct user associations with participants and retrieving participants through users. This shift will allow us to remove the foreign key constraint for users from the TeamsParticipant table, simplifying its structure. However, this change introduces the need for additional queries to retrieve a participant for a specific user_id before querying TeamsParticipant.&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
&lt;br /&gt;
====Mentor====&lt;br /&gt;
&lt;br /&gt;
* Jay, Patel&lt;br /&gt;
&lt;br /&gt;
====Members====&lt;br /&gt;
&lt;br /&gt;
* Agarwal, Arjit&lt;br /&gt;
* Manbhekar, Pranav&lt;br /&gt;
* Singhania, Chinmay&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
# [https://expertiza.ncsu.edu/ Expertiza]&lt;br /&gt;
# [https://docs.google.com/document/d/1fB9nHsop_yptjcj3CFn80BcZjXcSDbzcWwKvBDUTVrQ/edit?tab=t.0OSS Projects on Expertiza])&lt;br /&gt;
# [https://github.com/expertiza/expertiza Expertiza Github]&lt;br /&gt;
# [https://wiki.expertiza.ncsu.edu/index.php?title=Main_Page Expertiza Wiki]&lt;/div&gt;</summary>
		<author><name>Aagarw38</name></author>
	</entry>
</feed>