CSC/ECE 517 Spring 2024 - E2445. Implement BackEnd for participants.rb

From Expertiza_Wiki
Jump to navigation Jump to search

Expertiza

Expertiza stands out as an open-source initiative rooted in the Ruby on Rails framework, brought to life through the collective efforts of NC State's faculty and students. This web application supports instructors in creating tailored assignments that can either be new or build upon existing ones. Moreover, it allows for the organization of topics into a roster for student selection. Expertiza offers students the chance to team up for joint projects and assignments, promoting collaborative learning. A key feature of this platform is enabling students to peer-review their colleagues' work.

With its capability to handle a wide variety of document types, Expertiza accepts submissions in formats ranging from URLs to wiki pages. As an open-source learning management system crafted with Ruby on Rails, it boasts a broad range of features that facilitate the submission and peer review of diverse learning materials, including articles, code, and websites. Instructors and teaching assistants can easily monitor and evaluate these submissions, making Expertiza a valuable tool for managing course assignments.

Introduction

To develop the backend functionality for the participants controller of Expertiza, ensuring seamless integration with the enhanced user interface for participants. This involves setting up API endpoints for CRUD (Create, Read, Update, Delete) operations, integrating with the database, and ensuring data integrity and security. Our focus includes thorough rswag testing of the participants_controller method and demonstrating Swagger UI integration.

Problem Statement

The reimplementation project entails:

  1. CRUD Operations: Setting up CRUD (Create, Read, Update, Delete) functionalities in the controller to streamline data handling.
  2. Routes: Establishing pathways for accessing actions within the participants controller.
  3. Database: Maintaining a database for participant information, including their connections to "Assignment".
  4. Adherence to DRY Principle: Adhering to the Don't Repeat Yourself (DRY) principle to minimize redundancy and enhance coding efficiency.
  5. Testing with RSwag: Developing detailed tests using RSwag for every controller action, ensuring their performance and compatibility with Swagger UI. This includes a video tutorial to illustrate the integration with Swagger UI and the operational efficiency of the revamped controller.

Design

Implementation of Participants Controller

The Participants Controller is designed to handle various interactions with participant data within an application, providing a range of RESTful actions. This controller facilitates operations such as listing all participants, retrieving specific participant details, and creating, updating, or deleting participant records, all through JSON responses suitable for API usage. It includes actions that are traditionally used in view-based controllers (such as new and edit) to instantiate and prepare participants for creation or editing. Additionally, the controller offers a specialized action to fetch and render a participant's assignment, enhancing its functionality by addressing specific data retrieval needs. It also implements global error handling for missing records, ensuring that all actions gracefully handle cases where participants are not found. This comprehensive approach makes the controller a central part of the participant management system in the application, equipped to handle both standard CRUD operations and specific relational data accesses in a structured and efficient manner.

Implemented methods

"Create Method" Commit

  def create
     @participant = Participant.new(participant_params)
     if @participant.save
       render json: @participant, status: :created
     else
       render json: @participant.errors, status: :unprocessable_entity
     end
  end

create action will handle the addition of new participants. It will take participant information, conducts security validations, ensures data integrity, and inserts the new record into the database, responding with the participant's details in JSON format or an error message if the process fails.

"Read Method" Commit

   def index
     @participants = Participant.all
     render json: { participants: @participants }, status: :ok
   end

index action will accept a participant ID, retrieves the corresponding data from the database, and returns it as a JSON object. If the participant does not exist, it will send an error message.

"Update Method" Commit

   def update
     @participant = Participant.find(params[:id])
     if @participant.update(participant_params)
       render json: { participant: @participant }, status: :ok
     else
       render json: @participant.errors, status: :unprocessable_entity
     end
   end

update action will require a participant ID and the new data to be provided. The method will update the relevant record after security and data validation checks and returns the updated information in JSON format.

"Delete Method" Commit

   def destroy
     @participant = Participant.find(params[:id])
     @participant.destroy
     render json: { message: "Participant was successfully destroyed." }, status: :ok
   end

delete action will remove a participant's record using their ID, ensuring that the request is authenticated and the user is authorized to perform the deletion. Upon successful deletion, it will confirm the action with a success response; otherwise, it returns an error.

"Participants of a particular assignment Method" Commit

 def fetch_participants_for_assignment
   participants = Participant.where(assignment_id: params[:assignment_id])
   render json: participants, status: :ok
 end

The fetch_participants_for_assignment method will receive an assignment ID, this method will join the pertinent records from the participants and assignments tables, retrieving a comprehensive dataset that is then converted into a JSON array. This method will be instrumental for scenarios where a holistic view of assignment participation is required.

"Assignment of a particular Participant Method" Commit

   def fetch_assignment_for_participant
       participant = Participant.find(params[:participant_id])
       assignment = participant.assignment
   
       render json: assignment, status: :ok
   rescue ActiveRecord::RecordNotFound
       render json: { error: "Participant not found" }, status: :not_found
   end

The fetch_assignment_for_participant method is designed to retrieve the assignment associated with a specific participant. It takes a participant ID from the request parameters, finds the corresponding participant record, and accesses its associated assignment. The assignment data is then rendered as a JSON object.

Design Principles

Single Responsibility Principle (SRP):

  • Every function within the ParticipantsController will handle a distinct aspect of participant management.
  • The functions will undergo restructuring to delineate responsibilities like fetching data, performing calculations, and presenting views.
  • As an illustration, the view function will be dedicated to acquiring participant information.

