<?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=Tkini</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=Tkini"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Tkini"/>
	<updated>2026-07-18T06:07:09Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150384</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150384"/>
		<updated>2023-05-02T22:24:03Z</updated>

		<summary type="html">&lt;p&gt;Tkini: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&amp;lt;br&amp;gt;&lt;br /&gt;
A Questionnaire can have multiple Questions as a part of it. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few. There are multiple type of Questionnaires like Review, MetaReview, Assignment etc.&amp;lt;br&amp;gt;&lt;br /&gt;
To sum it off, we can have many types of Questionnaires and each would have possibly multiple types of Questions. There can be numerous questionnaires of the same kind for a given Questionnaire type.&lt;br /&gt;
The following 3 images would give a more clear picture about the information stated above -&lt;br /&gt;
* The types of Questionnaires present -&lt;br /&gt;
[[File:E2326-questionnaire_types.png|1000px|center]]&lt;br /&gt;
* The list if Questionnaires of type MetaReview - &lt;br /&gt;
[[File:E2326-questionnaire_list.png|1000px|center]]&lt;br /&gt;
* The list of Questions in a Questionnaire -&lt;br /&gt;
[[File:E2326-questions.png|1000px|center]]&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&amp;lt;br&amp;gt;&lt;br /&gt;
The following functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. &amp;lt;br&amp;gt;&lt;br /&gt;
Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e Commit]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a Commit]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured rendered an error&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|method &amp;lt;code&amp;gt;update_questionnaire_questions&amp;lt;/code&amp;gt;&lt;br /&gt;
|As per DRY, we removed the code to update the questionnaire's questions from &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; to the helper class.&lt;br /&gt;
|This will make the code more DRY and maintainable &lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/b8b504aeeb459958115fa4aed4df2cc1c61ddaf3 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Test Plan and Implementation =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
*All methods are well tested so there was no need to add any additional tests&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;br /&gt;
*Below is quiz_questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_quiz_questionnaries_test.jpg|1000px|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
'''Github''': https://github.com/Soultrekker21/expertiza &amp;lt;br&amp;gt;&lt;br /&gt;
'''Pull Request''': https://github.com/expertiza/expertiza/pull/2576 &amp;lt;br&amp;gt;&lt;br /&gt;
'''Current VCL''': http://152.7.178.100:3000/ &amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150383</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150383"/>
		<updated>2023-05-02T22:22:12Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&amp;lt;br&amp;gt;&lt;br /&gt;
A Questionnaire can have multiple Questions as a part of it. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few. There are multiple type of Questionnaires like Review, MetaReview, Assignment etc.&amp;lt;br&amp;gt;&lt;br /&gt;
To sum it off, we can have many types of Questionnaires and each would have possibly multiple types of Questions. There can be numerous questionnaires of the same kind for a given Questionnaire type.&lt;br /&gt;
The following 3 images would give a more clear picture about the information stated above -&lt;br /&gt;
* The types of Questionnaires present -&lt;br /&gt;
[[File:E2326-questionnaire_types.png|1000px|center]]&lt;br /&gt;
* The list if Questionnaires of type MetaReview - &lt;br /&gt;
[[File:E2326-questionnaire_list.png|1000px|center]]&lt;br /&gt;
* The list of Questions in a Questionnaire -&lt;br /&gt;
[[File:E2326-questions.png|1000px|center]]&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&amp;lt;br&amp;gt;&lt;br /&gt;
The following functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. &amp;lt;br&amp;gt;&lt;br /&gt;
Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e Commit]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a Commit]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured rendered an error&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|method &amp;lt;code&amp;gt;update_questionnaire_questions&amp;lt;/code&amp;gt;&lt;br /&gt;
|As per DRY, we removed the code to update the questionnaire's questions from &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; to the helper class.&lt;br /&gt;
|This will make the code more DRY and maintainable &lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/b8b504aeeb459958115fa4aed4df2cc1c61ddaf3 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
'''Github''': https://github.com/Soultrekker21/expertiza &amp;lt;br&amp;gt;&lt;br /&gt;
'''Pull Request''': https://github.com/expertiza/expertiza/pull/2576 &amp;lt;br&amp;gt;&lt;br /&gt;
'''Current VCL''': http://152.7.178.100:3000/ &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;br /&gt;
*Below is quiz_questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_quiz_questionnaries_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:E2326-questionnaire_types.png&amp;diff=150382</id>
		<title>File:E2326-questionnaire types.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:E2326-questionnaire_types.png&amp;diff=150382"/>
		<updated>2023-05-02T22:20:41Z</updated>

		<summary type="html">&lt;p&gt;Tkini: all types of questionnaires&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;all types of questionnaires&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:E2326-questionnaire_list.png&amp;diff=150381</id>
		<title>File:E2326-questionnaire list.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:E2326-questionnaire_list.png&amp;diff=150381"/>
		<updated>2023-05-02T22:19:48Z</updated>

		<summary type="html">&lt;p&gt;Tkini: List of questionnaire in Meta review&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;List of questionnaire in Meta review&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:E2326-questions.png&amp;diff=150380</id>
		<title>File:E2326-questions.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:E2326-questions.png&amp;diff=150380"/>
		<updated>2023-05-02T22:19:03Z</updated>

		<summary type="html">&lt;p&gt;Tkini: lists of questions in questionnaire&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;lists of questions in questionnaire&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150379</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150379"/>
		<updated>2023-05-02T22:17:42Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&amp;lt;br&amp;gt;&lt;br /&gt;
A Questionnaire can have multiple Questions as a part of it. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few. There are multiple type of Questionnaires like Review, MetaReview, Assignment etc.&amp;lt;br&amp;gt;&lt;br /&gt;
To sum it off, we can have many types of Questionnaires and each would have possibly multiple types of Questions. There can be numerous questionnaires of the same kind for a given Questionnaire type.&lt;br /&gt;
The following 3 images would give a more clear picture about the information stated above -&lt;br /&gt;
* The types of Questionnaires present -&lt;br /&gt;
[[File:E2326-questionnaire types.png|1000px|center]]&lt;br /&gt;
* The list if Questionnaires of type MetaReview - &lt;br /&gt;
[[File:E2326-questionnaire_list.png|1000px|center]]&lt;br /&gt;
* The list of Questions in a Questionnaire -&lt;br /&gt;
[[File:E2326-questions.png|1000px|center]]&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&amp;lt;br&amp;gt;&lt;br /&gt;
The following functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. &amp;lt;br&amp;gt;&lt;br /&gt;
Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e Commit]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a Commit]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured rendered an error&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|method &amp;lt;code&amp;gt;update_questionnaire_questions&amp;lt;/code&amp;gt;&lt;br /&gt;
|As per DRY, we removed the code to update the questionnaire's questions from &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; to the helper class.&lt;br /&gt;
|This will make the code more DRY and maintainable &lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/b8b504aeeb459958115fa4aed4df2cc1c61ddaf3 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
'''Github''': https://github.com/Soultrekker21/expertiza &amp;lt;br&amp;gt;&lt;br /&gt;
'''Pull Request''': https://github.com/expertiza/expertiza/pull/2576 &amp;lt;br&amp;gt;&lt;br /&gt;
'''Current VCL''': http://152.7.178.100:3000/ &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;br /&gt;
*Below is quiz_questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_quiz_questionnaries_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150378</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150378"/>
		<updated>2023-05-02T22:15:24Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&amp;lt;br&amp;gt;&lt;br /&gt;
