<?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=Acbondi</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=Acbondi"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Acbondi"/>
	<updated>2026-09-07T01:51:08Z</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_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152836</id>
		<title>CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152836"/>
		<updated>2023-12-06T22:05:12Z</updated>

		<summary type="html">&lt;p&gt;Acbondi: Refactored the documentation to be more easily read&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=='''Introduction'''==&lt;br /&gt;
The late_policies_controller.rb class houses the LatePoliciesController that controls the CRUD operations on late policies. However, there are many problems with the current implementation of this controller. In its current state, many functions are too long and repetitive as well as having inadequate variable names, comments, and error messages. This controller would benefit with optimizing its functions and various other aspects of the file.&lt;br /&gt;
&lt;br /&gt;
== About the LatePoliciesController ==&lt;br /&gt;
The LatePoliciesController provides CRUD functions to create, read, update, and destroy late policies. These include the index, show, new, edit, create, update, and destroy functions. Other functions are provided to allow it to work seamlessly within the framework of the overall project, including the action_allowed?, duplicate_name_check, validate_input, and various parameter and input functions. These additional functions are helper functions that ensure that the late policy can be created or updated based on if the user has the required permissions, doesn't enter a duplicate name, and inputs valid information to the late policy.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
*Refactor Long Methods: Longer functions should be refactored into smaller sub-functions to improve readability and make it easier for future alterations of the code.&lt;br /&gt;
*Improve Comments: More comments should be added to allow for users to easily follow through a given function and understand the specifics of its code statements.&lt;br /&gt;
*Follow the DRY Principle: Repeated code should be removed or moved into helper functions to allow for reusability of common code.&lt;br /&gt;
*Improve Testing: More tests should be created to ensure that everything works as intended and no unexpected errors occur, either exceptions or errors in logic.&lt;br /&gt;
*All changes must be done without the addition of new gems and must be clearly documented.&lt;br /&gt;
&lt;br /&gt;
== Functions to Optimize ==&lt;br /&gt;
*create: This function will be broken down into smaller functions to allow a more readable creation of new late policies. The error handling will also be altered to improve readability.&lt;br /&gt;
*update: Various comments will be added to the function as well as breaking down the code used for saving the late policy into a helper method to shorten the update method and make it more intuitive.&lt;br /&gt;
*duplicate_name_check: This function has various separate if statements that check for various things. These if statements will be broken down into separate helper methods to check for each individually. The duplicate_name_check function will be the main function that calls the various sub-functions so that it is clear what is being checked at a given step.&lt;br /&gt;
*validate_input: Similar to the duplicate_name_check function, this function has various if statements that can be refactored into smaller functions to check each input individually.&lt;br /&gt;
*Tests: Tests for creating and updating new late policies will be created. These tests will check for invalid inputs, correct error messages, etc. as well as ensure that edge cases are also captured correctly by the controller. New tests will also be created to ensure that previous functions, like the read and destroy functions, work correctly.&lt;br /&gt;
&lt;br /&gt;
=='''Create and Update'''==&lt;br /&gt;
&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     @late_policy = LatePolicy.new(late_policy_params)&lt;br /&gt;
     @late_policy.instructor_id = instructor_id&lt;br /&gt;
     begin&lt;br /&gt;
       @late_policy.save!&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully created.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while saving the late policy: '&lt;br /&gt;
       redirect_to action: 'new'&lt;br /&gt;
     end&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: 'new'&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       penalty_policy.save!&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully updated.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while updating the late policy: '&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
In the create and update methods, there are multiple if-else conditions and error handling which can be refactored for better readability and maintainability. The above code snippets represent the create and update functions. Both are very long and could benefit from splitting up the duplicated code and simplification.&lt;br /&gt;
&lt;br /&gt;
== Changes ==&lt;br /&gt;
&lt;br /&gt;
These functions were refactored into multiple new helper functions. They were created in the hopes to reduce the amount of repeated code as well as increase the readability and maintainability of said functions.&lt;br /&gt;
&lt;br /&gt;
Create: The create function has been simplified to improve its readability and size.&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   flash[:error] = error_message if error_message&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   begin&lt;br /&gt;
     if valid_penalty&lt;br /&gt;
       @late_policy = LatePolicy.new(params)&lt;br /&gt;
       @late_policy.instructor_id = instructor_id&lt;br /&gt;
       valid_penalty = save_late_policy&lt;br /&gt;
     end&lt;br /&gt;
   rescue StandardError&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # Redirect to new if there's an error, index if not&lt;br /&gt;
   redirect_to action: (valid_penalty ? 'index' : 'new')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Update: The update function received a similar improvement, being shortened and simplified.&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if !valid_penalty&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
     error_thrown = save_late_policy(true)&lt;br /&gt;
     # If there was an error thrown, go back to edit, otherwise go to index&lt;br /&gt;
     if error_thrown&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     else&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Both create and update have been refactored and split up into various helper functions, many of them to help reduce duplicate code and size in their caller.&lt;br /&gt;
 # Saves the late policy called from create or update&lt;br /&gt;
 def save_late_policy(from_update = false)&lt;br /&gt;
   begin&lt;br /&gt;
     @late_policy.save!&lt;br /&gt;
     # If the method that called this is update&lt;br /&gt;
     LatePolicy.update_calculated_penalty_objects(penalty_policy) if from_update&lt;br /&gt;
     # The code at the end of the string gets the name of the last method (create, update) and adds a d (created, updated)&lt;br /&gt;
     flash_for_save(from_update)&lt;br /&gt;
   rescue StandardError&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice&lt;br /&gt;
     flash[:error] = 'The following error occurred while saving the late policy: '&lt;br /&gt;
     return false&lt;br /&gt;
   end&lt;br /&gt;
   true&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def flash_for_save(from_update = false)&lt;br /&gt;
   flash[:notice] = &amp;quot;The late policy was successfully #{from_update ? 'updated' : 'created'}.&amp;quot;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The save_late_policy function has been refactored from duplicate code in both create and update. Both functions had very similar code with only one line of difference as well as a few characters in strings. This function shortens both of the other functions down by separating out this duplicate code into a private function. The same can be said for both the handle_error function. The flash_for_save function also improves the cognitive complexity of the save function by taking out an if statement into another function.&lt;br /&gt;
&lt;br /&gt;
=='''Validate_input'''==&lt;br /&gt;
&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty, error_message = duplicate_name_check(is_update)&lt;br /&gt;
   prefix = is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
   # This check validates the maximum penalty.&lt;br /&gt;
   if max_penalty &amp;lt; penalty_per_unit&lt;br /&gt;
     error_message = prefix + 'The maximum penalty cannot be less than penalty per unit.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This check validates the penalty per unit for a late policy.&lt;br /&gt;
   if penalty_per_unit &amp;lt; 0&lt;br /&gt;
     error_message = 'Penalty per unit cannot be negative.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This checks maximum penalty does not exceed 100.&lt;br /&gt;
   if max_penalty &amp;gt;= 100&lt;br /&gt;
     error_message = prefix + 'Maximum penalty cannot be greater than or equal to 100'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The validate_input method is quite lengthy and has multiple conditions being checked. It might be worth breaking down this method into smaller functions, each handling a specific validation to make this function more readable.&lt;br /&gt;