Don't Repeat Yourself (DRY) Principle:

  • Redundant code within the ParticipantsController will be reduced by moving shared functionalities into auxiliary methods or modules.

Encapsulation:

  • The ParticipantsController will organize data and functionality into suitable methods and classes to reduce dependencies.
  • The scope of access to instance variables and controller actions will be restricted to foster encapsulation and ensure a clear division of responsibilities.

Testing Plan

We employ a combination of manual testing with tools like Postman, automated testing through RSpec, and API documentation and testing using Swagger. This comprehensive approach allows us to validate our API's functionality, security, and usability across various scenarios.

Manual testing with Postman

We are using Postman to test our APIs during the development process. Below are few examples:

  • GET /api/v1/participants: Endpoint to test the fetching of all Participants.

Fig 5.1.1 Postman UI displaying API testing to fetch all Participant.


  • POST /api/v1/participants: Endpoint to test the creation of a Participant.

Fig 5.1.2 Postman UI displaying API testing to create a Partcipant.


  • PATCH api/v1/participants/4: Endpoint to test the functionality of updating Participant using its ID.

Fig 5.1.3 Postman UI displaying API testing to update a Participant using its ID.


  • DELETE api/v1/participants/4: Endpoint to test the functionality of deleting a Participant with participant id.

Fig 5.1.4 Postman UI displaying API testing to delete a Participant using its ID.


  • GET api/v1/assignments/1/participants: Endpoint to test the functionality of fetching a participant using assignment Id.

Fig 5.1.5 Postman UI displaying API testing to fetch a participant using assignment Id.


  • GET api/v1/participants/1/assignment: Endpoint to test the functionality of fetching an assignment using participant Id.

Fig 5.1.5 Postman UI displaying API testing to fetch an assignment using participant Id.

Automated Testing with Rspec

Scenario 1: Creating a New Participant

Validates the creation of a new Participant with appropriate parameters.

Expectation: Expects a 201 Created status and a JSON response with the created participant details.

describe "POST #create" do
   context "with valid parameters" do
     it "creates a new participant" do
       expect {
         post :create, params: { participant: attributes_for(:participant) }
       }.to change(Participant, :count).by(1)
       expect(response).to have_http_status(:created)
     end
   end
 end

Scenario 2: Handling Invalid Participant Creation

Tests the creation process with invalid parameters to ensure robust error handling.

Expectation: Expects a 400 Bad Request status and an error message detailing the invalid parameters.

   context "with invalid parameters" do
     it "does not create a new participant" do
       expect {
         post :create, params: { participant: { user_id: nil } } 
       }.to change(Participant, :count).by(0)
       expect(response).to have_http_status(:unprocessable_entity)
     end
   end

Scenario 3: Fetch a Participant who is not in the database

Checks the behaviour when attempting to fetch a Participant not present in the database.

Expectation: Expects a not found status

   context "when the participant does not exist" do
     it "returns a not found status" do
       get :show, params: { id: -1 }
       expect(response).to have_http_status(:not_found)
     end
   end


Scenario 4: Fetching an Assignment of a particular Participant

Validates the functionality for fetching an Assignment of a particular Participant Id Expectation: Expects a 200 Ok status with the assignment of the participant.

 describe "#participant_assignment" do
   context "when participant exists" do
     it "returns the assignment of the participant" do
       get :participant_assignment, params: { participant_id: participant.id }
       expect(response).to have_http_status(:ok)
     end
   end
 end

Scenario 5: Fetching an Assignment of an invalid Participant

Validates the functionality for fetching an Assignment of an Invalid Participant Id

Expectation: Expects a not found status status.

context "when participant does not exist" do
     it "returns not found status" do
       get :participant_assignment, params: { participant_id: -1 }
       expect(response).to have_http_status(:not_found)
     end
   end

Scenario 6: Updating a Participant

Ensures that an existing participant can be updated with valid parameters.

Expectation: Expects a 200 OK status and the updated participant details in the response.

 describe "PATCH/PUT #update" do
   context "with valid parameters" do
     it "updates the participant" do
       patch :update, params: { id: participant.id, participant: { type: "NewType" } }
       expect(response).to have_http_status(:ok)
     end
   end
 end


Scenario 7: Updating a Participant

Checks the behavior when attempting to update a participant with invalid parameters.

Expectation: Expects a 422 Unprocessable Entity status and an error message detailing the issue.

   context "with invalid parameters" do
     it "does not update the participant" do
       patch :update, params: { id: participant.id, participant: { user_id: nil } }
       expect(response).to have_http_status(:unprocessable_entity)
     end
   end

API Documentation and Testing with Swagger

To provide clear, interactive API documentation, facilitating easy understanding and testing of API endpoints.

Setup: Integrate Swagger with Rails application using gems like rswag.

Documentation: Annotate the API code to generate Swagger documentation automatically. Ensure that each endpoint is clearly described, with information on parameters, request bodies, and response schemas. Interactive Testing: Use the Swagger UI to interactively test API endpoints directly from the browser, providing an easy way for non-developers to understand and verify API functionality.


                                                                 

                                                                       Fig 5.3 Swagger UI displaying API documentation and interactive testing interface for Participants endpoints.

Relevant Links


Team

Mentor
  • Chunduru Chetana
Members
  • Akhilsai Chittipolu
  • Koushik Gudipelly
  • Sri Vaishnavi Mylavarapu