A Questionnaire can have multiple Questions as a part of it. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few. There are multiple type of Questionnaires like Review, MetaReview, Assignment etc.&amp;lt;br&amp;gt;&lt;br /&gt;
To sum it off, we can have many types of Questionnaires and each would have possibly multiple types of Questions. There can be numerous questionnaires of the same kind for a given Questionnaire type.&lt;br /&gt;
The following 3 images would give a more clear picture about the information stated above -&lt;br /&gt;
* The types of Questionnaires present -&lt;br /&gt;
[[File:E2326_quiz_questionnaries_test.jpg|1000px|center]]&lt;br /&gt;
* The list if Questionnaires of type MetaReview - &lt;br /&gt;
[[File:E2326_quiz_questionnaries_test.jpg|1000px|center]]&lt;br /&gt;
* The list of Questions in a Questionnaire -&lt;br /&gt;
[[File:E2326_quiz_questionnaries_test.jpg|1000px|center]]&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&amp;lt;br&amp;gt;&lt;br /&gt;
The following functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. &amp;lt;br&amp;gt;&lt;br /&gt;
Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e Commit]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a Commit]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured rendered an error&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|method &amp;lt;code&amp;gt;update_questionnaire_questions&amp;lt;/code&amp;gt;&lt;br /&gt;
|As per DRY, we removed the code to update the questionnaire's questions from &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; to the helper class.&lt;br /&gt;
|This will make the code more DRY and maintainable &lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/b8b504aeeb459958115fa4aed4df2cc1c61ddaf3 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
'''Github''': https://github.com/Soultrekker21/expertiza &amp;lt;br&amp;gt;&lt;br /&gt;
'''Pull Request''': https://github.com/expertiza/expertiza/pull/2576 &amp;lt;br&amp;gt;&lt;br /&gt;
'''Current VCL''': http://152.7.178.100:3000/ &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;br /&gt;
*Below is quiz_questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_quiz_questionnaries_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150377</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150377"/>
		<updated>2023-05-02T22:14:54Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&amp;lt;br&amp;gt;&lt;br /&gt;
A Questionnaire can have multiple Questions as a part of it. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few. There are multiple type of Questionnaires like Review, MetaReview, Assignment etc.&amp;lt;br&amp;gt;&lt;br /&gt;
To sum it off, we can have many types of Questionnaires and each would have possibly multiple types of Questions. There can be numerous questionnaires of the same kind for a given Questionnaire type.&lt;br /&gt;
The following 3 images would give a more clear picture about the information stated above -&lt;br /&gt;
* The types of Questionnaires present -&lt;br /&gt;
&lt;br /&gt;
* The list if Questionnaires of type MetaReview - &lt;br /&gt;
&lt;br /&gt;
* The list of Questions in a Questionnaire -&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&amp;lt;br&amp;gt;&lt;br /&gt;
The following functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. &amp;lt;br&amp;gt;&lt;br /&gt;
Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e Commit]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a Commit]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured rendered an error&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|method &amp;lt;code&amp;gt;update_questionnaire_questions&amp;lt;/code&amp;gt;&lt;br /&gt;
|As per DRY, we removed the code to update the questionnaire's questions from &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; to the helper class.&lt;br /&gt;
|This will make the code more DRY and maintainable &lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/b8b504aeeb459958115fa4aed4df2cc1c61ddaf3 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
'''Github''': https://github.com/Soultrekker21/expertiza &amp;lt;br&amp;gt;&lt;br /&gt;
'''Pull Request''': https://github.com/expertiza/expertiza/pull/2576 &amp;lt;br&amp;gt;&lt;br /&gt;
'''Current VCL''': http://152.7.178.100:3000/ &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;br /&gt;
*Below is quiz_questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_quiz_questionnaries_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150376</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150376"/>
		<updated>2023-05-02T22:11:35Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&amp;lt;br&amp;gt;&lt;br /&gt;
A Questionnaire can have multiple Questions as a part of it. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few. There are multiple type of Questionnaires like Review, MetaReview, Assignment etc.&amp;lt;br&amp;gt;&lt;br /&gt;
To sum it off, we can have many types of Questionnaires and each would have possibly multiple types of Questions. There can be numerous questionnaires of the same kind for a given Questionnaire type.&lt;br /&gt;
The following 3 images would give a more clear picture about the information stated above -&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&amp;lt;br&amp;gt;&lt;br /&gt;
The following functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. &amp;lt;br&amp;gt;&lt;br /&gt;
Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e Commit]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a Commit]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba Commit]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c Commit]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured rendered an error&lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[https://github.com/SoulTrekker21/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|16&lt;br /&gt;
|method &amp;lt;code&amp;gt;update_questionnaire_questions&amp;lt;/code&amp;gt;&lt;br /&gt;
|As per DRY, we removed the code to update the questionnaire's questions from &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; to the helper class.&lt;br /&gt;
|This will make the code more DRY and maintainable &lt;br /&gt;
|[https://github.com/Soultrekker21/expertiza/commit/b8b504aeeb459958115fa4aed4df2cc1c61ddaf3 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
'''Github''': https://github.com/Soultrekker21/expertiza &amp;lt;br&amp;gt;&lt;br /&gt;
'''Pull Request''': https://github.com/expertiza/expertiza/pull/2576 &amp;lt;br&amp;gt;&lt;br /&gt;
'''Current VCL''': http://152.7.178.100:3000/ &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;br /&gt;
*Below is quiz_questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_quiz_questionnaries_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150365</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150365"/>
		<updated>2023-05-02T21:52:41Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&amp;lt;br&amp;gt;&lt;br /&gt;
A Questionnaire can have multiple Questions as a part of it. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few. There are multiple type of Questionnaires like Review, MetaReview, Assignment etc.&amp;lt;br&amp;gt;&lt;br /&gt;
To sum it off, we can have many types of Questionnaires and each would have possibly multiple types of Questions. There can be numerous questionnaires of the same kind for a given Questionnaire type.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&amp;lt;br&amp;gt;&lt;br /&gt;
The following functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. &amp;lt;br&amp;gt;&lt;br /&gt;
Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150364</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150364"/>
		<updated>2023-05-02T21:43:35Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&amp;lt;br&amp;gt;&lt;br /&gt;
A Questionnaire can have multiple Questions as a part of it. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few. There are multiple type of Questionnaires like Review, MetaReview, Assignment etc.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&amp;lt;br&amp;gt;&lt;br /&gt;
The following functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. &amp;lt;br&amp;gt;&lt;br /&gt;
Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150363</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150363"/>
		<updated>2023-05-02T21:41:28Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Project Purpose */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&amp;lt;br&amp;gt;&lt;br /&gt;
The following functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. &amp;lt;br&amp;gt;&lt;br /&gt;
Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150362</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150362"/>
		<updated>2023-05-02T21:40:28Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Project Purpose */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.&amp;lt;br&amp;gt;&lt;br /&gt;
This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150361</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150361"/>
		<updated>2023-05-02T21:37:40Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= All Changes Implemented =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150360</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150360"/>
		<updated>2023-05-02T21:36:56Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaires are used primarily by instructors to create question forms/ reviews, etc. As a student, you might have seen them while performing reviews for peers. The questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions and taking quizzes and surveys.  All of these are subclasses of the Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also, we notice that the Questionnaire controller has a parent-child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox, and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|{ede}[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150358</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150358"/>
		<updated>2023-05-02T21:33:06Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|13&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|14&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|15&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150357</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150357"/>
		<updated>2023-05-02T21:30:47Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150355</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150355"/>
		<updated>2023-05-02T21:26:37Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code re-usability&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150354</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150354"/>
		<updated>2023-05-02T21:24:33Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150353</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150353"/>
		<updated>2023-05-02T21:23:49Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9d3a846d862cfe4661c858e98902876cfe789a64]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;delete_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/669fc8e47c7a81223d48748f785af10b359f942e]&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4edd184930109b920f7cf714b10dd22fd62c1f41]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor or add more comments to the following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; and the use of each cannot be easily understood&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/9edb52d359a1e341985259829bc7b4ddd224663a]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150350</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150350"/>
		<updated>2023-05-02T19:31:49Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