&lt;br /&gt;
== Changes ==&lt;br /&gt;
&lt;br /&gt;
The validate_input function was originally very long and confusing. It has since been simplified down and separated into helper functions so each function only has one job.&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   error_messages = []&lt;br /&gt;
   # Validates the name is not a duplicate&lt;br /&gt;
   valid_penalty, name_error = duplicate_name_check(is_update)&lt;br /&gt;
   error_messages &amp;lt;&amp;lt; name_error if name_error&lt;br /&gt;
   # This validates the max_penalty to make sure it's within the correct range&lt;br /&gt;
   if max_penalty_valid(max_penalty, penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;#{error_prefix(is_update)}The maximum penalty must be between the penalty per unit and 100.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This validates the penalty_per_unit and makes sure it's not negative&lt;br /&gt;
   if penalty_per_unit_valid(penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; 'Penalty per unit cannot be negative.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   [valid_penalty, error_messages.join(&amp;quot;\n&amp;quot;)]&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validate the maximum penalty and ensure it's in the correct range&lt;br /&gt;
 def max_penalty_valid(max_penalty, penalty_per_unit)&lt;br /&gt;
   max_penalty &amp;lt; penalty_per_unit || max_penalty &amp;gt; 100&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validates the penalty per unit&lt;br /&gt;
 def penalty_per_unit_valid(penalty_per_unit)&lt;br /&gt;
   penalty_per_unit &amp;lt; 0&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validation error prefix&lt;br /&gt;
 def error_prefix(is_update)&lt;br /&gt;
   is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The new validate_input function has combined two of the conditions that validated the same input, max_penalty, into one helper function, max_penalty_valid. This new helper function validates everything with max_penalty. Additionally, the penalty_per_unit validation is moved to another new function. The new error_prefix function is a small helper function that obtains the prefix for specific errors, as per the original validate_input. Lastly, the original validate_input function returned the last error it found, overwriting all previous errors in favor of the last. This new validate_input returns all errors that are found in one big String.&lt;br /&gt;
&lt;br /&gt;
=='''Duplicate Name Check'''==&lt;br /&gt;
 if is_update&lt;br /&gt;
      existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
      if existing_late_policy.policy_name == params[:late_policy][:policy_name]&lt;br /&gt;
        should_check = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if should_check&lt;br /&gt;
      if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
        error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
        valid_penalty = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
The above code is the current implementation of some duplication checks in this function. These if statements can be refactored into smaller sub-functions.&lt;br /&gt;
The pseudo-code for one sub-function is as follows:&lt;br /&gt;
 if should_check_policy_name&lt;br /&gt;
   Call sub-function should_check_policy_name&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def should_check_policy_name(old valid_penalty, old error_message)&lt;br /&gt;
   if check policy with same name(currenty name, instructor_id)&lt;br /&gt;
     error_message = new error message&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
&lt;br /&gt;
In the above sub-function, the should_check name was changed to be more explicit and the should check if-statement was refactored to be in a different method to improve readability.&lt;br /&gt;
&lt;br /&gt;
== Changes ==&lt;br /&gt;
&lt;br /&gt;
The def duplicate_name_check function was originally also long not reusable according to DRY principles. It has since been simplified down and separated into helper functions so each function only has one job.&lt;br /&gt;
 # This function checks if the policy name already exists or not and returns boolean value for penalty and the error message.&lt;br /&gt;
  def duplicate_name_check(is_update = false)&lt;br /&gt;
    valid_penalty, error_message = true, nil&lt;br /&gt;
    prefix = is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
  &lt;br /&gt;
    if should_check_policy_name?(is_update)&lt;br /&gt;
      valid_penalty, error_message = check_for_duplicate_name(prefix)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return valid_penalty, error_message&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This is a helper function for the duplicate name check&lt;br /&gt;
  def should_check_policy_name?(is_update)&lt;br /&gt;
    # If the function is called in the context of updating a policy&lt;br /&gt;
    if is_update&lt;br /&gt;
        # Find the existing late policy by its ID&lt;br /&gt;
        existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
        # Check if the policy name in the request is different from the existing policy's name&lt;br /&gt;
        # Return true if they are different, indicating a need to check the policy name&lt;br /&gt;
        return existing_late_policy.policy_name != params[:late_policy][:policy_name]&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This is a helper function for the duplicate name check&lt;br /&gt;
  def check_for_duplicate_name(prefix)&lt;br /&gt;
    # Using `exists?` to check if a LatePolicy with the same name already exists for the instructor.&lt;br /&gt;
    # It's assumed that `params[:late_policy][:policy_name]` holds the name of the policy and &lt;br /&gt;
    # `instructor_id` is the ID of the instructor.&lt;br /&gt;
    if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
      error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
      valid_penalty = false&lt;br /&gt;
    else&lt;br /&gt;
      # If no duplicate name is found, set valid_penalty to true&lt;br /&gt;
      valid_penalty = true&lt;br /&gt;
      error_message = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Return the validity status of the penalty and the corresponding error message, if any&lt;br /&gt;
    return valid_penalty, error_message&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
The new duplicate_name_check function has been simplified down to using two helper functions to simplify the functionality of the code. It uses the should_check_policy_name and check_for_duplicate_name to make sure that there are no duplicate late policies. Each helper function has its own functionality, the first one, should_check_policy_name makes sure we need to check if there is a duplicate. The second one, check_for_duplicate_name is only used if we do need to check the duplicate and it returns whether it is valid and the error message. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Proposed Solution'''==&lt;br /&gt;
&lt;br /&gt;
There are multiple routes we can go down to tackle this issue. One way to break down a long method would be to refactor the create method, we can extract and rewrite the save_late_policy method. We also have to refactor the duplicate name check method by rewriting the if statements as smaller sub methods. We would then have to write tests for all the new functionality/refactoring done.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Test Changes ==&lt;br /&gt;
&lt;br /&gt;
Various duplicate code in the latest_policies_controller_spec file has been factored out into helper functions.&lt;br /&gt;
&lt;br /&gt;
 def create_late_policy(policy_name, max_penalty, penalty_per_unit, instructor_id) &lt;br /&gt;
   late_policy = LatePolicy.new&lt;br /&gt;
   late_policy.policy_name = policy_name&lt;br /&gt;
   late_policy.max_penalty = max_penalty&lt;br /&gt;
   late_policy.penalty_per_unit = penalty_per_unit&lt;br /&gt;
   late_policy.instructor_id = instructor_id&lt;br /&gt;
   late_policy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def request_params(policy_name, max_penalty, penalty_per_unit) {&lt;br /&gt;
   late_policy: {&lt;br /&gt;
     max_penalty: max_penalty,&lt;br /&gt;
     penalty_per_unit: penalty_per_unit,&lt;br /&gt;
     policy_name: policy_name&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def request_params_with_id(policy_name, max_penalty, penalty_per_unit, id) {&lt;br /&gt;
   late_policy: {&lt;br /&gt;
     max_penalty: max_penalty,&lt;br /&gt;
     penalty_per_unit: penalty_per_unit,&lt;br /&gt;
     policy_name: policy_name&lt;br /&gt;
   },&lt;br /&gt;
   id: id&lt;br /&gt;
 }&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Create an RSpec example to reduce code duplication&lt;br /&gt;
 RSpec.shared_examples 'late policy creation with error' do |policy_name, max_penalty, penalty_per_unit, expected_error|&lt;br /&gt;
   before(:each) do&lt;br /&gt;
     latePolicy = LatePolicy.new&lt;br /&gt;
     allow(latePolicy).to receive(:check_policy_with_same_name).with(any_args).and_return(false)&lt;br /&gt;
   end&lt;br /&gt;
   it 'throws a flash error' do&lt;br /&gt;
     post :create, params: request_params(policy_name, max_penalty, penalty_per_unit)&lt;br /&gt;
     expect(flash[:error]).to eq(expected_error)&lt;br /&gt;
     expect(response).to redirect_to('/late_policies/new')&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
These additions to the test file, late_policies_controller_spec.rb, helps reduce duplicate code in the test by refactoring the shared components into these helper methods. Each helper method sets up specific late_policies to be used in various tests in the file.&lt;/div&gt;</summary>
		<author><name>Acbondi</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152665</id>
		<title>CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152665"/>
		<updated>2023-12-05T05:06:03Z</updated>

		<summary type="html">&lt;p&gt;Acbondi: Updated the wiki with the new changes to the code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=='''Introduction'''==&lt;br /&gt;
The late_policies_controller.rb class houses the LatePoliciesController that controls the CRUD operations on late policies. However, there are many problems with the current implementation of this controller. In its current state, many functions are too long and repetitive as well as having inadequate variable names, comments, and error messages. This controller would benefit with optimizing its functions and various other aspects of the file.&lt;br /&gt;
&lt;br /&gt;
== About the LatePoliciesController ==&lt;br /&gt;
The LatePoliciesController provides CRUD functions to create, read, update, and destroy late policies. These include the index, show, new, edit, create, update, and destroy functions. Other functions are provided to allow it to work seamlessly within the framework of the overall project, including the action_allowed?, duplicate_name_check, validate_input, and various parameter and input functions. These additional functions are helper functions that ensure that the late policy can be created or updated based on if the user has the required permissions, doesn't enter a duplicate name, and inputs valid information to the late policy.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
*Refactor Long Methods: Longer functions should be refactored into smaller sub-functions to improve readability and make it easier for future alterations of the code.&lt;br /&gt;
*Improve Comments: More comments should be added to allow for users to easily follow through a given function and understand the specifics of its code statements.&lt;br /&gt;
*Follow the DRY Principle: Repeated code should be removed or moved into helper functions to allow for reusability of common code.&lt;br /&gt;
*Improve Testing: More tests should be created to ensure that everything works as intended and no unexpected errors occur, either exceptions or errors in logic.&lt;br /&gt;
*All changes must be done without the addition of new gems and must be clearly documented.&lt;br /&gt;
&lt;br /&gt;
== Functions to Optimize ==&lt;br /&gt;
*create: This function will be broken down into smaller functions to allow a more readable creation of new late policies. The error handling will also be altered to improve readability.&lt;br /&gt;
*update: Various comments will be added to the function as well as breaking down the code used for saving the late policy into a helper method to shorten the update method and make it more intuitive.&lt;br /&gt;
*duplicate_name_check: This function has various separate if statements that check for various things. These if statements will be broken down into separate helper methods to check for each individually. The duplicate_name_check function will be the main function that calls the various sub-functions so that it is clear what is being checked at a given step.&lt;br /&gt;
*validate_input: Similar to the duplicate_name_check function, this function has various if statements that can be refactored into smaller functions to check each input individually.&lt;br /&gt;
*Tests: Tests for creating and updating new late policies will be created. These tests will check for invalid inputs, correct error messages, etc. as well as ensure that edge cases are also captured correctly by the controller. New tests will also be created to ensure that previous functions, like the read and destroy functions, work correctly.&lt;br /&gt;
&lt;br /&gt;
== Create and Update Functions ==&lt;br /&gt;
&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     @late_policy = LatePolicy.new(late_policy_params)&lt;br /&gt;
     @late_policy.instructor_id = instructor_id&lt;br /&gt;
     begin&lt;br /&gt;
       @late_policy.save!&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully created.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while saving the late policy: '&lt;br /&gt;
       redirect_to action: 'new'&lt;br /&gt;
     end&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: 'new'&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       penalty_policy.save!&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully updated.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while updating the late policy: '&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
In the create and update methods, there are multiple if-else conditions and error handling which can be refactored for better readability and maintainability. The above code snippets represent the create and update functions. Both are very long and could benefit from splitting up the duplicated code and simplification.&lt;br /&gt;
&lt;br /&gt;
== Validate_input Function ==&lt;br /&gt;
&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty, error_message = duplicate_name_check(is_update)&lt;br /&gt;
   prefix = is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
   # This check validates the maximum penalty.&lt;br /&gt;
   if max_penalty &amp;lt; penalty_per_unit&lt;br /&gt;
     error_message = prefix + 'The maximum penalty cannot be less than penalty per unit.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This check validates the penalty per unit for a late policy.&lt;br /&gt;
   if penalty_per_unit &amp;lt; 0&lt;br /&gt;
     error_message = 'Penalty per unit cannot be negative.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This checks maximum penalty does not exceed 100.&lt;br /&gt;
   if max_penalty &amp;gt;= 100&lt;br /&gt;
     error_message = prefix + 'Maximum penalty cannot be greater than or equal to 100'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The validate_input method is quite lengthy and has multiple conditions being checked. It might be worth breaking down this method into smaller functions, each handling a specific validation to make this function more readable.&lt;br /&gt;
&lt;br /&gt;
== Duplicate Name Check Function ==&lt;br /&gt;
 if is_update&lt;br /&gt;
      existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
      if existing_late_policy.policy_name == params[:late_policy][:policy_name]&lt;br /&gt;
        should_check = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if should_check&lt;br /&gt;
      if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
        error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
        valid_penalty = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
The above code is the current implementation of some duplication checks in this function. These if statements can be refactored into smaller sub-functions.&lt;br /&gt;
The pseudo-code for one sub-function is as follows:&lt;br /&gt;
 if should_check_policy_name&lt;br /&gt;
   Call sub-function should_check_policy_name&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def should_check_policy_name(old valid_penalty, old error_message)&lt;br /&gt;
   if check policy with same name(currenty name, instructor_id)&lt;br /&gt;
     error_message = new error message&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
&lt;br /&gt;
In the above sub-function, the should_check name was changed to be more explicit and the should check if-statement was refactored to be in a different method to improve readability.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Proposed Solution'''==&lt;br /&gt;
&lt;br /&gt;
There are multiple routes we can go down to tackle this issue. One way to break down a long method would be to refactor the create method, we can extract and rewrite the save_late_policy method. We also have to refactor the duplicate name check method by rewriting the if statements as smaller sub methods. We would then have to write tests for all the new functionality/refactoring done.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Updated Works'''==&lt;br /&gt;
&lt;br /&gt;
== Create and Update ==&lt;br /&gt;
&lt;br /&gt;
The Create and Update functions were refactored into multiple new helper functions. These functions were created in the hopes to reduce the amount of repeated code as well as increase the readability and maintainability of said functions.&lt;br /&gt;
&lt;br /&gt;
Create: The create function has been simplified to improve its readability and size.&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   flash[:error] = error_message if error_message&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   begin&lt;br /&gt;
     if valid_penalty&lt;br /&gt;
       @late_policy = LatePolicy.new(params)&lt;br /&gt;
       @late_policy.instructor_id = instructor_id&lt;br /&gt;
       valid_penalty = save_late_policy&lt;br /&gt;
     end&lt;br /&gt;
   rescue StandardError&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # Redirect to new if there's an error, index if not&lt;br /&gt;
   redirect_to action: (valid_penalty ? 'index' : 'new')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Update: The update function received a similar improvement, being shortened and simplified.&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if !valid_penalty&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
     error_thrown = save_late_policy(true)&lt;br /&gt;
     # If there was an error thrown, go back to edit, otherwise go to index&lt;br /&gt;
     if error_thrown&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     else&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Both create and update have been refactored and split up into various helper functions, many of them to help reduce duplicate code and size in their caller.&lt;br /&gt;
 # Saves the late policy called from create or update&lt;br /&gt;
 def save_late_policy(from_update = false)&lt;br /&gt;
   begin&lt;br /&gt;
     @late_policy.save!&lt;br /&gt;
     # If the method that called this is update&lt;br /&gt;
     LatePolicy.update_calculated_penalty_objects(penalty_policy) if from_update&lt;br /&gt;
     # The code at the end of the string gets the name of the last method (create, update) and adds a d (created, updated)&lt;br /&gt;
     flash_for_save(from_update)&lt;br /&gt;
   rescue StandardError&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice&lt;br /&gt;
     flash[:error] = 'The following error occurred while saving the late policy: '&lt;br /&gt;
     return false&lt;br /&gt;
   end&lt;br /&gt;
   true&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def flash_for_save(from_update = false)&lt;br /&gt;
   flash[:notice] = &amp;quot;The late policy was successfully #{from_update ? 'updated' : 'created'}.&amp;quot;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The save_late_policy function has been refactored from duplicate code in both create and update. Both functions had very similar code with only one line of difference as well as a few characters in strings. This function shortens both of the other functions down by separating out this duplicate code into a private function. The same can be said for both the handle_error function. The flash_for_save function also improves the cognitive complexity of the save function by taking out an if statement into another function.&lt;br /&gt;
&lt;br /&gt;
== Validate_input ==&lt;br /&gt;
&lt;br /&gt;
The validate_input function was originally very long and confusing. It has since been simplified down and separated into helper functions so each function only has one job.&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   error_messages = []&lt;br /&gt;
   # Validates the name is not a duplicate&lt;br /&gt;
   valid_penalty, name_error = duplicate_name_check(is_update)&lt;br /&gt;
   error_messages &amp;lt;&amp;lt; name_error if name_error&lt;br /&gt;
   # This validates the max_penalty to make sure it's within the correct range&lt;br /&gt;
   if max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;#{error_prefix(is_update)}The maximum penalty must be between the penalty per unit and 100.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This validates the penalty_per_unit and makes sure it's not negative&lt;br /&gt;
   if penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; 'Penalty per unit cannot be negative.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   [valid_penalty, error_messages.join(&amp;quot;\n&amp;quot;)]&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validate the maximum penalty and ensure it's in the correct range&lt;br /&gt;
 def max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
   max_penalty &amp;lt; penalty_per_unit || max_penalty &amp;gt; 100&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validates the penalty per unit&lt;br /&gt;
 def penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
   penalty_per_unit &amp;lt; 0&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validation error prefix&lt;br /&gt;
 def error_prefix(is_update)&lt;br /&gt;
   is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The new validate_input function has combined two of the conditions that validated the same input, max_penalty, into one helper function, max_penalty_validation. This new helper function validates everything with max_penalty. Additionally, the penalty_per_unit validation is moved to another new function. The new error_prefix function is a small helper function that obtains the prefix for specific errors, as per the original validate_input. Lastly, the original validate_input function returned the last error it found, overwriting all previous errors in favor of the last. This new validate_input returns all errors that are found in one big String.&lt;br /&gt;
&lt;br /&gt;
== Duplicate Name Check Function ==&lt;br /&gt;
&lt;br /&gt;
The def duplicate_name_check function was originally also long not reusable according to DRY principles. It has since been simplified down and separated into helper functions so each function only has one job.&lt;br /&gt;
 # This function checks if the policy name already exists or not and returns boolean value for penalty and the error message.&lt;br /&gt;
  def duplicate_name_check(is_update = false)&lt;br /&gt;
    valid_penalty, error_message = true, nil&lt;br /&gt;
    prefix = is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
  &lt;br /&gt;
    if should_check_policy_name?(is_update)&lt;br /&gt;
      valid_penalty, error_message = check_for_duplicate_name(prefix)&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    return valid_penalty, error_message&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This is a helper function for the duplicate name check&lt;br /&gt;
  def should_check_policy_name?(is_update)&lt;br /&gt;
    # If the function is called in the context of updating a policy&lt;br /&gt;
    if is_update&lt;br /&gt;
        # Find the existing late policy by its ID&lt;br /&gt;
        existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
        # Check if the policy name in the request is different from the existing policy's name&lt;br /&gt;
        # Return true if they are different, indicating a need to check the policy name&lt;br /&gt;
        return existing_late_policy.policy_name != params[:late_policy][:policy_name]&lt;br /&gt;
    end&lt;br /&gt;
    return true&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This is a helper function for the duplicate name check&lt;br /&gt;
  def check_for_duplicate_name(prefix)&lt;br /&gt;
    # Using `exists?` to check if a LatePolicy with the same name already exists for the instructor.&lt;br /&gt;
    # It's assumed that `params[:late_policy][:policy_name]` holds the name of the policy and &lt;br /&gt;
    # `instructor_id` is the ID of the instructor.&lt;br /&gt;
    if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
      error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
      valid_penalty = false&lt;br /&gt;
    else&lt;br /&gt;
      # If no duplicate name is found, set valid_penalty to true&lt;br /&gt;
      valid_penalty = true&lt;br /&gt;
      error_message = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Return the validity status of the penalty and the corresponding error message, if any&lt;br /&gt;
    return valid_penalty, error_message&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
The new duplicate_name_check function has been simplified down to using two helper functions to simplify the functionality of the code. It uses the should_check_policy_name and check_for_duplicate_name to make sure that there are no duplicate late policies. Each helper function has its own functionality, the first one, should_check_policy_name makes sure we need to check if there is a duplicate. The second one, check_for_duplicate_name is only used if we do need to check the duplicate and it returns whether it is valid and the error message. &lt;br /&gt;
&lt;br /&gt;
== Test Changes ==&lt;br /&gt;
&lt;br /&gt;
Various duplicate code in the latest_policies_controller_spec file has been factored out into helper functions.&lt;br /&gt;
&lt;br /&gt;
 def create_late_policy(policy_name, max_penalty, penalty_per_unit, instructor_id) &lt;br /&gt;
   late_policy = LatePolicy.new&lt;br /&gt;
   late_policy.policy_name = policy_name&lt;br /&gt;
   late_policy.max_penalty = max_penalty&lt;br /&gt;
   late_policy.penalty_per_unit = penalty_per_unit&lt;br /&gt;
   late_policy.instructor_id = instructor_id&lt;br /&gt;
   late_policy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def request_params(policy_name, max_penalty, penalty_per_unit) {&lt;br /&gt;
   late_policy: {&lt;br /&gt;
     max_penalty: max_penalty,&lt;br /&gt;
     penalty_per_unit: penalty_per_unit,&lt;br /&gt;
     policy_name: policy_name&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def request_params_with_id(policy_name, max_penalty, penalty_per_unit, id) {&lt;br /&gt;
   late_policy: {&lt;br /&gt;
     max_penalty: max_penalty,&lt;br /&gt;
     penalty_per_unit: penalty_per_unit,&lt;br /&gt;
     policy_name: policy_name&lt;br /&gt;
   },&lt;br /&gt;
   id: id&lt;br /&gt;
 }&lt;br /&gt;
 end&lt;/div&gt;</summary>
		<author><name>Acbondi</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152372</id>
		<title>CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152372"/>
		<updated>2023-12-04T23:17:17Z</updated>

		<summary type="html">&lt;p&gt;Acbondi: Changed the code segments in the Updated&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=='''Introduction'''==&lt;br /&gt;
The late_policies_controller.rb class houses the LatePoliciesController that controls the CRUD operations on late policies. However, there are many problems with the current implementation of this controller. In its current state, many functions are too long and repetitive as well as having inadequate variable names, comments, and error messages. This controller would benefit with optimizing its functions and various other aspects of the file.&lt;br /&gt;
&lt;br /&gt;
== About the LatePoliciesController ==&lt;br /&gt;
The LatePoliciesController provides CRUD functions to create, read, update, and destroy late policies. These include the index, show, new, edit, create, update, and destroy functions. Other functions are provided to allow it to work seamlessly within the framework of the overall project, including the action_allowed?, duplicate_name_check, validate_input, and various parameter and input functions. These additional functions are helper functions that ensure that the late policy can be created or updated based on if the user has the required permissions, doesn't enter a duplicate name, and inputs valid information to the late policy.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
*Refactor Long Methods: Longer functions should be refactored into smaller sub-functions to improve readability and make it easier for future alterations of the code.&lt;br /&gt;
*Improve Comments: More comments should be added to allow for users to easily follow through a given function and understand the specifics of its code statements.&lt;br /&gt;
*Follow the DRY Principle: Repeated code should be removed or moved into helper functions to allow for reusability of common code.&lt;br /&gt;
*Improve Testing: More tests should be created to ensure that everything works as intended and no unexpected errors occur, either exceptions or errors in logic.&lt;br /&gt;
*All changes must be done without the addition of new gems and must be clearly documented.&lt;br /&gt;
&lt;br /&gt;
== Functions to Optimize ==&lt;br /&gt;
*create: This function will be broken down into smaller functions to allow a more readable creation of new late policies. The error handling will also be altered to improve readability.&lt;br /&gt;
*update: Various comments will be added to the function as well as breaking down the code used for saving the late policy into a helper method to shorten the update method and make it more intuitive.&lt;br /&gt;
*duplicate_name_check: This function has various separate if statements that check for various things. These if statements will be broken down into separate helper methods to check for each individually. The duplicate_name_check function will be the main function that calls the various sub-functions so that it is clear what is being checked at a given step.&lt;br /&gt;
*validate_input: Similar to the duplicate_name_check function, this function has various if statements that can be refactored into smaller functions to check each input individually.&lt;br /&gt;
*Tests: Tests for creating and updating new late policies will be created. These tests will check for invalid inputs, correct error messages, etc. as well as ensure that edge cases are also captured correctly by the controller. New tests will also be created to ensure that previous functions, like the read and destroy functions, work correctly.&lt;br /&gt;
&lt;br /&gt;
== Create and Update Functions ==&lt;br /&gt;
&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     @late_policy = LatePolicy.new(late_policy_params)&lt;br /&gt;
     @late_policy.instructor_id = instructor_id&lt;br /&gt;
     begin&lt;br /&gt;
       @late_policy.save!&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully created.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while saving the late policy: '&lt;br /&gt;
       redirect_to action: 'new'&lt;br /&gt;
     end&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: 'new'&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       penalty_policy.save!&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully updated.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while updating the late policy: '&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
In the create and update methods, there are multiple if-else conditions and error handling which can be refactored for better readability and maintainability. The above code snippets represent the create and update functions. Both are very long and could benefit from splitting up the duplicated code and simplification.&lt;br /&gt;
&lt;br /&gt;
== Validate_input Function ==&lt;br /&gt;
&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty, error_message = duplicate_name_check(is_update)&lt;br /&gt;
   prefix = is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
   # This check validates the maximum penalty.&lt;br /&gt;
   if max_penalty &amp;lt; penalty_per_unit&lt;br /&gt;
     error_message = prefix + 'The maximum penalty cannot be less than penalty per unit.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This check validates the penalty per unit for a late policy.&lt;br /&gt;
   if penalty_per_unit &amp;lt; 0&lt;br /&gt;
     error_message = 'Penalty per unit cannot be negative.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This checks maximum penalty does not exceed 100.&lt;br /&gt;
   if max_penalty &amp;gt;= 100&lt;br /&gt;
     error_message = prefix + 'Maximum penalty cannot be greater than or equal to 100'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The validate_input method is quite lengthy and has multiple conditions being checked. It might be worth breaking down this method into smaller functions, each handling a specific validation to make this function more readable.&lt;br /&gt;
&lt;br /&gt;
== Duplicate Name Check Function ==&lt;br /&gt;
 if is_update&lt;br /&gt;
      existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
      if existing_late_policy.policy_name == params[:late_policy][:policy_name]&lt;br /&gt;
        should_check = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if should_check&lt;br /&gt;
      if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
        error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
        valid_penalty = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
The above code is the current implementation of some duplication checks in this function. These if statements can be refactored into smaller sub-functions.&lt;br /&gt;
The pseudo-code for one sub-function is as follows:&lt;br /&gt;
 if should_check_policy_name&lt;br /&gt;
   Call sub-function should_check_policy_name&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def should_check_policy_name(old valid_penalty, old error_message)&lt;br /&gt;
   if check policy with same name(currenty name, instructor_id)&lt;br /&gt;
     error_message = new error message&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
&lt;br /&gt;
In the above sub-function, the should_check name was changed to be more explicit and the should check if-statement was refactored to be in a different method to improve readability.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Proposed Solution'''==&lt;br /&gt;
&lt;br /&gt;
There are multiple routes we can go down to tackle this issue. One way to break down a long method would be to refactor the create method, we can extract and rewrite the save_late_policy method. We also have to refactor the duplicate name check method by rewriting the if statements as smaller sub methods. We would then have to write tests for all the new functionality/refactoring done.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Updated Works'''==&lt;br /&gt;
&lt;br /&gt;
== Create and Update ==&lt;br /&gt;
&lt;br /&gt;
The Create and Update functions were refactored into multiple new helper functions. These functions were created in the hopes to reduce the amount of repeated code as well as increase the readability and maintainability of said functions.&lt;br /&gt;
&lt;br /&gt;
Create: The create function has been simplified to improve its readability and size.&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     create_new_late_policy(late_policy_params)&lt;br /&gt;
     error_thrown = save_late_policy&lt;br /&gt;
     if error_thrown&lt;br /&gt;
       # If there was an error thrown go to new, otherwise go to index&lt;br /&gt;
       redirect_to action: 'new'&lt;br /&gt;
     else&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     end&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: 'new'&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Update: The update function received a similar improvement, being shortened and simplified.&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if !valid_penalty&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
     error_thrown = save_late_policy&lt;br /&gt;
     # If there was an error thrown, go back to edit, otherwise go to index&lt;br /&gt;
     if error_thrown&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     else&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Both create and update have been refactored and split up into various helper functions, many of them to help reduce duplicate code and size in their caller.&lt;br /&gt;
 # Create and save the late policy with the required params&lt;br /&gt;
 def create_new_late_policy(params)&lt;br /&gt;
   @late_policy = LatePolicy.new(params)&lt;br /&gt;
   @late_policy.instructor_id = instructor_id&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Saves the late policy called from create or update&lt;br /&gt;
 def save_late_policy&lt;br /&gt;
   error_thrown = false&lt;br /&gt;
   begin&lt;br /&gt;
     @late_policy.save!&lt;br /&gt;
     if caller_locations(2,1)[0].label == 'update'&lt;br /&gt;
       # If the method that called this is update&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
     end&lt;br /&gt;
     # The code at the end of the string gets the name of the last method (create, update) and adds a d (created, updated)&lt;br /&gt;
     flash[:notice] = &amp;quot;The late policy was successfully #{caller_locations(2,1)[0].label}d.&amp;quot;&lt;br /&gt;
   rescue StandardError&lt;br /&gt;
     error_thrown = true&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     if caller_locations(2,1)[0].label == 'update'&lt;br /&gt;
       message_thrown = 'The following error occurred while updating the late policy: '&lt;br /&gt;
     else&lt;br /&gt;
       message_thrown = 'The following error occurred while saving the late policy: '&lt;br /&gt;
     end&lt;br /&gt;
     handle_error(message_thrown)&lt;br /&gt;
   end&lt;br /&gt;
   error_thrown&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # A method to extrapolate out the flashing of error messages&lt;br /&gt;
 def handle_error(error_message)&lt;br /&gt;
   flash[:error] = error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The create_new_late_policy function is refactored from the create method to move all the code required to create a new blank late policy into one method. This slightly improves readability in the create method. The save_late_policy function has been refactored from duplicate code in both create and update. Both functions had very similar code with only one line of difference as well as a few characters in strings. This function shortens both of the other functions down by separating out this duplicate code into a private function. The same can be said for both the handle_error function.&lt;br /&gt;
&lt;br /&gt;
== Validate_input ==&lt;br /&gt;
&lt;br /&gt;
The validate_input function was originally very long and confusing. It has since been simplified down and separated into helper functions so each function only has one job.&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   error_messages = []&lt;br /&gt;
   # Validates the name is not a duplicate&lt;br /&gt;
   valid_penalty, name_error = duplicate_name_check(is_update)&lt;br /&gt;
   error_messages &amp;lt;&amp;lt; name_error if name_error&lt;br /&gt;
   # This validates the max_penalty to make sure it's within the correct range&lt;br /&gt;
   if max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;#{error_prefix(is_update)}The maximum penalty must be between the penalty per unit and 100.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This validates the penalty_per_unit and makes sure it's not negative&lt;br /&gt;
   if penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;Penalty per unit cannot be negative.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   [valid_penalty, error_messages.join(&amp;quot;\n&amp;quot;)]&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validate the maximum penalty and ensure it's in the correct range&lt;br /&gt;
 def max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
   max_penalty &amp;lt; penalty_per_unit || max_penalty &amp;gt; 100&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validates the penalty per unit&lt;br /&gt;
 def penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
   penalty_per_unit &amp;lt; 0&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validation error prefix&lt;br /&gt;
 def error_prefix(is_update)&lt;br /&gt;
   is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The new validate_input function has combined two of the conditions that validated the same input, max_penalty, into one helper function, max_penalty_validation. This new helper function validates everything with max_penalty. Additionally, the penalty_per_unit validation is moved to another new function. The new error_prefix function is a small helper function that obtains the prefix for specific errors, as per the original validate_input. Lastly, the original validate_input function returned the last error it found, overwriting all previous errors in favor of the last. This new validate_input returns all errors that are found in one big String.&lt;br /&gt;
&lt;br /&gt;
== Test Changes ==&lt;br /&gt;
&lt;br /&gt;
Various duplicate code in the latest_policies_controller_spec file has been factored out into helper functions.&lt;br /&gt;
&lt;br /&gt;
 def create_late_policy(policy_name, max_penalty, penalty_per_unit, instructor_id) &lt;br /&gt;
   late_policy = LatePolicy.new&lt;br /&gt;
   late_policy.policy_name = policy_name&lt;br /&gt;
   late_policy.max_penalty = max_penalty&lt;br /&gt;
   late_policy.penalty_per_unit = penalty_per_unit&lt;br /&gt;
   late_policy.instructor_id = instructor_id&lt;br /&gt;
   late_policy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def request_params(policy_name, max_penalty, penalty_per_unit) {&lt;br /&gt;
   late_policy: {&lt;br /&gt;
     max_penalty: max_penalty,&lt;br /&gt;
     penalty_per_unit: penalty_per_unit,&lt;br /&gt;
     policy_name: policy_name&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def request_params_with_id(policy_name, max_penalty, penalty_per_unit, id) {&lt;br /&gt;
   late_policy: {&lt;br /&gt;
     max_penalty: max_penalty,&lt;br /&gt;
     penalty_per_unit: penalty_per_unit,&lt;br /&gt;
     policy_name: policy_name&lt;br /&gt;
   },&lt;br /&gt;
   id: id&lt;br /&gt;
 }&lt;br /&gt;
 end&lt;/div&gt;</summary>
		<author><name>Acbondi</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152345</id>
		<title>CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152345"/>
		<updated>2023-12-04T20:30:54Z</updated>

		<summary type="html">&lt;p&gt;Acbondi: Fixed a typo in the test changes code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=='''Introduction'''==&lt;br /&gt;
The late_policies_controller.rb class houses the LatePoliciesController that controls the CRUD operations on late policies. However, there are many problems with the current implementation of this controller. In its current state, many functions are too long and repetitive as well as having inadequate variable names, comments, and error messages. This controller would benefit with optimizing its functions and various other aspects of the file.&lt;br /&gt;
&lt;br /&gt;
== About the LatePoliciesController ==&lt;br /&gt;
The LatePoliciesController provides CRUD functions to create, read, update, and destroy late policies. These include the index, show, new, edit, create, update, and destroy functions. Other functions are provided to allow it to work seamlessly within the framework of the overall project, including the action_allowed?, duplicate_name_check, validate_input, and various parameter and input functions. These additional functions are helper functions that ensure that the late policy can be created or updated based on if the user has the required permissions, doesn't enter a duplicate name, and inputs valid information to the late policy.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
*Refactor Long Methods: Longer functions should be refactored into smaller sub-functions to improve readability and make it easier for future alterations of the code.&lt;br /&gt;
*Improve Comments: More comments should be added to allow for users to easily follow through a given function and understand the specifics of its code statements.&lt;br /&gt;
*Follow the DRY Principle: Repeated code should be removed or moved into helper functions to allow for reusability of common code.&lt;br /&gt;
*Improve Testing: More tests should be created to ensure that everything works as intended and no unexpected errors occur, either exceptions or errors in logic.&lt;br /&gt;
*All changes must be done without the addition of new gems and must be clearly documented.&lt;br /&gt;
&lt;br /&gt;
== Functions to Optimize ==&lt;br /&gt;
*create: This function will be broken down into smaller functions to allow a more readable creation of new late policies. The error handling will also be altered to improve readability.&lt;br /&gt;
*update: Various comments will be added to the function as well as breaking down the code used for saving the late policy into a helper method to shorten the update method and make it more intuitive.&lt;br /&gt;
*duplicate_name_check: This function has various separate if statements that check for various things. These if statements will be broken down into separate helper methods to check for each individually. The duplicate_name_check function will be the main function that calls the various sub-functions so that it is clear what is being checked at a given step.&lt;br /&gt;
*validate_input: Similar to the duplicate_name_check function, this function has various if statements that can be refactored into smaller functions to check each input individually.&lt;br /&gt;
*Tests: Tests for creating and updating new late policies will be created. These tests will check for invalid inputs, correct error messages, etc. as well as ensure that edge cases are also captured correctly by the controller. New tests will also be created to ensure that previous functions, like the read and destroy functions, work correctly.&lt;br /&gt;
&lt;br /&gt;
== Create and Update Functions ==&lt;br /&gt;
&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     @late_policy = LatePolicy.new(late_policy_params)&lt;br /&gt;
     @late_policy.instructor_id = instructor_id&lt;br /&gt;
     begin&lt;br /&gt;
       @late_policy.save!&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully created.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while saving the late policy: '&lt;br /&gt;
       redirect_to action: 'new'&lt;br /&gt;
     end&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: 'new'&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       penalty_policy.save!&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully updated.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while updating the late policy: '&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
In the create and update methods, there are multiple if-else conditions and error handling which can be refactored for better readability and maintainability. The above code snippets represent the create and update functions. Both are very long and could benefit from splitting up the duplicated code and simplification.&lt;br /&gt;
&lt;br /&gt;
== Validate_input Function ==&lt;br /&gt;
&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty, error_message = duplicate_name_check(is_update)&lt;br /&gt;
   prefix = is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
   # This check validates the maximum penalty.&lt;br /&gt;
   if max_penalty &amp;lt; penalty_per_unit&lt;br /&gt;
     error_message = prefix + 'The maximum penalty cannot be less than penalty per unit.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This check validates the penalty per unit for a late policy.&lt;br /&gt;
   if penalty_per_unit &amp;lt; 0&lt;br /&gt;
     error_message = 'Penalty per unit cannot be negative.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This checks maximum penalty does not exceed 100.&lt;br /&gt;
   if max_penalty &amp;gt;= 100&lt;br /&gt;
     error_message = prefix + 'Maximum penalty cannot be greater than or equal to 100'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The validate_input method is quite lengthy and has multiple conditions being checked. It might be worth breaking down this method into smaller functions, each handling a specific validation to make this function more readable.&lt;br /&gt;
&lt;br /&gt;
== Duplicate Name Check Function ==&lt;br /&gt;
 if is_update&lt;br /&gt;
      existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
      if existing_late_policy.policy_name == params[:late_policy][:policy_name]&lt;br /&gt;
        should_check = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if should_check&lt;br /&gt;
      if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
        error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
        valid_penalty = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
The above code is the current implementation of some duplication checks in this function. These if statements can be refactored into smaller sub-functions.&lt;br /&gt;
The pseudo-code for one sub-function is as follows:&lt;br /&gt;
 if should_check_policy_name&lt;br /&gt;
   Call sub-function should_check_policy_name&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def should_check_policy_name(old valid_penalty, old error_message)&lt;br /&gt;
   if check policy with same name(currenty name, instructor_id)&lt;br /&gt;
     error_message = new error message&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
&lt;br /&gt;
In the above sub-function, the should_check name was changed to be more explicit and the should check if-statement was refactored to be in a different method to improve readability.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Proposed Solution'''==&lt;br /&gt;
&lt;br /&gt;
There are multiple routes we can go down to tackle this issue. One way to break down a long method would be to refactor the create method, we can extract and rewrite the save_late_policy method. We also have to refactor the duplicate name check method by rewriting the if statements as smaller sub methods. We would then have to write tests for all the new functionality/refactoring done.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Updated Works'''==&lt;br /&gt;
&lt;br /&gt;
== Create and Update ==&lt;br /&gt;
&lt;br /&gt;
The Create and Update functions were refactored into multiple new helper functions. These functions were created in the hopes to reduce the amount of repeated code as well as increase the readability and maintainability of said functions.&lt;br /&gt;
&lt;br /&gt;
Create: The create function has been simplified to improve its readability and size.&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     create_new_late_policy(late_policy_params)&lt;br /&gt;
     save_late_policy&lt;br /&gt;
     redirect_to_policy('index')&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Update: The update function received a similar improvement, being shortened and simplified.&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
     redirect_to_policy('edit')&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       save_late_policy&lt;br /&gt;
       redirect_to_policy('index')&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       handle_error('The following error occurred while updating the late policy: ')&lt;br /&gt;
       redirect_to_policy('edit')&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Both create and update have been refactored and split up into various helper functions, many of them to help reduce duplicate code and size in their caller.&lt;br /&gt;
 # Create and save the late policy with the required params&lt;br /&gt;
 def create_new_late_policy(params)&lt;br /&gt;
   @late_policy = LatePolicy.new(params)&lt;br /&gt;
   @late_policy.instructor_id = instructor_id&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Saves the late policy called from create or update&lt;br /&gt;
 def save_late_policy&lt;br /&gt;
   begin&lt;br /&gt;
     @late_policy.save!&lt;br /&gt;
     if caller_locations(2,1)[0].label == 'update'&lt;br /&gt;
       # If the method that called this is update&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
     end&lt;br /&gt;
     # The code at the end of the string gets the name of the last method (create, update) and adds a d (created, updated)&lt;br /&gt;
     flash[:notice] = &amp;quot;The late policy was successfully #{caller_locations(2,1)[0].label}d.&amp;quot;&lt;br /&gt;
   rescue StandardError&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     handle_error('The following error occurred while saving the late policy: ')&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # A method to extrapolate out the flashing of error messages&lt;br /&gt;
 def handle_error(error_message)&lt;br /&gt;
   flash[:error] = error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # A method to extrapolate out the redirecting to policy controller states&lt;br /&gt;
 def redirect_to_policy(location)&lt;br /&gt;
   if location == &amp;quot;edit&amp;quot;&lt;br /&gt;
     # If the location is the edit screen, use the old id that was inputted&lt;br /&gt;
     redirect_to action: location, id: params[:id]&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: location&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The create_new_late_policy function is refactored from the create method to move all the code required to create a new blank late policy into one method. This slightly improves readability in the create method. The save_late_policy function has been refactored from duplicate code in both create and update. Both functions had very similar code with only one line of difference as well as a few characters in strings. This function shortens both of the other functions down by separating out this duplicate code into a private function. The same can be said for both the handle_error function and redirect_to_policy function.&lt;br /&gt;
&lt;br /&gt;
== Validate_input ==&lt;br /&gt;
&lt;br /&gt;
The validate_input function was originally very long and confusing. It has since been simplified down and separated into helper functions so each function only has one job.&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty = true&lt;br /&gt;
   error_messages = []&lt;br /&gt;
   # Validates the name is not a duplicate&lt;br /&gt;
   valid_penalty, name_error = duplicate_name_check(is_update)&lt;br /&gt;
   error_messages &amp;lt;&amp;lt; name_error if name_error&lt;br /&gt;
   # This validates the max_penalty to make sure it's within the correct range&lt;br /&gt;
   if max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;#{error_prefix(is_update)}The maximum penalty must be between the penalty per unit and 100.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This validates the penalty_per_unit and makes sure it's not negative&lt;br /&gt;
   if penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;Penalty per unit cannot be negative.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   [valid_penalty, error_messages.join(&amp;quot;\n&amp;quot;)]&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validate the maximum penalty and ensure it's in the correct range&lt;br /&gt;
 def max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
   max_penalty &amp;lt; penalty_per_unit || max_penalty &amp;gt; 100&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validates the penalty per unit&lt;br /&gt;
 def penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
   penalty_per_unit &amp;lt; 0&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validation error prefix&lt;br /&gt;
 def error_prefix(is_update)&lt;br /&gt;
   is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The new validate_input function has combined two of the conditions that validated the same input, max_penalty, into one helper function, max_penalty_validation. This new helper function validates everything with max_penalty. Additionally, the penalty_per_unit validation is moved to another new function. The new error_prefix function is a small helper function that obtains the prefix for specific errors, as per the original validate_input. Lastly, the original validate_input function returned the last error it found, overwriting all previous errors in favor of the last. This new validate_input returns all errors that are found in one big String.&lt;br /&gt;
&lt;br /&gt;
== Test Changes ==&lt;br /&gt;
&lt;br /&gt;
Various duplicate code in the latest_policies_controller_spec file has been factored out into helper functions.&lt;br /&gt;
&lt;br /&gt;
 def create_late_policy(policy_name, max_penalty, penalty_per_unit, instructor_id) &lt;br /&gt;
   late_policy = LatePolicy.new&lt;br /&gt;
   late_policy.policy_name = policy_name&lt;br /&gt;
   late_policy.max_penalty = max_penalty&lt;br /&gt;
   late_policy.penalty_per_unit = penalty_per_unit&lt;br /&gt;
   late_policy.instructor_id = instructor_id&lt;br /&gt;
   late_policy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def request_params(policy_name, max_penalty, penalty_per_unit) {&lt;br /&gt;
   late_policy: {&lt;br /&gt;
     max_penalty: max_penalty,&lt;br /&gt;
     penalty_per_unit: penalty_per_unit,&lt;br /&gt;
     policy_name: policy_name&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 end&lt;/div&gt;</summary>
		<author><name>Acbondi</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152327</id>
		<title>CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152327"/>
		<updated>2023-12-04T19:59:28Z</updated>

		<summary type="html">&lt;p&gt;Acbondi: Added the changes to tests section and added what I changed&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=='''Introduction'''==&lt;br /&gt;
The late_policies_controller.rb class houses the LatePoliciesController that controls the CRUD operations on late policies. However, there are many problems with the current implementation of this controller. In its current state, many functions are too long and repetitive as well as having inadequate variable names, comments, and error messages. This controller would benefit with optimizing its functions and various other aspects of the file.&lt;br /&gt;
&lt;br /&gt;
== About the LatePoliciesController ==&lt;br /&gt;
The LatePoliciesController provides CRUD functions to create, read, update, and destroy late policies. These include the index, show, new, edit, create, update, and destroy functions. Other functions are provided to allow it to work seamlessly within the framework of the overall project, including the action_allowed?, duplicate_name_check, validate_input, and various parameter and input functions. These additional functions are helper functions that ensure that the late policy can be created or updated based on if the user has the required permissions, doesn't enter a duplicate name, and inputs valid information to the late policy.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
*Refactor Long Methods: Longer functions should be refactored into smaller sub-functions to improve readability and make it easier for future alterations of the code.&lt;br /&gt;
*Improve Comments: More comments should be added to allow for users to easily follow through a given function and understand the specifics of its code statements.&lt;br /&gt;
*Follow the DRY Principle: Repeated code should be removed or moved into helper functions to allow for reusability of common code.&lt;br /&gt;
*Improve Testing: More tests should be created to ensure that everything works as intended and no unexpected errors occur, either exceptions or errors in logic.&lt;br /&gt;
*All changes must be done without the addition of new gems and must be clearly documented.&lt;br /&gt;
&lt;br /&gt;
== Functions to Optimize ==&lt;br /&gt;
*create: This function will be broken down into smaller functions to allow a more readable creation of new late policies. The error handling will also be altered to improve readability.&lt;br /&gt;
*update: Various comments will be added to the function as well as breaking down the code used for saving the late policy into a helper method to shorten the update method and make it more intuitive.&lt;br /&gt;
*duplicate_name_check: This function has various separate if statements that check for various things. These if statements will be broken down into separate helper methods to check for each individually. The duplicate_name_check function will be the main function that calls the various sub-functions so that it is clear what is being checked at a given step.&lt;br /&gt;
*validate_input: Similar to the duplicate_name_check function, this function has various if statements that can be refactored into smaller functions to check each input individually.&lt;br /&gt;
*Tests: Tests for creating and updating new late policies will be created. These tests will check for invalid inputs, correct error messages, etc. as well as ensure that edge cases are also captured correctly by the controller. New tests will also be created to ensure that previous functions, like the read and destroy functions, work correctly.&lt;br /&gt;
&lt;br /&gt;
== Create and Update Functions ==&lt;br /&gt;
&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     @late_policy = LatePolicy.new(late_policy_params)&lt;br /&gt;
     @late_policy.instructor_id = instructor_id&lt;br /&gt;
     begin&lt;br /&gt;
       @late_policy.save!&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully created.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while saving the late policy: '&lt;br /&gt;
       redirect_to action: 'new'&lt;br /&gt;
     end&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: 'new'&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       penalty_policy.save!&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully updated.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while updating the late policy: '&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
In the create and update methods, there are multiple if-else conditions and error handling which can be refactored for better readability and maintainability. The above code snippets represent the create and update functions. Both are very long and could benefit from splitting up the duplicated code and simplification.&lt;br /&gt;
&lt;br /&gt;
== Validate_input Function ==&lt;br /&gt;
&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty, error_message = duplicate_name_check(is_update)&lt;br /&gt;
   prefix = is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
   # This check validates the maximum penalty.&lt;br /&gt;
   if max_penalty &amp;lt; penalty_per_unit&lt;br /&gt;
     error_message = prefix + 'The maximum penalty cannot be less than penalty per unit.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This check validates the penalty per unit for a late policy.&lt;br /&gt;
   if penalty_per_unit &amp;lt; 0&lt;br /&gt;
     error_message = 'Penalty per unit cannot be negative.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This checks maximum penalty does not exceed 100.&lt;br /&gt;
   if max_penalty &amp;gt;= 100&lt;br /&gt;
     error_message = prefix + 'Maximum penalty cannot be greater than or equal to 100'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The validate_input method is quite lengthy and has multiple conditions being checked. It might be worth breaking down this method into smaller functions, each handling a specific validation to make this function more readable.&lt;br /&gt;
&lt;br /&gt;
== Duplicate Name Check Function ==&lt;br /&gt;
 if is_update&lt;br /&gt;
      existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
      if existing_late_policy.policy_name == params[:late_policy][:policy_name]&lt;br /&gt;
        should_check = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if should_check&lt;br /&gt;
      if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
        error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
        valid_penalty = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
The above code is the current implementation of some duplication checks in this function. These if statements can be refactored into smaller sub-functions.&lt;br /&gt;
The pseudo-code for one sub-function is as follows:&lt;br /&gt;
 if should_check_policy_name&lt;br /&gt;
   Call sub-function should_check_policy_name&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def should_check_policy_name(old valid_penalty, old error_message)&lt;br /&gt;
   if check policy with same name(currenty name, instructor_id)&lt;br /&gt;
     error_message = new error message&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
&lt;br /&gt;
In the above sub-function, the should_check name was changed to be more explicit and the should check if-statement was refactored to be in a different method to improve readability.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Proposed Solution'''==&lt;br /&gt;
&lt;br /&gt;
There are multiple routes we can go down to tackle this issue. One way to break down a long method would be to refactor the create method, we can extract and rewrite the save_late_policy method. We also have to refactor the duplicate name check method by rewriting the if statements as smaller sub methods. We would then have to write tests for all the new functionality/refactoring done.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Updated Works'''==&lt;br /&gt;
&lt;br /&gt;
== Create and Update ==&lt;br /&gt;
&lt;br /&gt;
The Create and Update functions were refactored into multiple new helper functions. These functions were created in the hopes to reduce the amount of repeated code as well as increase the readability and maintainability of said functions.&lt;br /&gt;
&lt;br /&gt;
Create: The create function has been simplified to improve its readability and size.&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     create_new_late_policy(late_policy_params)&lt;br /&gt;
     save_late_policy&lt;br /&gt;
     redirect_to_policy('index')&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Update: The update function received a similar improvement, being shortened and simplified.&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
     redirect_to_policy('edit')&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       save_late_policy&lt;br /&gt;
       redirect_to_policy('index')&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       handle_error('The following error occurred while updating the late policy: ')&lt;br /&gt;
       redirect_to_policy('edit')&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Both create and update have been refactored and split up into various helper functions, many of them to help reduce duplicate code and size in their caller.&lt;br /&gt;
 # Create and save the late policy with the required params&lt;br /&gt;
 def create_new_late_policy(params)&lt;br /&gt;
   @late_policy = LatePolicy.new(params)&lt;br /&gt;
   @late_policy.instructor_id = instructor_id&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Saves the late policy called from create or update&lt;br /&gt;
 def save_late_policy&lt;br /&gt;
   begin&lt;br /&gt;
     @late_policy.save!&lt;br /&gt;
     if caller_locations(2,1)[0].label == 'update'&lt;br /&gt;
       # If the method that called this is update&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
     end&lt;br /&gt;
     # The code at the end of the string gets the name of the last method (create, update) and adds a d (created, updated)&lt;br /&gt;
     flash[:notice] = &amp;quot;The late policy was successfully #{caller_locations(2,1)[0].label}d.&amp;quot;&lt;br /&gt;
   rescue StandardError&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     handle_error('The following error occurred while saving the late policy: ')&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # A method to extrapolate out the flashing of error messages&lt;br /&gt;
 def handle_error(error_message)&lt;br /&gt;
   flash[:error] = error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # A method to extrapolate out the redirecting to policy controller states&lt;br /&gt;
 def redirect_to_policy(location)&lt;br /&gt;
   if location == &amp;quot;edit&amp;quot;&lt;br /&gt;
     # If the location is the edit screen, use the old id that was inputted&lt;br /&gt;
     redirect_to action: location, id: params[:id]&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: location&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The create_new_late_policy function is refactored from the create method to move all the code required to create a new blank late policy into one method. This slightly improves readability in the create method. The save_late_policy function has been refactored from duplicate code in both create and update. Both functions had very similar code with only one line of difference as well as a few characters in strings. This function shortens both of the other functions down by separating out this duplicate code into a private function. The same can be said for both the handle_error function and redirect_to_policy function.&lt;br /&gt;
&lt;br /&gt;
== Validate_input ==&lt;br /&gt;
&lt;br /&gt;
The validate_input function was originally very long and confusing. It has since been simplified down and separated into helper functions so each function only has one job.&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty = true&lt;br /&gt;
   error_messages = []&lt;br /&gt;
   # Validates the name is not a duplicate&lt;br /&gt;
   valid_penalty, name_error = duplicate_name_check(is_update)&lt;br /&gt;
   error_messages &amp;lt;&amp;lt; name_error if name_error&lt;br /&gt;
   # This validates the max_penalty to make sure it's within the correct range&lt;br /&gt;
   if max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;#{error_prefix(is_update)}The maximum penalty must be between the penalty per unit and 100.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This validates the penalty_per_unit and makes sure it's not negative&lt;br /&gt;
   if penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;Penalty per unit cannot be negative.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   [valid_penalty, error_messages.join(&amp;quot;\n&amp;quot;)]&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validate the maximum penalty and ensure it's in the correct range&lt;br /&gt;
 def max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
   max_penalty &amp;lt; penalty_per_unit || max_penalty &amp;gt; 100&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validates the penalty per unit&lt;br /&gt;
 def penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
   penalty_per_unit &amp;lt; 0&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validation error prefix&lt;br /&gt;
 def error_prefix(is_update)&lt;br /&gt;
   is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The new validate_input function has combined two of the conditions that validated the same input, max_penalty, into one helper function, max_penalty_validation. This new helper function validates everything with max_penalty. Additionally, the penalty_per_unit validation is moved to another new function. The new error_prefix function is a small helper function that obtains the prefix for specific errors, as per the original validate_input. Lastly, the original validate_input function returned the last error it found, overwriting all previous errors in favor of the last. This new validate_input returns all errors that are found in one big String.&lt;br /&gt;
&lt;br /&gt;
== Test Changes ==&lt;br /&gt;
&lt;br /&gt;
Various duplicate code in the latest_policies_controller_spec file has been factored out into helper functions.&lt;br /&gt;
&lt;br /&gt;
 def create_late_policy(policy_name, max_penalty, penalty_per_unit, instructor_id) &lt;br /&gt;
   late_policy = LatePolicy.new&lt;br /&gt;
   late_policy.policy_name = policy_name&lt;br /&gt;
   late_policy.max_penalty = max_penalty&lt;br /&gt;
   late_policy.penalty_per_unit = penalty_per_unit&lt;br /&gt;
   late_policy.instructor_id = instructor_id&lt;br /&gt;
   late_policy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def request_params(policy_name, max_penalty, penalty_per_unit) {&lt;br /&gt;
   late_policy: {&lt;br /&gt;
     max_penalty: max_penalty&lt;br /&gt;
     penalty_per_unit: penalty_per_unit&lt;br /&gt;
     policy_name: policy_name&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 end&lt;/div&gt;</summary>
		<author><name>Acbondi</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152326</id>
		<title>CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152326"/>
		<updated>2023-12-04T19:56:09Z</updated>

		<summary type="html">&lt;p&gt;Acbondi: Added the changes to validate_input&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=='''Introduction'''==&lt;br /&gt;
The late_policies_controller.rb class houses the LatePoliciesController that controls the CRUD operations on late policies. However, there are many problems with the current implementation of this controller. In its current state, many functions are too long and repetitive as well as having inadequate variable names, comments, and error messages. This controller would benefit with optimizing its functions and various other aspects of the file.&lt;br /&gt;
&lt;br /&gt;
== About the LatePoliciesController ==&lt;br /&gt;
The LatePoliciesController provides CRUD functions to create, read, update, and destroy late policies. These include the index, show, new, edit, create, update, and destroy functions. Other functions are provided to allow it to work seamlessly within the framework of the overall project, including the action_allowed?, duplicate_name_check, validate_input, and various parameter and input functions. These additional functions are helper functions that ensure that the late policy can be created or updated based on if the user has the required permissions, doesn't enter a duplicate name, and inputs valid information to the late policy.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
*Refactor Long Methods: Longer functions should be refactored into smaller sub-functions to improve readability and make it easier for future alterations of the code.&lt;br /&gt;
*Improve Comments: More comments should be added to allow for users to easily follow through a given function and understand the specifics of its code statements.&lt;br /&gt;
*Follow the DRY Principle: Repeated code should be removed or moved into helper functions to allow for reusability of common code.&lt;br /&gt;
*Improve Testing: More tests should be created to ensure that everything works as intended and no unexpected errors occur, either exceptions or errors in logic.&lt;br /&gt;
*All changes must be done without the addition of new gems and must be clearly documented.&lt;br /&gt;
&lt;br /&gt;
== Functions to Optimize ==&lt;br /&gt;
*create: This function will be broken down into smaller functions to allow a more readable creation of new late policies. The error handling will also be altered to improve readability.&lt;br /&gt;
*update: Various comments will be added to the function as well as breaking down the code used for saving the late policy into a helper method to shorten the update method and make it more intuitive.&lt;br /&gt;
*duplicate_name_check: This function has various separate if statements that check for various things. These if statements will be broken down into separate helper methods to check for each individually. The duplicate_name_check function will be the main function that calls the various sub-functions so that it is clear what is being checked at a given step.&lt;br /&gt;
*validate_input: Similar to the duplicate_name_check function, this function has various if statements that can be refactored into smaller functions to check each input individually.&lt;br /&gt;
*Tests: Tests for creating and updating new late policies will be created. These tests will check for invalid inputs, correct error messages, etc. as well as ensure that edge cases are also captured correctly by the controller. New tests will also be created to ensure that previous functions, like the read and destroy functions, work correctly.&lt;br /&gt;
&lt;br /&gt;
== Create and Update Functions ==&lt;br /&gt;
&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     @late_policy = LatePolicy.new(late_policy_params)&lt;br /&gt;
     @late_policy.instructor_id = instructor_id&lt;br /&gt;
     begin&lt;br /&gt;
       @late_policy.save!&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully created.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while saving the late policy: '&lt;br /&gt;
       redirect_to action: 'new'&lt;br /&gt;
     end&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: 'new'&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       penalty_policy.save!&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully updated.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while updating the late policy: '&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
In the create and update methods, there are multiple if-else conditions and error handling which can be refactored for better readability and maintainability. The above code snippets represent the create and update functions. Both are very long and could benefit from splitting up the duplicated code and simplification.&lt;br /&gt;
&lt;br /&gt;
== Validate_input Function ==&lt;br /&gt;
&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty, error_message = duplicate_name_check(is_update)&lt;br /&gt;
   prefix = is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
   # This check validates the maximum penalty.&lt;br /&gt;
   if max_penalty &amp;lt; penalty_per_unit&lt;br /&gt;
     error_message = prefix + 'The maximum penalty cannot be less than penalty per unit.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This check validates the penalty per unit for a late policy.&lt;br /&gt;
   if penalty_per_unit &amp;lt; 0&lt;br /&gt;
     error_message = 'Penalty per unit cannot be negative.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This checks maximum penalty does not exceed 100.&lt;br /&gt;
   if max_penalty &amp;gt;= 100&lt;br /&gt;
     error_message = prefix + 'Maximum penalty cannot be greater than or equal to 100'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The validate_input method is quite lengthy and has multiple conditions being checked. It might be worth breaking down this method into smaller functions, each handling a specific validation to make this function more readable.&lt;br /&gt;
&lt;br /&gt;
== Duplicate Name Check Function ==&lt;br /&gt;
 if is_update&lt;br /&gt;
      existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
      if existing_late_policy.policy_name == params[:late_policy][:policy_name]&lt;br /&gt;
        should_check = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if should_check&lt;br /&gt;
      if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
        error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
        valid_penalty = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
The above code is the current implementation of some duplication checks in this function. These if statements can be refactored into smaller sub-functions.&lt;br /&gt;
The pseudo-code for one sub-function is as follows:&lt;br /&gt;
 if should_check_policy_name&lt;br /&gt;
   Call sub-function should_check_policy_name&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def should_check_policy_name(old valid_penalty, old error_message)&lt;br /&gt;
   if check policy with same name(currenty name, instructor_id)&lt;br /&gt;
     error_message = new error message&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
&lt;br /&gt;
In the above sub-function, the should_check name was changed to be more explicit and the should check if-statement was refactored to be in a different method to improve readability.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Proposed Solution'''==&lt;br /&gt;
&lt;br /&gt;
There are multiple routes we can go down to tackle this issue. One way to break down a long method would be to refactor the create method, we can extract and rewrite the save_late_policy method. We also have to refactor the duplicate name check method by rewriting the if statements as smaller sub methods. We would then have to write tests for all the new functionality/refactoring done.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Updated Works'''==&lt;br /&gt;
&lt;br /&gt;
== Create and Update Functions ==&lt;br /&gt;
&lt;br /&gt;
The Create and Update functions were refactored into multiple new helper functions. These functions were created in the hopes to reduce the amount of repeated code as well as increase the readability and maintainability of said functions.&lt;br /&gt;
&lt;br /&gt;
Create: The create function has been simplified to improve its readability and size.&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     create_new_late_policy(late_policy_params)&lt;br /&gt;
     save_late_policy&lt;br /&gt;
     redirect_to_policy('index')&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Update: The update function received a similar improvement, being shortened and simplified.&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
     redirect_to_policy('edit')&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       save_late_policy&lt;br /&gt;
       redirect_to_policy('index')&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       handle_error('The following error occurred while updating the late policy: ')&lt;br /&gt;
       redirect_to_policy('edit')&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Both create and update have been refactored and split up into various helper functions, many of them to help reduce duplicate code and size in their caller.&lt;br /&gt;
 # Create and save the late policy with the required params&lt;br /&gt;
 def create_new_late_policy(params)&lt;br /&gt;
   @late_policy = LatePolicy.new(params)&lt;br /&gt;
   @late_policy.instructor_id = instructor_id&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Saves the late policy called from create or update&lt;br /&gt;
 def save_late_policy&lt;br /&gt;
   begin&lt;br /&gt;
     @late_policy.save!&lt;br /&gt;
     if caller_locations(2,1)[0].label == 'update'&lt;br /&gt;
       # If the method that called this is update&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
     end&lt;br /&gt;
     # The code at the end of the string gets the name of the last method (create, update) and adds a d (created, updated)&lt;br /&gt;
     flash[:notice] = &amp;quot;The late policy was successfully #{caller_locations(2,1)[0].label}d.&amp;quot;&lt;br /&gt;
   rescue StandardError&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     handle_error('The following error occurred while saving the late policy: ')&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # A method to extrapolate out the flashing of error messages&lt;br /&gt;
 def handle_error(error_message)&lt;br /&gt;
   flash[:error] = error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # A method to extrapolate out the redirecting to policy controller states&lt;br /&gt;
 def redirect_to_policy(location)&lt;br /&gt;
   if location == &amp;quot;edit&amp;quot;&lt;br /&gt;
     # If the location is the edit screen, use the old id that was inputted&lt;br /&gt;
     redirect_to action: location, id: params[:id]&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: location&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The create_new_late_policy function is refactored from the create method to move all the code required to create a new blank late policy into one method. This slightly improves readability in the create method. The save_late_policy function has been refactored from duplicate code in both create and update. Both functions had very similar code with only one line of difference as well as a few characters in strings. This function shortens both of the other functions down by separating out this duplicate code into a private function. The same can be said for both the handle_error function and redirect_to_policy function.&lt;br /&gt;
&lt;br /&gt;
== Validate_input Function ==&lt;br /&gt;
&lt;br /&gt;
The validate_input function was originally very long and confusing. It has since been simplified down and separated into helper functions so each function only has one job.&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty = true&lt;br /&gt;
   error_messages = []&lt;br /&gt;
   # Validates the name is not a duplicate&lt;br /&gt;
   valid_penalty, name_error = duplicate_name_check(is_update)&lt;br /&gt;
   error_messages &amp;lt;&amp;lt; name_error if name_error&lt;br /&gt;
   # This validates the max_penalty to make sure it's within the correct range&lt;br /&gt;
   if max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;#{error_prefix(is_update)}The maximum penalty must be between the penalty per unit and 100.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This validates the penalty_per_unit and makes sure it's not negative&lt;br /&gt;
   if penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
     error_messages &amp;lt;&amp;lt; &amp;quot;Penalty per unit cannot be negative.&amp;quot;&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   [valid_penalty, error_messages.join(&amp;quot;\n&amp;quot;)]&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validate the maximum penalty and ensure it's in the correct range&lt;br /&gt;
 def max_penalty_validation(max_penalty, penalty_per_unit)&lt;br /&gt;
   max_penalty &amp;lt; penalty_per_unit || max_penalty &amp;gt; 100&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validates the penalty per unit&lt;br /&gt;
 def penalty_per_unit_validation(penalty_per_unit)&lt;br /&gt;
   penalty_per_unit &amp;lt; 0&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Validation error prefix&lt;br /&gt;
 def error_prefix(is_update)&lt;br /&gt;
   is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The new validate_input function has combined two of the conditions that validated the same input, max_penalty, into one helper function, max_penalty_validation. This new helper function validates everything with max_penalty. Additionally, the penalty_per_unit validation is moved to another new function. The new error_prefix function is a small helper function that obtains the prefix for specific errors, as per the original validate_input. Lastly, the original validate_input function returned the last error it found, overwriting all previous errors in favor of the last. This new validate_input returns all errors that are found in one big String.&lt;/div&gt;</summary>
		<author><name>Acbondi</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152323</id>
		<title>CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=152323"/>
		<updated>2023-12-04T19:43:36Z</updated>

		<summary type="html">&lt;p&gt;Acbondi: Reworded some previous create and update solutions as well as added the changes to those functions in a new Updated Works section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=='''Introduction'''==&lt;br /&gt;
The late_policies_controller.rb class houses the LatePoliciesController that controls the CRUD operations on late policies. However, there are many problems with the current implementation of this controller. In its current state, many functions are too long and repetitive as well as having inadequate variable names, comments, and error messages. This controller would benefit with optimizing its functions and various other aspects of the file.&lt;br /&gt;
&lt;br /&gt;
== About the LatePoliciesController ==&lt;br /&gt;
The LatePoliciesController provides CRUD functions to create, read, update, and destroy late policies. These include the index, show, new, edit, create, update, and destroy functions. Other functions are provided to allow it to work seamlessly within the framework of the overall project, including the action_allowed?, duplicate_name_check, validate_input, and various parameter and input functions. These additional functions are helper functions that ensure that the late policy can be created or updated based on if the user has the required permissions, doesn't enter a duplicate name, and inputs valid information to the late policy.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
*Refactor Long Methods: Longer functions should be refactored into smaller sub-functions to improve readability and make it easier for future alterations of the code.&lt;br /&gt;
*Improve Comments: More comments should be added to allow for users to easily follow through a given function and understand the specifics of its code statements.&lt;br /&gt;
*Follow the DRY Principle: Repeated code should be removed or moved into helper functions to allow for reusability of common code.&lt;br /&gt;
*Improve Testing: More tests should be created to ensure that everything works as intended and no unexpected errors occur, either exceptions or errors in logic.&lt;br /&gt;
*All changes must be done without the addition of new gems and must be clearly documented.&lt;br /&gt;
&lt;br /&gt;
== Functions to Optimize ==&lt;br /&gt;
*create: This function will be broken down into smaller functions to allow a more readable creation of new late policies. The error handling will also be altered to improve readability.&lt;br /&gt;
*update: Various comments will be added to the function as well as breaking down the code used for saving the late policy into a helper method to shorten the update method and make it more intuitive.&lt;br /&gt;
*duplicate_name_check: This function has various separate if statements that check for various things. These if statements will be broken down into separate helper methods to check for each individually. The duplicate_name_check function will be the main function that calls the various sub-functions so that it is clear what is being checked at a given step.&lt;br /&gt;
*validate_input: Similar to the duplicate_name_check function, this function has various if statements that can be refactored into smaller functions to check each input individually.&lt;br /&gt;
*Tests: Tests for creating and updating new late policies will be created. These tests will check for invalid inputs, correct error messages, etc. as well as ensure that edge cases are also captured correctly by the controller. New tests will also be created to ensure that previous functions, like the read and destroy functions, work correctly.&lt;br /&gt;
&lt;br /&gt;
== Create and Update Functions ==&lt;br /&gt;
&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     @late_policy = LatePolicy.new(late_policy_params)&lt;br /&gt;
     @late_policy.instructor_id = instructor_id&lt;br /&gt;
     begin&lt;br /&gt;
       @late_policy.save!&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully created.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while saving the late policy: '&lt;br /&gt;
       redirect_to action: 'new'&lt;br /&gt;
     end&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: 'new'&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     flash[:error] = error_message&lt;br /&gt;
     redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       penalty_policy.save!&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
       flash[:notice] = 'The late policy was successfully updated.'&lt;br /&gt;
       redirect_to action: 'index'&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       flash[:error] = 'The following error occurred while updating the late policy: '&lt;br /&gt;
       redirect_to action: 'edit', id: params[:id]&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
In the create and update methods, there are multiple if-else conditions and error handling which can be refactored for better readability and maintainability. The above code snippets represent the create and update functions. Both are very long and could benefit from splitting up the duplicated code and simplification.&lt;br /&gt;
&lt;br /&gt;
== Validate_input Function ==&lt;br /&gt;
&lt;br /&gt;
 # This function validates the input.&lt;br /&gt;
 def validate_input(is_update = false)&lt;br /&gt;
   # Validates input for create and update forms&lt;br /&gt;
   max_penalty = params[:late_policy][:max_penalty].to_i&lt;br /&gt;
   penalty_per_unit = params[:late_policy][:penalty_per_unit].to_i&lt;br /&gt;
   valid_penalty, error_message = duplicate_name_check(is_update)&lt;br /&gt;
   prefix = is_update ? &amp;quot;Cannot edit the policy. &amp;quot; : &amp;quot;&amp;quot;&lt;br /&gt;
   # This check validates the maximum penalty.&lt;br /&gt;
   if max_penalty &amp;lt; penalty_per_unit&lt;br /&gt;
     error_message = prefix + 'The maximum penalty cannot be less than penalty per unit.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This check validates the penalty per unit for a late policy.&lt;br /&gt;
   if penalty_per_unit &amp;lt; 0&lt;br /&gt;
     error_message = 'Penalty per unit cannot be negative.'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   # This checks maximum penalty does not exceed 100.&lt;br /&gt;
   if max_penalty &amp;gt;= 100&lt;br /&gt;
     error_message = prefix + 'Maximum penalty cannot be greater than or equal to 100'&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The validate_input method is quite lengthy and has multiple conditions being checked. It might be worth breaking down this method into smaller functions, each handling a specific validation to make this function more readable.&lt;br /&gt;
&lt;br /&gt;
== Duplicate Name Check Function ==&lt;br /&gt;
 if is_update&lt;br /&gt;
      existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
      if existing_late_policy.policy_name == params[:late_policy][:policy_name]&lt;br /&gt;
        should_check = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if should_check&lt;br /&gt;
      if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
        error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
        valid_penalty = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
The above code is the current implementation of some duplication checks in this function. These if statements can be refactored into smaller sub-functions.&lt;br /&gt;
The pseudo-code for one sub-function is as follows:&lt;br /&gt;
 if should_check_policy_name&lt;br /&gt;
   Call sub-function should_check_policy_name&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def should_check_policy_name(old valid_penalty, old error_message)&lt;br /&gt;
   if check policy with same name(currenty name, instructor_id)&lt;br /&gt;
     error_message = new error message&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
&lt;br /&gt;
In the above sub-function, the should_check name was changed to be more explicit and the should check if-statement was refactored to be in a different method to improve readability.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Proposed Solution'''==&lt;br /&gt;
&lt;br /&gt;
There are multiple routes we can go down to tackle this issue. One way to break down a long method would be to refactor the create method, we can extract and rewrite the save_late_policy method. We also have to refactor the duplicate name check method by rewriting the if statements as smaller sub methods. We would then have to write tests for all the new functionality/refactoring done.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=='''Updated Works'''==&lt;br /&gt;
&lt;br /&gt;
== Create and Update Functions ==&lt;br /&gt;
&lt;br /&gt;
The Create and Update functions were refactored into multiple new helper functions. These functions were created in the hopes to reduce the amount of repeated code as well as increase the readability and maintainability of said functions.&lt;br /&gt;
&lt;br /&gt;
Create: The create function has been simplified to improve its readability and size.&lt;br /&gt;
 # Create method can create a new late policy.&lt;br /&gt;
 # There are few check points before creating a late policy which are written in the if/else statements.&lt;br /&gt;
 def create&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   valid_penalty, error_message = validate_input&lt;br /&gt;
   if error_message&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
   # If penalty  is valid then tries to update and save.&lt;br /&gt;
   if valid_penalty&lt;br /&gt;
     create_new_late_policy(late_policy_params)&lt;br /&gt;
     save_late_policy&lt;br /&gt;
     redirect_to_policy('index')&lt;br /&gt;
   # If any of above checks fails, then redirect to create a new late policy again.&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Update: The update function received a similar improvement, being shortened and simplified.&lt;br /&gt;
 # Update method can update late policy. There are few check points before updating a late policy which are written in the if/else statements.&lt;br /&gt;
 def update&lt;br /&gt;
   penalty_policy = LatePolicy.find(params[:id])&lt;br /&gt;
   # First this function validates the input then save if the input is valid.&lt;br /&gt;
   _valid_penalty, error_message = validate_input(true)&lt;br /&gt;
   if error_message&lt;br /&gt;
     handle_error(error_message)&lt;br /&gt;
     redirect_to_policy('edit')&lt;br /&gt;
   # If there are no errors, then save the record.&lt;br /&gt;
   else&lt;br /&gt;
     begin&lt;br /&gt;
       penalty_policy.update_attributes(late_policy_params)&lt;br /&gt;
       save_late_policy&lt;br /&gt;
       redirect_to_policy('index')&lt;br /&gt;
     # If something unexpected happens while updating, then redirect to the edit page of that policy again.&lt;br /&gt;
     rescue StandardError&lt;br /&gt;
       handle_error('The following error occurred while updating the late policy: ')&lt;br /&gt;
       redirect_to_policy('edit')&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
Both create and update have been refactored and split up into various helper functions, many of them to help reduce duplicate code and size in their caller.&lt;br /&gt;
 # Create and save the late policy with the required params&lt;br /&gt;
 def create_new_late_policy(params)&lt;br /&gt;
   @late_policy = LatePolicy.new(params)&lt;br /&gt;
   @late_policy.instructor_id = instructor_id&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Saves the late policy called from create or update&lt;br /&gt;
 def save_late_policy&lt;br /&gt;
   begin&lt;br /&gt;
     @late_policy.save!&lt;br /&gt;
     if caller_locations(2,1)[0].label == 'update'&lt;br /&gt;
       # If the method that called this is update&lt;br /&gt;
       LatePolicy.update_calculated_penalty_objects(penalty_policy)&lt;br /&gt;
     end&lt;br /&gt;
     # The code at the end of the string gets the name of the last method (create, update) and adds a d (created, updated)&lt;br /&gt;
     flash[:notice] = &amp;quot;The late policy was successfully #{caller_locations(2,1)[0].label}d.&amp;quot;&lt;br /&gt;
   rescue StandardError&lt;br /&gt;
     # If something unexpected happens while saving the record in to database then displays a flash notice and redirect to create a new late policy again.&lt;br /&gt;
     handle_error('The following error occurred while saving the late policy: ')&lt;br /&gt;
     redirect_to_policy('new')&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # A method to extrapolate out the flashing of error messages&lt;br /&gt;
 def handle_error(error_message)&lt;br /&gt;
   flash[:error] = error_message&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # A method to extrapolate out the redirecting to policy controller states&lt;br /&gt;
 def redirect_to_policy(location)&lt;br /&gt;
   if location == &amp;quot;edit&amp;quot;&lt;br /&gt;
     # If the location is the edit screen, use the old id that was inputted&lt;br /&gt;
     redirect_to action: location, id: params[:id]&lt;br /&gt;
   else&lt;br /&gt;
     redirect_to action: location&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
The create_new_late_policy function is refactored from the create method to move all the code required to create a new blank late policy into one method. This slightly improves readability in the create method. The save_late_policy function has been refactored from duplicate code in both create and update. Both functions had very similar code with only one line of difference as well as a few characters in strings. This function shortens both of the other functions down by separating out this duplicate code into a private function. The same can be said for both the handle_error function and redirect_to_policy function.&lt;/div&gt;</summary>
		<author><name>Acbondi</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=151337</id>
		<title>CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=151337"/>
		<updated>2023-11-14T21:38:26Z</updated>

		<summary type="html">&lt;p&gt;Acbondi: Moved the previous text below statement to be more clear&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=='''Introduction'''==&lt;br /&gt;
The late_policies_controller.rb class houses the LatePoliciesController that controls the CRUD operations on late policies. However, there are many problems with the current implementation of this controller. In its current state, many functions are too long and repetitive as well as having inadequate variable names, comments, and error messages. This controller would benefit with optimizing its functions and various other aspects of the file.&lt;br /&gt;
&lt;br /&gt;
== About the LatePoliciesController ==&lt;br /&gt;
The LatePoliciesController provides CRUD functions to create, read, update, and destroy late policies. These include the index, show, new, edit, create, update, and destroy functions. Other functions are provided to allow it to work seamlessly within the framework of the overall project, including the action_allowed?, duplicate_name_check, validate_input, and various parameter and input functions. These additional functions are helper functions that ensure that the late policy can be created or updated based on if the user has the required permissions, doesn't enter a duplicate name, and inputs valid information to the late policy.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
*Refactor Long Methods: Longer functions should be refactored into smaller sub-functions to improve readability and make it easier for future alterations of the code.&lt;br /&gt;
*Improve Comments: More comments should be added to allow for users to easily follow through a given function and understand the specifics of its code statements.&lt;br /&gt;
*Follow the DRY Principle: Repeated code should be removed or moved into helper functions to allow for reusability of common code.&lt;br /&gt;
*Improve Testing: More tests should be created to ensure that everything works as intended and no unexpected errors occur, either exceptions or errors in logic.&lt;br /&gt;
*All changes must be done without the addition of new gems and must be clearly documented.&lt;br /&gt;
&lt;br /&gt;
== Functions to Optimize ==&lt;br /&gt;
*create: This function will be broken down into smaller functions to allow a more readable creation of new late policies. The error handling will also be altered to improve readability.&lt;br /&gt;
*update: Various comments will be added to the function as well as breaking down the code used for saving the late policy into a helper method to shorten the update method and make it more intuitive.&lt;br /&gt;
*duplicate_name_check: This function has various separate if statements that check for various things. These if statements will be broken down into separate helper methods to check for each individually. The duplicate_name_check function will be the main function that calls the various sub-functions so that it is clear what is being checked at a given step.&lt;br /&gt;
*validate_input: Similar to the duplicate_name_check function, this function has various if statements that can be refactored into smaller functions to check each input individually.&lt;br /&gt;
*Tests: Tests for creating and updating new late policies will be created. These tests will check for invalid inputs, correct error messages, etc. as well as ensure that edge cases are also captured correctly by the controller. New tests will also be created to ensure that previous functions, like the read and destroy functions, work correctly.&lt;br /&gt;
&lt;br /&gt;
== Create Function ==&lt;br /&gt;
&lt;br /&gt;
== Update Function ==&lt;br /&gt;
&lt;br /&gt;
== Duplicate Name Check Function ==&lt;br /&gt;
 if is_update&lt;br /&gt;
      existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
      if existing_late_policy.policy_name == params[:late_policy][:policy_name]&lt;br /&gt;
        should_check = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if should_check&lt;br /&gt;
      if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
        error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
        valid_penalty = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
The above code is the current implementation of some duplication checks in this function. These if statements can be refactored into smaller sub-functions.&lt;br /&gt;
The pseudo-code for one sub-function is as follows:&lt;br /&gt;
 if should_check_policy_name&lt;br /&gt;
   Call sub-function should_check_policy_name&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def should_check_policy_name(old valid_penalty, old error_message)&lt;br /&gt;
   if check policy with same name(currenty name, instructor_id)&lt;br /&gt;
     error_message = new error message&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
&lt;br /&gt;
In the above sub-function, the should_check name was changed to be more explicit and the should check if-statement was refactored to be in a different method to improve readability.&lt;br /&gt;
&lt;br /&gt;
== Validate Input Function ==&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
-----------------------------------------------------------------------&lt;br /&gt;
(Previous text below)&lt;br /&gt;
-----------------------------------------------------------------------&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
After an instructor gave a grade to an assignment, there is no way to track who gave the grade.&lt;br /&gt;
A grading audit trail must be created and the following information needs to be stored: &lt;br /&gt;
:1. When a grade is assigned by an instructor, there needs to be an indication of who did it and when it was done. &lt;br /&gt;
:2. Comments previously provided by other instructors must also be preserved.&lt;br /&gt;
&lt;br /&gt;
This information needs to be stored every time an instructor edits a grade/comment and clicks the save button.&lt;br /&gt;
&lt;br /&gt;
== Overview of Major Changes By Previous Teams ==&lt;br /&gt;
&lt;br /&gt;
*A new table was added to the database ('''grading_history'''), along with the corresponding model ('''grading_history.rb''') and controller ('''grading_history_controller.rb''').&lt;br /&gt;
**Whenever an instructor submits a new grade, or edits an existing grade, the '''grading_history_controller''' saves a new history entry to the database.&lt;br /&gt;
&lt;br /&gt;
*Two models for specific types of histories were added: '''review_grading_history.rb''', and '''submission_grading_history.rb'''.&lt;br /&gt;
&lt;br /&gt;
*A view for displaying the grading history of a particular assignment or review was added ('''grading_histories/index.html.erb''').&lt;br /&gt;
&lt;br /&gt;
*THIS IS FROM THE FIRST TEAM NEED TO ADD MORE FROM THE SECOND TEAM&lt;br /&gt;
&lt;br /&gt;
=='''Proposed Solution'''==&lt;/div&gt;</summary>
		<author><name>Acbondi</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=151336</id>
		<title>CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2382._Optimizing_the_LatePoliciesController&amp;diff=151336"/>
		<updated>2023-11-14T21:37:27Z</updated>

		<summary type="html">&lt;p&gt;Acbondi: Created more sections and filled some of them in for the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=='''Introduction'''==&lt;br /&gt;
The late_policies_controller.rb class houses the LatePoliciesController that controls the CRUD operations on late policies. However, there are many problems with the current implementation of this controller. In its current state, many functions are too long and repetitive as well as having inadequate variable names, comments, and error messages. This controller would benefit with optimizing its functions and various other aspects of the file.&lt;br /&gt;
&lt;br /&gt;
== About the LatePoliciesController ==&lt;br /&gt;
The LatePoliciesController provides CRUD functions to create, read, update, and destroy late policies. These include the index, show, new, edit, create, update, and destroy functions. Other functions are provided to allow it to work seamlessly within the framework of the overall project, including the action_allowed?, duplicate_name_check, validate_input, and various parameter and input functions. These additional functions are helper functions that ensure that the late policy can be created or updated based on if the user has the required permissions, doesn't enter a duplicate name, and inputs valid information to the late policy.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
*Refactor Long Methods: Longer functions should be refactored into smaller sub-functions to improve readability and make it easier for future alterations of the code.&lt;br /&gt;
*Improve Comments: More comments should be added to allow for users to easily follow through a given function and understand the specifics of its code statements.&lt;br /&gt;
*Follow the DRY Principle: Repeated code should be removed or moved into helper functions to allow for reusability of common code.&lt;br /&gt;
*Improve Testing: More tests should be created to ensure that everything works as intended and no unexpected errors occur, either exceptions or errors in logic.&lt;br /&gt;
*All changes must be done without the addition of new gems and must be clearly documented.&lt;br /&gt;
&lt;br /&gt;
== Functions to Optimize ==&lt;br /&gt;
*create: This function will be broken down into smaller functions to allow a more readable creation of new late policies. The error handling will also be altered to improve readability.&lt;br /&gt;
*update: Various comments will be added to the function as well as breaking down the code used for saving the late policy into a helper method to shorten the update method and make it more intuitive.&lt;br /&gt;
*duplicate_name_check: This function has various separate if statements that check for various things. These if statements will be broken down into separate helper methods to check for each individually. The duplicate_name_check function will be the main function that calls the various sub-functions so that it is clear what is being checked at a given step.&lt;br /&gt;
*validate_input: Similar to the duplicate_name_check function, this function has various if statements that can be refactored into smaller functions to check each input individually.&lt;br /&gt;
*Tests: Tests for creating and updating new late policies will be created. These tests will check for invalid inputs, correct error messages, etc. as well as ensure that edge cases are also captured correctly by the controller. New tests will also be created to ensure that previous functions, like the read and destroy functions, work correctly.&lt;br /&gt;
&lt;br /&gt;
== Create Function ==&lt;br /&gt;
&lt;br /&gt;
== Update Function ==&lt;br /&gt;
&lt;br /&gt;
== Duplicate Name Check Function ==&lt;br /&gt;
 if is_update&lt;br /&gt;
      existing_late_policy = LatePolicy.find(params[:id])&lt;br /&gt;
      if existing_late_policy.policy_name == params[:late_policy][:policy_name]&lt;br /&gt;
        should_check = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if should_check&lt;br /&gt;
      if LatePolicy.check_policy_with_same_name(params[:late_policy][:policy_name], instructor_id)&lt;br /&gt;
        error_message = prefix + 'A policy with the same name ' + params[:late_policy][:policy_name] + ' already exists.'&lt;br /&gt;
        valid_penalty = false&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
The above code is the current implementation of some duplication checks in this function. These if statements can be refactored into smaller sub-functions.&lt;br /&gt;
The pseudo-code for one sub-function is as follows:&lt;br /&gt;
 if should_check_policy_name&lt;br /&gt;
   Call sub-function should_check_policy_name&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 def should_check_policy_name(old valid_penalty, old error_message)&lt;br /&gt;
   if check policy with same name(currenty name, instructor_id)&lt;br /&gt;
     error_message = new error message&lt;br /&gt;
     valid_penalty = false&lt;br /&gt;
   end&lt;br /&gt;
   return valid_penalty, error_message&lt;br /&gt;
&lt;br /&gt;
In the above sub-function, the should_check name was changed to be more explicit and the should check if-statement was refactored to be in a different method to improve readability.&lt;br /&gt;
&lt;br /&gt;
== Validate Input Function ==&lt;br /&gt;
&lt;br /&gt;
== Test Plan ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----------------------------------------------------------------------&lt;br /&gt;
(Previous text below)&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
After an instructor gave a grade to an assignment, there is no way to track who gave the grade.&lt;br /&gt;
A grading audit trail must be created and the following information needs to be stored: &lt;br /&gt;
:1. When a grade is assigned by an instructor, there needs to be an indication of who did it and when it was done. &lt;br /&gt;
:2. Comments previously provided by other instructors must also be preserved.&lt;br /&gt;
&lt;br /&gt;
This information needs to be stored every time an instructor edits a grade/comment and clicks the save button.&lt;br /&gt;
&lt;br /&gt;
== Overview of Major Changes By Previous Teams ==&lt;br /&gt;
&lt;br /&gt;
*A new table was added to the database ('''grading_history'''), along with the corresponding model ('''grading_history.rb''') and controller ('''grading_history_controller.rb''').&lt;br /&gt;
**Whenever an instructor submits a new grade, or edits an existing grade, the '''grading_history_controller''' saves a new history entry to the database.&lt;br /&gt;
&lt;br /&gt;
*Two models for specific types of histories were added: '''review_grading_history.rb''', and '''submission_grading_history.rb'''.&lt;br /&gt;
&lt;br /&gt;
*A view for displaying the grading history of a particular assignment or review was added ('''grading_histories/index.html.erb''').&lt;br /&gt;
&lt;br /&gt;
*THIS IS FROM THE FIRST TEAM NEED TO ADD MORE FROM THE SECOND TEAM&lt;br /&gt;
&lt;br /&gt;
=='''Proposed Solution'''==&lt;/div&gt;</summary>
		<author><name>Acbondi</name></author>
	</entry>
</feed>