CSC/ECE 517 Spring 2024 - E2417. Reimplement submitted content controller.rb

From Expertiza_Wiki
Jump to navigation Jump to search

E2417. Reimplement Submitted Content Controller

This page provides a description of the Expertiza based OSS Project E2417. Reimplement the SubmittedContentController

About Expertiza

Expertiza is an open-source web application facilitating peer feedback and assessment in educational courses. It enables students to submit work, review peers' submissions, and receive feedback. The platform supports anonymous peer reviews, grading rubrics, and discussion forums. Its goal is to enhance collaborative learning and improve the quality of student work through constructive criticism.

Objective

A submitted content controller should have the functionalities to manage the submitted content, for eg, the CRUD operations for submissions, different types of submissions, etc. The goal here is to implement this controller via API's and use principles of Object-Oriented Programming such as SOLID.

Problem Description

The reimplementation of SubmittedContentController in Expertiza needs to be done to enhance its functionality and maintainability. It should handle various tasks like file submissions and uploads, hyperlink submissions, and downloads, but the controller suffers from code redundancy and mixed responsibilities within methods. The reimplementation aims to ensure participants receive appropriate messages and HTTP status codes for actions like uploading files and deleting them, while also using SOLID principles, refactoring DRY code and minimizing excessive use of instance variables. The goal is to optimize the controller's design, adhering to best practices in readability and modularity.

Improvements in New Code

Index, show and create operations have been performed for the submission content controller.

  • Index method for Submitted Content
  • Show method for Submitted Content
  • Create method to Submit Content
  • SignedUpTopic Model
  • SignedUpTeam Model
  • SubmissionRecord Model
  • Duty Model
  • Late Policy Model
  • Submitted Content Helper

Index method for Submitted Content

 def index
   @submission_record = SubmissionRecord.all
   render json: @submission_record, status: :ok
 end

The index function is responsible for retrieving the data for the users. This function serves to fetch all submission records from the database using the `SubmissionRecord` model and assigns them to an instance variable `@submission_record`. The status: :ok parameter ensures that the HTTP response status is set to 200, indicating a successful request. This function operates on the HTTP GET method, allowing clients to request information from the server. The rendered JSON response includes the submission records, providing comprehensive data to clients.

Show method for Submitted Content

 def show
   @submission_record = SubmissionRecord.find(params[:id])
   render json: @submission_record, status: :ok
 rescue ActiveRecord::RecordNotFound => e
   render json: { error: e.message }, status: :not_found
 end

The show function enables clients to retrieve detailed information about specific submission records stored in the backend database and operates on HTTP GET method. The function retrieves the submission record associated with the provided ID using the SubmissionRecord.find(params[:id]) query. If the record is found, it is serialized into JSON format using the render method. If the record is not found, it renders a JSON response containing an error message conveying the exception's details, alongside an appropriate HTTP status code of :not_found (404).

Create method to Submit Content

 def create
   @submission_record = SubmissionRecord.create(submitted_content_params)
   if @submission_record.save
     render json: @submission_record, status: :created
   else
     render json: @submission_record.errors, status: :unprocessable_entity
   end
 end

The create function facilitates the creation of new submission records using HTTP POST method. The function initializes a new SubmissionRecord instance by passing the submitted content parameters obtained from the client to the SubmissionRecord.create method. If the record is successfully saved, indicating that the submission was processed without errors, the function renders a JSON response containing the newly created submission record along with an HTTP status code of :created (201), signifying successful record creation. If not, it renders a JSON response containing the errors encountered during the submission attempt, along with an appropriate HTTP status code of :unprocessable_entity (422), indicating that it cannot process it due to validation errors.

SignedUpTeam Model

The SignedUpTeam model represents the association between a topic and a team in the Expertiza project. Each instance of SignedUpTeam signifies that a particular team has signed up for a specific topic. This model facilitates the management and validation of these associations. This model is used by the Submitted Content Control so a skeleton for the same was implemented in this phase of the project.

   class SignedUpTeam < ApplicationRecord
     validates :topic_id, :team_id, presence: true
     scope :by_team_id, ->(team_id) { where('team_id = ?', team_id) }
   end


SignedUpTopic Model

The SignUpTopic model in the Expertiza project manages topics that users can sign up for within specific assignments. It provides functionalities for topic creation, modification, and retrieval. Additionally, it handles the association between topics and various other entities such as teams, due dates, bids, and assignment questionnaires. This model is used by the Submitted Content Control so a skeleton for the same was implemented in this phase of the project.

   class SignUpTopic < ApplicationRecord
     validates :topic_name, :assignment_id, :max_choosers, presence: true
     validates :topic_identifier, length: { maximum: 10 }
   end

SubmissionRecord Model

The SubmissionRecord model in the Expertiza project manages records of submissions made by users for specific assignments. It ensures that essential attributes related to the submission, such as content, operation, team ID, user, and assignment ID, are present through validations. This model is used by the Submitted Content Control so a skeleton for the same was implemented in this phase of the project.

   class SubmissionRecord < ApplicationRecord
       validates :content, presence: true
       validates :operation, presence: true
       validates :team_id, presence: true
       validates :user, presence: true
       validates :assignment_id, presence: true
   end  