There are multiple types of questions created based on the parameters passed by the user to the controller. This led to two things, Objects being created dynamically which might not be of the acceptable kind, and code injection, as we are using unsanitized user input. &lt;br /&gt;
&lt;br /&gt;
We have decided to use the '''Factory design''' pattern instead where we create a type of Questionnaire based on the type of parameters passed. Hence instead of multiple if/else code blocks to check the kind of input passed, we use a factory method to create and return the Questionnaire/Question object. Additionally, Instead of using if/else checks in the factory method, we opt for using a Map to match the input param to an Object type which further cleaned our code. &lt;br /&gt;
&lt;br /&gt;
We employed '''SOLID''' principles, and shifted code that pertained to Questions from Questionnaire controller to Questions controller. This helps us better adhere to the '''Single Responsibility''' principle. We also shifted the common code out of the Questionnaire controller to helper classes to make the code more '''DRY'''.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|files&amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add a factory method that creates respective object based on the parameter that is being passed&lt;br /&gt;
|We use factory method in a helper file as that removes the code for creating an object from inside a function that just uses those objects&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/4721039e523505e2c07f0691d8a7d42af2dc87ba]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questionnaire factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove the usage of if/else or switch case and use a Hash Map for questions factory object creation&lt;br /&gt;
|We want to make our code more modular and extendable. Any change can be easily added to Hash Map rather than adding if else statements.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/a24b18cb1702188a4d04483de8ca407920fef775]&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|controller &amp;lt;code&amp;gt;advice_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|There needs to be a &amp;lt;code&amp;gt;.each&amp;lt;/code&amp;gt; after they keys are enumerated&lt;br /&gt;
|The Edit/View advice button was not working on the view where we create a questionnaire and new questions&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/690f8afe526d79c5811dcfbbc5dad826c1fd2c7c]&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that all the new methods in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; can work&lt;br /&gt;
|Newly added functions don't have a predefined route and it must be specified&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/843a12bce18bf441c8cb7e5b2a04d905bb155418]&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|file &amp;lt;code&amp;gt;routes.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Add some routes so that the delete functionality works for questionnaires&lt;br /&gt;
|The existing code had the functionality implemented but the route was not configured that rendered an error&lt;br /&gt;
|[https://github.com/expertiza/expertiza/commit/6647464ad7c478ad7cd6ba27beecdee2cfa492f9]&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;br /&gt;
*Below is questionnaires_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questionnaires_test.jpg|1000px|center]]&lt;br /&gt;
*Below is questions_controller_spec.rb tests run with &amp;lt;code&amp;gt;bundle exec rspec&amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:E2326_questions_test.jpg|1000px|center]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150345</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150345"/>
		<updated>2023-05-02T19:16:45Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150344</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150344"/>
		<updated>2023-05-02T19:16:20Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|Commit link[https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150343</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150343"/>
		<updated>2023-05-02T19:16:01Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|[Commit link][https://github.com/expertiza/expertiza/commit/7b875fbcbc0bc23db2d14280945f09c4cc968223 ]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150342</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150342"/>
		<updated>2023-05-02T19:15:13Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Proposed Design Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|9&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|10&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|11&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|12&lt;br /&gt;
|controller &amp;lt;code&amp;gt;quiz_questionnaire_controller.rb()&amp;lt;/code&amp;gt;&lt;br /&gt;
|There are multiple redirects to functions in the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|As some functions have been moved to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; they need to be refactored. &lt;br /&gt;
|Commit link&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Sample of Code Changes = &lt;br /&gt;
*Questionnaire Factory where the object is created with switch case using a HashMap in &amp;lt;code&amp;gt;questionnaire_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  #Map type to questionnaire&lt;br /&gt;
  QUESTIONNAIRE_MAP = {&lt;br /&gt;
    'ReviewQuestionnaire' =&amp;gt; ReviewQuestionnaire,&lt;br /&gt;
    'MetareviewQuestionnaire' =&amp;gt; MetareviewQuestionnaire,&lt;br /&gt;
    'AuthorFeedbackQuestionnaire' =&amp;gt; AuthorFeedbackQuestionnaire,&lt;br /&gt;
    'TeammateReviewQuestionnaire' =&amp;gt; TeammateReviewQuestionnaire,&lt;br /&gt;
    'AssignmentSurveyQuestionnaire' =&amp;gt; AssignmentSurveyQuestionnaire,&lt;br /&gt;
    'SurveyQuestionnaire' =&amp;gt; SurveyQuestionnaire,&lt;br /&gt;
    'GlobalSurveyQuestionnaire' =&amp;gt; GlobalSurveyQuestionnaire,&lt;br /&gt;
    'CourseSurveyQuestionnaire' =&amp;gt; CourseSurveyQuestionnaire,&lt;br /&gt;
    'BookmarkRatingQuestionnaire' =&amp;gt; BookmarkRatingQuestionnaire,&lt;br /&gt;
    'QuizQuestionnaire' =&amp;gt; QuizQuestionnaire&lt;br /&gt;
  }.freeze&lt;br /&gt;
  &lt;br /&gt;
  # factory method to create the appropriate questionnaire based on the type &lt;br /&gt;
  def questionnaire_factory(type)&lt;br /&gt;
    questionnaire = QUESTIONNAIRE_MAP[type]&lt;br /&gt;
    if questionnaire.nil?&lt;br /&gt;
      flash[:error] = 'Error: Undefined Questionnaire'&lt;br /&gt;
    else&lt;br /&gt;
      questionnaire.new&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Question Factory where the questions object is created using a HashMap in &amp;lt;code&amp;gt;question_helper.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
 module QuestionHelper&lt;br /&gt;
   # Maps type to question&lt;br /&gt;
   QUESTION_MAP = {&lt;br /&gt;
     'Criterion' =&amp;gt; Criterion,&lt;br /&gt;
     'Scale' =&amp;gt; Scale,&lt;br /&gt;
     'Cake' =&amp;gt; Cake,&lt;br /&gt;
     'Dropdown' =&amp;gt; Dropdown,&lt;br /&gt;
     'Checkbox' =&amp;gt; Checkbox,&lt;br /&gt;
     'TextArea' =&amp;gt; TextArea,&lt;br /&gt;
     'TextField' =&amp;gt; TextField,&lt;br /&gt;
     'UploadFile' =&amp;gt; UploadFile,&lt;br /&gt;
     'SectionHeader' =&amp;gt; SectionHeader,&lt;br /&gt;
     'TableHeader' =&amp;gt; TableHeader,&lt;br /&gt;
     'ColumnHeader' =&amp;gt; ColumnHeader&lt;br /&gt;
   }.freeze&lt;br /&gt;
   &lt;br /&gt;
   # factory method to create the appropriate question based on the type&lt;br /&gt;
   def question_factory(type, questionnaire_id, seq)&lt;br /&gt;
     question_class = QUESTION_MAP[type]&lt;br /&gt;
     if question_class.nil?&lt;br /&gt;
       flash[:error] = 'Error: Undefined Question'&lt;br /&gt;
     else&lt;br /&gt;
       question_class.create(txt: '', questionnaire_id: questionnaire_id, seq: seq, type: type, break_before: true)&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
  # Class variables - used questionnaires_controller.rb to set the parameters for a question.&lt;br /&gt;
  MAX_LABEL = 'Strongly agree'.freeze&lt;br /&gt;
  MIN_LABEL = 'Strongly disagree'.freeze&lt;br /&gt;
  SIZES = { 'Criterion' =&amp;gt; '50, 3', 'Cake' =&amp;gt; '50, 3', 'TextArea' =&amp;gt; '60, 5', 'TextField' =&amp;gt; '30' }.freeze&lt;br /&gt;
  ALTERNATIVES = { 'Dropdown' =&amp;gt; '0|1|2|3|4|5' }.freeze&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
  # Assigns corrresponding variables to questionnaire object.&lt;br /&gt;
  def set_questionnaire_parameters(private_flag, display)&lt;br /&gt;
    @questionnaire.private = private_flag&lt;br /&gt;
    @questionnaire.name = params[:questionnaire][:name]&lt;br /&gt;
    @questionnaire.instructor_id = session[:user].id&lt;br /&gt;
    @questionnaire.min_question_score = params[:questionnaire][:min_question_score]&lt;br /&gt;
    @questionnaire.max_question_score = params[:questionnaire][:max_question_score]&lt;br /&gt;
    @questionnaire.type = params[:questionnaire][:type]&lt;br /&gt;
    @questionnaire.display_type = display&lt;br /&gt;
    @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL&lt;br /&gt;
    @questionnaire.save&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*advice_controller.rb lines 57-64:  keys &amp;amp;&amp;amp; each_key methods return incorrectly, keys.each is proper syntax for this functionality&lt;br /&gt;
before:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
      	 QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end &lt;br /&gt;
after:&lt;br /&gt;
  unless params[:advice].nil?&lt;br /&gt;
    	 params[:advice].keys.each do |advice_key|&lt;br /&gt;
      	 # Updates the advice corresponding to the key&lt;br /&gt;
         QuestionAdvice.update(advice_key, advice: params[:advice] [advice_key.to_sym] [:advice])&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Questionnaires_controller.rb lines 89-99: removal of create_questionnaires method due to it having identical functionality to create&lt;br /&gt;
The following method was deleted&lt;br /&gt;
  def create_questionnaire&lt;br /&gt;
    @questionnaire = Object.const_get(params[:questionnaire][:type]).new(questionnaire_params)&lt;br /&gt;
    # Create Quiz content has been moved to Quiz Questionnaire Controller&lt;br /&gt;
    if @questionnaire.type != 'QuizQuestionnaire' # checking if it is a quiz questionnaire&lt;br /&gt;
      @questionnaire.instructor_id = Ta.get_my_instructor(session[:user].id) if session[:user].role.name == 'Teaching Assistant'&lt;br /&gt;
      save&lt;br /&gt;
      &lt;br /&gt;
      redirect_to controller: 'tree_display', action: 'list'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Important links ==&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;br /&gt;
&lt;br /&gt;
= Testing Implementation =&lt;br /&gt;
*Removal of create_questionnaire method test: Testing a non-existent method no longer necessary&lt;br /&gt;
*Aside from this we found that the questionnaire controller is already well tested&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150335</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150335"/>
		<updated>2023-05-02T18:19:57Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Project Purpose */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
We also noticed that there were many places that used constants like the text file are size or the default min and max scores being hard coded. This makes the code not suitable for extension as any change would need to be refactored in multiple places and break code easily. Thus we plan to modify the &amp;lt;code&amp;gt; models/questions.rb&amp;lt;/code&amp;gt; and add the constants there so that all files related to questions can have access to these constants. This would make the refactoring process very easy.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
* Questionnaire Factory where the object is created with switch case using a HashMap &lt;br /&gt;
&lt;br /&gt;
* Question Factory where the questions object is created using a HashMap&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150334</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150334"/>
		<updated>2023-05-02T18:17:22Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Project Purpose */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt; has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller which is fully developed.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the &amp;lt;code&amp;gt;questionnaire_controller.rb&amp;lt;/code&amp;gt; has multiple non CRUD methods that should have been in the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;. Our priority is to refactor these functions to the &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt; so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* &amp;lt;code&amp;gt;def delete_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def question_params&amp;lt;/code&amp;gt;  Move to questions_controller?&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_all_questions&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_new_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
* &amp;lt;code&amp;gt;def save_questions(questionnaire_id)&amp;lt;/code&amp;gt;  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
* Questionnaire Factory where the object is created with switch case using a HashMap &lt;br /&gt;
&lt;br /&gt;
* Question Factory where the questions object is created using a HashMap&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150333</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150333"/>
		<updated>2023-05-02T18:09:14Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Some Code Samples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the questionnaire_controller.rb has multiple non CRUD methods that should have been in the questions_controller.rb. Our priority is to refactor these functions to the questions_controller.rb so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* def delete_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def question_params  Move to questions_controller?&lt;br /&gt;
* def save_all_questions  Move to questions_controller&lt;br /&gt;
* def save_new_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def save_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
* Questionnaire Factory where the object is created with switch case using a HashMap &lt;br /&gt;
&lt;br /&gt;
* Question Factory where the questions object is created using a HashMap&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;models/question.rb&amp;lt;/code&amp;gt; that shows how the constants are used to store the parameters that would be used for object creation&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;def set_questionnaire_parameters&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150332</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150332"/>
		<updated>2023-05-02T17:49:13Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Some Code Samples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the questionnaire_controller.rb has multiple non CRUD methods that should have been in the questions_controller.rb. Our priority is to refactor these functions to the questions_controller.rb so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* def delete_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def question_params  Move to questions_controller?&lt;br /&gt;
* def save_all_questions  Move to questions_controller&lt;br /&gt;
* def save_new_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def save_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
* Questionnaire Factory where the object is created with switch case using a HashMap &lt;br /&gt;
&lt;br /&gt;
* Question Factory where the questions object is created using a HashMap&lt;br /&gt;
&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150331</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150331"/>
		<updated>2023-05-02T17:43:24Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller. There are multiple types of questions that can be added to a questionnaire like Criterion, Dropdown, Checkbox and TextArea to name a few.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the questionnaire_controller.rb has multiple non CRUD methods that should have been in the questions_controller.rb. Our priority is to refactor these functions to the questions_controller.rb so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* def delete_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def question_params  Move to questions_controller?&lt;br /&gt;
* def save_all_questions  Move to questions_controller&lt;br /&gt;
* def save_new_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def save_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150330</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150330"/>
		<updated>2023-05-02T17:37:59Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
Also we notice that Questionnaire controler has a parent child relationship with the QuizQuestionnaire controller.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the questionnaire_controller.rb has multiple non CRUD methods that should have been in the questions_controller.rb. Our priority is to refactor these functions to the questions_controller.rb so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* def delete_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def question_params  Move to questions_controller?&lt;br /&gt;
* def save_all_questions  Move to questions_controller&lt;br /&gt;
* def save_new_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def save_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150329</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150329"/>
		<updated>2023-05-02T17:36:40Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Project Purpose */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the questionnaire_controller.rb has multiple non CRUD methods that should have been in the questions_controller.rb. Our priority is to refactor these functions to the questions_controller.rb so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* def delete_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def question_params  Move to questions_controller?&lt;br /&gt;
* def save_all_questions  Move to questions_controller&lt;br /&gt;
* def save_new_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
* def save_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150328</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150328"/>
		<updated>2023-05-02T17:35:23Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Project Purpose */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
In the present code we see that the questionnaire_controller.rb has multiple non CRUD methods that should have been in the questions_controller.rb. Our priority is to refactor these functions to the questions_controller.rb so that we maintain the Single responsibility in the SOLID principles. We also notice that there are 2 places where there is code that is repeating itself so we extract the common code into a helper function to make the code more DRY.&lt;br /&gt;
the functions that need refactoring-&lt;br /&gt;
* def add_new_questions   Possibly move to questions_controller&lt;br /&gt;
  def delete_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
  def question_params  Move to questions_controller?&lt;br /&gt;
  def save_all_questions  Move to questions_controller&lt;br /&gt;
  def save_new_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
  def save_questions(questionnaire_id)  Move to questions_controller&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150327</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150327"/>
		<updated>2023-05-02T17:30:23Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
We can see that a Questionnaire can have multiple Questions. These questionnaires can be used as a part of an assignment.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150326</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150326"/>
		<updated>2023-05-02T17:20:43Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Design Pattern Used */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150325</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150325"/>
		<updated>2023-05-02T17:20:21Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Design Pattern Used */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
 We have decided to used the Factory design pattern where we create a type of Questionnaire based on the type of parameters passed. The earlier code was using multiple if else statements to check the parameter passed and then create the required object.\\&lt;br /&gt;
In the current code we give a call to a helper function in the &amp;lt;file name&amp;gt; file and expect it to return the object based on the string parameter passed.&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150324</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=150324"/>
		<updated>2023-05-02T16:54:03Z</updated>

		<summary type="html">&lt;p&gt;Tkini: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
&lt;br /&gt;
= Design Pattern Used =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Proposed Design Changes =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Move save_all_questions(), delete_questions(), save_new_questions(), save_questions()&lt;br /&gt;
|To be consistent with SOLID principle, these methods belong in questions_controller.rb&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|file &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor following vague method names&lt;br /&gt;
|There are confusing function names like &amp;lt;code&amp;gt;save_all_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_new_questions() &amp;lt;/code&amp;gt; ,  &amp;lt;code&amp;gt;save_questions() &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;save() &amp;lt;/code&amp;gt; &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added late&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|File &amp;lt;code&amp;gt;questionnaires_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|Refactor large methods&lt;br /&gt;
|Create, update, and delete are noticeably larger than most methods &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|method &amp;lt;code&amp;gt;questionnaire_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|method &amp;lt;code&amp;gt;question_helper()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change if/else to switch case and add default error checking to helper&lt;br /&gt;
|Code will be cleaner and there will needs to be catch all because there are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Some Code Samples = &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
Pull Request: https://github.com/expertiza/expertiza/pull/2576&lt;br /&gt;
= Test Plan =&lt;br /&gt;
* Make sure that current proposed changes don't break existing test cases.&lt;br /&gt;
* Add unit test for newly proposed methods. &lt;br /&gt;
* Shift existing test cases for questionnaire_controller_spec.rb to question_controller.rb corresponding to methods that are being shifted&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=149362</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=149362"/>
		<updated>2023-04-09T00:43:08Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Tushar */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
&lt;br /&gt;
= Design =&lt;br /&gt;
&lt;br /&gt;
== Tushar ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|method &amp;lt;code&amp;gt;add_new_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Store the used default value to some kind of constant in &amp;lt;code&amp;gt;questions.rb&amp;lt;/code&amp;gt;, so that they can be changed without refactoring code&lt;br /&gt;
|There are many literals used in the code and can change in future, so it is better to separate them &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a &lt;br /&gt;
|The &lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find&lt;br /&gt;
|The pr&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Change &amp;lt;code&amp;gt;params[:question].keys.each&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;params[:question].each_key&amp;lt;/code&amp;gt;&lt;br /&gt;
| This will improve the performance and uses a single enumerator&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|method &amp;lt;code&amp;gt;create()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Remove parenthesis around function call on line 72 &lt;br /&gt;
|Unnecessary parenthesis&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|method &amp;lt;code&amp;gt;save_all_questions()&amp;lt;/code&amp;gt;&lt;br /&gt;
|Find a way to refactor the code by using more variables or Procs that can be reused in &amp;lt;code&amp;gt;questions_controller.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|The process of saving all questions with 2 nested do blocks is difficult to understand&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|method create&lt;br /&gt;
|Move code related to creation of tree node to different function name &amp;lt;code&amp;gt;create_tree_node()&amp;lt;/code&amp;gt;&lt;br /&gt;
|The create method is very big and this would help in readability and code reusability&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ani ==&lt;br /&gt;
&lt;br /&gt;
'''questionnaires_controller.rb'''&lt;br /&gt;
&lt;br /&gt;
- Update the Create Method as it's too long and needs to be refactored. One way to do this is by breaking it down into smaller, more manageable methods. we can create separate methods to handle different parts of the creation process, such as one method to handle validation, one method to handle saving the questionnaire to the database, etc. &lt;br /&gt;
&lt;br /&gt;
- Update confusing names: To avoid confusion, it's important to give methods and controllers descriptive names that accurately reflect their functionality and if there is another method with a similar name that performs a similar function, it should be renamed to avoid confusion. Ex. Create and Create_Questionare&lt;br /&gt;
&lt;br /&gt;
- Unused methods should be removed. ( ex. create_questionnaire)&lt;br /&gt;
&lt;br /&gt;
- Magic Strings should be declared globally or as a configuration: Magic strings, or hard-coded string values in the code, can be difficult to maintain and debug. To avoid this, we can declare them globally or as a configuration in the application. This makes it easier to manage and update these values in one place.&lt;br /&gt;
&lt;br /&gt;
'''Factory methods for question and questionare'''&lt;br /&gt;
&lt;br /&gt;
- previous PRs employed the Factory method for questions and questionnaire object creation which can be used for more readable code.&lt;br /&gt;
&lt;br /&gt;
- There are no default else conditions/ error checks in factories as of now.&lt;br /&gt;
&lt;br /&gt;
== Jacob ==&lt;br /&gt;
*Comments still need to be removed in create function&lt;br /&gt;
&lt;br /&gt;
*questionnaire helper needs to be case statement by type (checking same object 'type')&lt;br /&gt;
&lt;br /&gt;
*question helper needs to be case statement by type (checking same object 'type')&lt;br /&gt;
&lt;br /&gt;
*save_all_questions &lt;br /&gt;
&lt;br /&gt;
=== Problems and planned changes ===&lt;br /&gt;
problems and planned changes&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
 Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
 test1&lt;br /&gt;
 test2&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=149357</id>
		<title>CSC/ECE 517 Spring 2023 -E2326 Refactor questionnaires controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-E2326_Refactor_questionnaires_controller.rb&amp;diff=149357"/>
		<updated>2023-04-09T00:00:43Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Tushar */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= Background =&lt;br /&gt;
&lt;br /&gt;
In Expertiza, Questionnaire is the superclass for all kinds of questionnaires and rubrics—rubrics for evaluating submissions and teammate contributions, and taking quizzes and surveys.  All of these are subclasses of Questionnaire.  questionnaires_controller.rb is charged with creating, displaying, and managing Questionnaires.  Because it is used so widely, malfunctions could cause bugs in many parts of the system; hence it is especially important that the code be clear.&lt;br /&gt;
&lt;br /&gt;
= Project Purpose =&lt;br /&gt;
&lt;br /&gt;
In recent years, questionnaires_controller.rb has been refactored repeatedly.  It is a lot clearer than it used to be.  But rough edges still remain.&lt;br /&gt;
question.rb contains a large number of constants.  It is not clear what they are used for.&lt;br /&gt;
There is a questionnaires_controller, but no questions_controller.  The questionnaires_controller creates Question objects.  This is not elegant, because a controller should only create objects of one type, the type of objects it controls.&lt;br /&gt;
&lt;br /&gt;
= Design =&lt;br /&gt;
&lt;br /&gt;
== Tushar ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! File/Function !! Change Proposed !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; &lt;br /&gt;
| The cur&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|&lt;br /&gt;
|Used &lt;br /&gt;
|We refa&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some&lt;br /&gt;
|Will be added later&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|Will be added later&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ani ==&lt;br /&gt;
== Jacob ==&lt;br /&gt;
&lt;br /&gt;
=== Problems and planned changes ===&lt;br /&gt;
problems and planned changes&lt;br /&gt;
&lt;br /&gt;
=== Important links ===&lt;br /&gt;
 Github: https://github.com/Soultrekker21/expertiza&lt;br /&gt;
&lt;br /&gt;
= Test Plan =&lt;br /&gt;
 test1&lt;br /&gt;
 test2&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148620</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148620"/>
		<updated>2023-03-28T03:10:42Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Expertiza Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Remove the switch case and moved code out of conditional &lt;br /&gt;
|There was repetition of code in multiple cases of switch statement. Moved them out of the case so that they are executed after the if statements.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/158bf7bc971a7bcfba7cf377cccdbdeef62cab40 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Testing / Test Plan ===&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
&lt;br /&gt;
=== Edge Cases ===&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ===&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Changes to Code wrt CodeClimate ===&lt;br /&gt;
* Removing duplicate Code in files related to our project&lt;br /&gt;
* Make the lines smaller if number of characters is more than 80&lt;br /&gt;
* Remove any kind of trailing spaces in the files&lt;br /&gt;
* Indentation issues were fixed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Coverage Report in the Build of the Pull Request ===&lt;br /&gt;
[[File:E2302_coveralls.png|1000px]]&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148618</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148618"/>
		<updated>2023-03-28T03:09:56Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Edge Cases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Remove the switch case and moved code out of conditional &lt;br /&gt;
|There was repetition of code in multiple cases of switch statement. Moved them out of the case so that they are executed after the if statements.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/158bf7bc971a7bcfba7cf377cccdbdeef62cab40 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ===&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Changes to Code wrt CodeClimate ===&lt;br /&gt;
* Removing duplicate Code in files related to our project&lt;br /&gt;
* Make the lines smaller if number of characters is more than 80&lt;br /&gt;
* Remove any kind of trailing spaces in the files&lt;br /&gt;
* Indentation issues were fixed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Coverage Report in the Build of the Pull Request ===&lt;br /&gt;
[[File:E2302_coveralls.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Testing / Test Plan ===&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
&lt;br /&gt;
=== Edge Cases ===&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148617</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148617"/>
		<updated>2023-03-28T03:09:42Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Testing / Test Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Remove the switch case and moved code out of conditional &lt;br /&gt;
|There was repetition of code in multiple cases of switch statement. Moved them out of the case so that they are executed after the if statements.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/158bf7bc971a7bcfba7cf377cccdbdeef62cab40 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ===&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Changes to Code wrt CodeClimate ===&lt;br /&gt;
* Removing duplicate Code in files related to our project&lt;br /&gt;
* Make the lines smaller if number of characters is more than 80&lt;br /&gt;
* Remove any kind of trailing spaces in the files&lt;br /&gt;
* Indentation issues were fixed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Coverage Report in the Build of the Pull Request ===&lt;br /&gt;
[[File:E2302_coveralls.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Testing / Test Plan ===&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
&lt;br /&gt;
== Edge Cases ==&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148614</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148614"/>
		<updated>2023-03-28T03:08:52Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Coverage Report in the Build of the Pull Request */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Remove the switch case and moved code out of conditional &lt;br /&gt;
|There was repetition of code in multiple cases of switch statement. Moved them out of the case so that they are executed after the if statements.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/158bf7bc971a7bcfba7cf377cccdbdeef62cab40 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ===&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Changes to Code wrt CodeClimate ===&lt;br /&gt;
* Removing duplicate Code in files related to our project&lt;br /&gt;
* Make the lines smaller if number of characters is more than 80&lt;br /&gt;
* Remove any kind of trailing spaces in the files&lt;br /&gt;
* Indentation issues were fixed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Coverage Report in the Build of the Pull Request ===&lt;br /&gt;
[[File:E2302_coveralls.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
== Testing / Test Plan ==&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
== Edge Cases ==&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148611</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148611"/>
		<updated>2023-03-28T03:07:46Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Coverage Report in the Build of the Pull Request */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Remove the switch case and moved code out of conditional &lt;br /&gt;
|There was repetition of code in multiple cases of switch statement. Moved them out of the case so that they are executed after the if statements.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/158bf7bc971a7bcfba7cf377cccdbdeef62cab40 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ===&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Changes to Code wrt CodeClimate ===&lt;br /&gt;
* Removing duplicate Code in files related to our project&lt;br /&gt;
* Make the lines smaller if number of characters is more than 80&lt;br /&gt;
* Remove any kind of trailing spaces in the files&lt;br /&gt;
* Indentation issues were fixed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Coverage Report in the Build of the Pull Request ===&lt;br /&gt;
[[File:E2302_coveralls.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing / Test Plan ==&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
== Edge Cases ==&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:E2302_coveralls.png&amp;diff=148609</id>
		<title>File:E2302 coveralls.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:E2302_coveralls.png&amp;diff=148609"/>
		<updated>2023-03-28T03:06:36Z</updated>

		<summary type="html">&lt;p&gt;Tkini: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148608</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148608"/>
		<updated>2023-03-28T03:05:21Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Expertiza Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Remove the switch case and moved code out of conditional &lt;br /&gt;
|There was repetition of code in multiple cases of switch statement. Moved them out of the case so that they are executed after the if statements.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/158bf7bc971a7bcfba7cf377cccdbdeef62cab40 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ===&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Changes to Code wrt CodeClimate ===&lt;br /&gt;
* Removing duplicate Code in files related to our project&lt;br /&gt;
* Make the lines smaller if number of characters is more than 80&lt;br /&gt;
* Remove any kind of trailing spaces in the files&lt;br /&gt;
* Indentation issues were fixed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Coverage Report in the Build of the Pull Request ===&lt;br /&gt;
&lt;br /&gt;
== Testing / Test Plan ==&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
== Edge Cases ==&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148607</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148607"/>
		<updated>2023-03-28T03:03:03Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Expertiza Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Remove the switch case and moved code out of conditional &lt;br /&gt;
|There was repetition of code in multiple cases of switch statement. Moved them out of the case so that they are executed after the if statements.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/158bf7bc971a7bcfba7cf377cccdbdeef62cab40 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ===&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Changes to Code wrt CodeClimate ===&lt;br /&gt;
* Removing duplicate Code in files related to our project&lt;br /&gt;
* Make the lines smaller if number of characters is more than 80&lt;br /&gt;
* Remove any kind of trailing spaces in the files&lt;br /&gt;
* Indentation issues were fixed&lt;br /&gt;
&lt;br /&gt;
== Testing / Test Plan ==&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
== Edge Cases ==&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148580</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148580"/>
		<updated>2023-03-28T02:42:41Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Changes to app/models/assignment_form.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Remove the switch case and moved code out of conditional &lt;br /&gt;
|There was repetition of code in multiple cases of switch statement. Moved them out of the case so that they are executed after the if statements.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/158bf7bc971a7bcfba7cf377cccdbdeef62cab40 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ===&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
== Testing / Test Plan ==&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
== Edge Cases ==&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148540</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148540"/>
		<updated>2023-03-28T01:50:21Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Commented out Tests so that the Build passed  = */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ===&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
== Testing / Test Plan ==&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
== Edge Cases ==&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148538</id>
		<title>CSC/ECE 517 Spring 2023 - E2302</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2302&amp;diff=148538"/>
		<updated>2023-03-28T01:49:28Z</updated>

		<summary type="html">&lt;p&gt;Tkini: /* Expertiza Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2302. Refactoring the Delayed Mailer and Scheduler==&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Expertiza Overview ==&lt;br /&gt;
&lt;br /&gt;
===Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an open-source software written using Ruby on Rails which functions as a learning management software system. It has many different functions and abilities including the ability to create assignments, quizzes, assignment groups, and topics, and also a complete mechanism for providing peer reviews and feedback for other groups and other teammates. &lt;br /&gt;
&lt;br /&gt;
''Sidekiq is a popular open-source gem for Ruby on Rails applications that provides a simple and efficient way to perform background processing for time-consuming tasks. It uses multi-threading to handle jobs asynchronously, allowing the main application to continue running while the background jobs are executed. Sidekiq provides a queue system that manages jobs and prioritizes them based on their urgency.'' The docs can be found here [https://sidekiq.org/about.html].&lt;br /&gt;
&lt;br /&gt;
Sidekiq is used in Expertiza to schedule background tasks such as Plagiarism checks for Assignments (Similink) and the mail for assignment's due dates.  &lt;br /&gt;
&lt;br /&gt;
Based on our task prompt we understood that the create method of the assignment controller needs to be changed alongside the testing needs to be improved for sidekiq-related worker files. Also, the code should be commented more thoroughly and variable names changed to better reflect the context they are used for. &lt;br /&gt;
&lt;br /&gt;
===Prior Work===&lt;br /&gt;
&lt;br /&gt;
=== History: Previous projects ===&lt;br /&gt;
&lt;br /&gt;
 * E2253 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2253.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
 * E2144 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2021_-_E2144._Refactor_delayed_mailer_and_scheduled_task]&lt;br /&gt;
 * E2273 [https://expertiza.csc.ncsu.edu/index.php/CSC/ECE_517_Fall_2022_-_E2273.Refactor_delayed_mailer.rb_and_scheduled_task.rb]&lt;br /&gt;
&lt;br /&gt;
The latest Pull Request was not merged into the repository due to some failing tests and missing comments. &amp;lt;br&amp;gt;&lt;br /&gt;
Tests were failing in the following files-&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;spec/controllers/assignments_controller_spec.rb&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
We try to address those failing tests and add block comments before function definition wherever needed. &amp;lt;br&amp;gt;&lt;br /&gt;
Additional testing of some related files is also in the scope of the project.&lt;br /&gt;
&lt;br /&gt;
=== Our Changes ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Upon review of previous PRs, we found that the work was thorough, albeit a few test cases were failing, and comments and methods could be refactored better. Based on the prompts we got, we focussed on refactoring the create method of assignments controller, and assignments form, along with the refactoring of sidekiq-related files.&lt;br /&gt;
  &lt;br /&gt;
Below is the summary of all the changes as part of this PR.&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Refactored the &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method into multiple methods&lt;br /&gt;
| The current &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; method is long and have multiple complex references and if statements. Created separate helpers to simplify complex DB context &lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Used early return in case of errors&lt;br /&gt;
|We refactored the code such that the errors like the assignment already being present or the directory already being present were caught early in the code. It leads to cleaner code as well.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/3c00648b7228eb0daf8a9afd30f8f3abfb44c2c4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Renamed variable names&lt;br /&gt;
|Some of the current variable names were ambiguous as to what they meant, &amp;lt;code&amp;gt;(cur_questionnaire, cur_due, etc.)&amp;lt;/code&amp;gt;. Renamed those names to be less ambiguous and state their function.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/4c2f0e04e7e3ab10443af26d2868758b5c696b55 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Added comments to other helper methods&lt;br /&gt;
|Some functions had no comments which were needed.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b72febb7f2370d6ccb0c99939500f6d36178bf00 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/mailers/mail_worker.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Removed inline comments and added block comments to the function perform&lt;br /&gt;
|Block comments before the function allows better readability and looks clean&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Moved the line to find the participants of a course inside the conditional block&lt;br /&gt;
|Earlier the list of participants of a course were found even when the &amp;lt;code&amp;gt;deadline_type&amp;lt;/code&amp;gt; was  &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt;. We do find the list of emails when it is not &amp;lt;code&amp;gt;'drop_outstanding_reviews’&amp;lt;/code&amp;gt; and send emails to them.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Combined the multiple &amp;lt;code&amp;gt;attr_accessor&amp;lt;/code&amp;gt;lines into a single line&lt;br /&gt;
|Better readability and shorter function code.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|@mail object is not used as it is not reused anywhere else&lt;br /&gt;
|Any temporary variable that is used once should be avoided as it takes up valuable resources.&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/b56ecca4db6e1784a3f92b4fa9619992c1d4dcb2 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
| Replaced ‘mailers’ with ‘jobs’ in &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; test&lt;br /&gt;
| Test was failing due to checking the wrong Sidekiq queue, currently &amp;lt;code&amp;gt;add_to_delayed_queue&amp;lt;/code&amp;gt; adds to job queue NOT mailers queue&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/95dcdaaa36b837df3d580f3352b8504535cc7c2e Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;app/models/assignment_form.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added block comments to methods and removed inline comments&lt;br /&gt;
|Better readability and looks clean&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Created &amp;lt;code&amp;gt;default_assignment_questionaire&amp;lt;/code&amp;gt; to handle creation of a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; that was originally in assignment questionnaire&lt;br /&gt;
|&amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; originally not only searched for an &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt; but created one if one matching type did not exist. Now the second functionality (creating a default &amp;lt;code&amp;gt;assignment_questionnaire&amp;lt;/code&amp;gt;) is its own method.&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/b784e829920059cbff412ad7768833e95469ff2b Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|In line 58 of original code replaced &amp;lt;code&amp;gt;[][]&amp;lt;/code&amp;gt; method of searching with &amp;lt;code&amp;gt;.dig&amp;lt;/code&amp;gt;&lt;br /&gt;
|This particular line could throw errors and .dig is a safer way to search a table without the risk of getting nil errors&lt;br /&gt;
|[https://github.com/expertiza/expertiza/pull/2556/commits/975312c88bb65861b1b6f2b268dc8d80c15aa501 Commit]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Changes to &amp;lt;code&amp;gt;spec/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width: 100%;&lt;br /&gt;
! &amp;amp;nbsp;#&amp;amp;nbsp; !! Change !! Rationale !! Commit Link&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;perform&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/8d78d40ea4e4035f95522e025fd08e220b8b9ce4 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;find_participant_emails&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/190ca781681021f995a8a034a34bb8cede1733e3 Commit]&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Added test case for method &amp;lt;code&amp;gt;email_reminder&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;mail_worker.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
|This test case was not implemented in the earlier Pull Request&lt;br /&gt;
|[https://github.com/tusharkini/expertiza/commit/53b8cf281215aeeec857886deaa2fae7998eff47 Commit]&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Test Coverage for some related files===&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/models/assignment_form_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
After making the changes to  &amp;lt;code&amp;gt;assignment_form.rb &amp;lt;/code&amp;gt; and  &amp;lt;code&amp;gt;assignment_form_spec.rb &amp;lt;/code&amp;gt; we ran the rspec tests with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/models/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_form_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;spec/workers/sidekiq_mail_worker_spec.rb&amp;lt;/code&amp;gt;  ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/workers/sidekiq_mailer_worker_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:mailer_spec.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
====  &amp;lt;code&amp;gt;spec/controllers/auth_controller_spec.rb&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Automated testing of  &amp;lt;code&amp;gt;assignments_controller_spec.rb &amp;lt;/code&amp;gt; with the command  &amp;lt;code&amp;gt;bundle exec rspec spec/controllers/assignment_form_spec.rb &amp;lt;/code&amp;gt;&lt;br /&gt;
[[File:Assignment_controller_test.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Commented out Tests so that the Build passed  ====&lt;br /&gt;
These are some tests that were failing and causing the build to fail. These tests that are commented out are completely un related to our project and fall way outside of our scope to go and resolve it.&amp;lt;br&amp;gt;&lt;br /&gt;
The files are-&amp;lt;br&amp;gt;&lt;br /&gt;
* ./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/course_participant_spec.rb&lt;br /&gt;
*./spec/models/assignment_participant_spec.rb&lt;br /&gt;
*./spec/models/due_date_spec.rb&lt;br /&gt;
&lt;br /&gt;
== Testing / Test Plan ==&lt;br /&gt;
The enhancement is tested manually and through rspec tests. &lt;br /&gt;
&lt;br /&gt;
VCL : http://152.7.178.223:8080/&lt;br /&gt;
&lt;br /&gt;
Login: instructor_Lien&lt;br /&gt;
&lt;br /&gt;
Password: password&lt;br /&gt;
&lt;br /&gt;
To Test via UI: &lt;br /&gt;
&lt;br /&gt;
1) Login to VCL with the above credentials&lt;br /&gt;
&lt;br /&gt;
2) Click on Manage tab &lt;br /&gt;
&lt;br /&gt;
3) Click on Assignments&lt;br /&gt;
&lt;br /&gt;
4) click on + to add a new assignment&lt;br /&gt;
&lt;br /&gt;
5) Create an assignment with a non-zero delay(this feature is to send a reminder email to participants of the course) in SimiCheck(this is the Plagiarism Checker that is being used) and Similarity Threshold to a non-zero. &lt;br /&gt;
&lt;br /&gt;
6) Go to the due date and add a due date for any day after the current date and timestamp. Just be sure that you have atleast 'delay'(set above while creating the assignment) number of hours left for the deadline. Or else the jobs would not be scheduled properly.&lt;br /&gt;
&lt;br /&gt;
7) Create the assignment&lt;br /&gt;
&lt;br /&gt;
8) Go to the Assignment page and add participants (ex. 'Paul' &amp;amp; 'Dan' to name a few. You can query the database and find more Students in the test database) to the assignment.&lt;br /&gt;
&lt;br /&gt;
9) Check the sidekiq dashboard [http://152.7.178.223:8080/sidekiq] page for queued jobs. Check the time left for the MailWorker that would be sending out the mails. &lt;br /&gt;
&lt;br /&gt;
10) It would be under the scheduled tab and would have 'delay' number of hours left less that the actual time left for the deadline. This indicated that the Mailer jobs is queued in a perfect way to send out reminder emails.&lt;br /&gt;
== Edge Cases ==&lt;br /&gt;
&lt;br /&gt;
Error shown in the dashboard:&lt;br /&gt;
&lt;br /&gt;
[[File: Functional_test_error.jpg|1000px]]&amp;lt;br&amp;gt;&lt;br /&gt;
1) Note: In previous refactoring changes it was noted that this error is to be expected and will not affect the real Expertiza. Error is due to Simicheck Plagiarism Checker not having access to certain features in the PR build. This is currently out of the scope of the project and is yet to be implemented in totality. Also the Scheduled MailWorker that sends the email out to user would fail because of lack of SMTP authentication in the test database and environment. It is present in the production environment to which we dont have access.&lt;br /&gt;
&lt;br /&gt;
2) If setting up the environment yourself, the users table in expertiza_development DB would need to be updated and a Preferred Time needed to be added in already created users, for assignments to be saved.&lt;/div&gt;</summary>
		<author><name>Tkini</name></author>
	</entry>
</feed>