Participant Model

Participant model is implemented in association with user submitting an assignment. This model is used by the Submitted Content Control so a skeleton for the same was implemented in this phase of the project.

   class Participant < ApplicationRecord
     validates :grade, numericality: { allow_nil: true }
   end


Assignment Model

Assignment model handles the assignment submission. This model is used by the Submitted Content Control so a skeleton for the same was implemented in this phase of the project.

   class Assignment < ApplicationRecord
   end

Assignment Participant Model

The AssignmentParticipant model extends the functionality of the Participant model, providing additional features and associations specific to assignments. This model is used by the Submitted Content Control so a skeleton for the same was implemented in this phase of the project.

   class AssignmentParticipant < Participant
     validates :handle, presence: true 
   end

SignUpSheet Model

The SignUpSheet model handles the signing up of users for topics within assignments. It provides methods for managing teams, confirming topics, adding signup topics, and importing signup data. This model is used by the Submitted Content Control so a skeleton for the same was implemented in this phase of the project.

   class SignUpSheet < ApplicationRecord
   end

Team Model

The Team model facilitates the management of teams. This model is used by the Submitted Content Control so a skeleton for the same was implemented in this phase of the project.

   class Team < ApplicationRecord
   end
   

Team User Model

The TeamUserNode model represents nodes in a tree structure associated with team users. This model is used by the Submitted Content Control so a skeleton for the same was implemented in this phase of the project.

   class TeamsUser < ApplicationRecord
   end

Duty Model

The Duty model in the Expertiza project manages duties assigned to individuals within teams. It validates the attributes of duties, including their names and maximum member counts, and provides a method for determining whether a duty can be assigned to a particular team. The Submitted Content Controller has an indirect dependency on this model. This model will be implemented in the next phase of the project.

Late Policy Model

The LatePolicy model in the Expertiza project manages late submission policies. It associates late policies with assignments. The model provides validations for policy attributes and methods for checking policy names and updating penalty objects when policies are modified. The Submitted Content Controller has an indirect dependency on this model. This model will be implemented in the next phase of the project.

Submitted Content Helper

The SubmittedContentHelper module facilitates the unzipping of files, aiding in the management of uploaded content within web applications. Its unzip_file method efficiently extracts the contents of a zip file to a specified directory, ensuring reliability. By leveraging the RubyZip gem, this module helps in the process of handling zip files, enhancing the backend's functionality.

Original Code

 module SubmittedContentHelper
   # Installing RubyZip
   # run the command,  gem install rubyzip
   # restart the server
   def self.unzip_file(file_name, unzip_dir, should_delete)
     # Checking if file exists.
     raise "File #{file_name} does not exist" unless File.exist?(file_name)
     # begin
     Zip::File.open(file_name) do |zf|
       zf.each do |e|
         safename = FileHelper.sanitize_filename(e.name)
         fpath = File.join(unzip_dir, safename)
         FileUtils.mkdir_p(File.dirname(fpath))
         zf.extract(e, fpath)
       end
     end
     if should_delete
       # The zip file is no longer needed, so delete it
       File.delete(file_name)
     end
   end
 end

Refactored Code

 module SubmittedContentHelper
   # Installing RubyZip
   # run the command,  gem install rubyzip
   # restart the server
   def self.unzip_file(file_name, unzip_dir, should_delete)
     # Checking if file exists.
     raise "File #{file_name} does not exist" unless File.exist?(file_name)
     # begin
     Zip::File.open(file_name) do |zf|
       zf.each do |e|
         extract_entry(e, unzip_dir)
       end
     end
     if should_delete
       # The zip file is no longer needed, so delete it
       File.delete(file_name)
     end
   end
   private
   def extract_entry(e, unzip_dir)
     safename = FileHelper.sanitize_filename(e.name)
     fpath = File.join(unzip_dir, safename)
     FileUtils.mkdir_p(File.dirname(fpath))
     zf.extract(e, fpath)
   end
 end

In the previous code, to extract files, it was tightly coupled with the unzip_files method, making it less reusable and harder to maintain. After refactoring the code, a separate private method is formed to unzip the file. By separating the extract_entry function into its own module or file, each component now has a single responsibility: the extract_entry function is responsible solely for extracting a single entry from a zip file. Single Responsibility Principle is followed.

Deployment Link

http://152.7.177.13:3000/api-docs

  • Credentials:
   Username: admin 
   Password: admin

Note: The authorization has been skipped to ensure smooth testing.

Github Repo

https://github.com/Neel317/reimplementation-back-end

PR Link

https://github.com/expertiza/reimplementation-back-end/pull/78/files

Links

  1. Github Repo
  2. Pull request

References

  1. Expertiza on GitHub
  2. The live Expertiza website
  3. Expertiza project documentation wiki
  4. Rspec Documentation