<?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=Abommag</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=Abommag"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Abommag"/>
	<updated>2026-09-08T06:51:26Z</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_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145619</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145619"/>
		<updated>2022-05-02T02:50:17Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* UI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Flowchart==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UML Diagrams==&lt;br /&gt;
&lt;br /&gt;
==='''Reviewers use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Reviewer_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==='''Author's use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Author_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
===Code Implementation===&lt;br /&gt;
&lt;br /&gt;
Expertiza code base already contains a module 'MailerHelper' which makes use of ActionMailer and contains methods to send emails to different users.&lt;br /&gt;
email_author_reviewers(subject, body, email) will be added which can be used in both the workflows to send an Email.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
From the Reviewer's perspective, the following files will be updated and a new view will be created. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/response/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/response_controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/response/author.html.erb :''' This is the new UI page. A mock up for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From Author's perspective, the following files will be updated and a new partial will be created to render the new view. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/student_task/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/student_task controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/student_task/email_reviewers.html.erb :''' This is the new UI page. A mockup for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===UI===&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Assignment_page.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:reviewer_email.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Author_SS.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:author_email.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Implememtation==&lt;br /&gt;
&lt;br /&gt;
The following are the screenshots of the changes that we made in the codebase. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Send Email Method in MailerHelper===&lt;br /&gt;
We created a new method called send_mail_to_author_reviewers(subject, body, email), which accepts 3 parameters; subject, body and email. We used the same method for both sending emails to authors and reviewers.&lt;br /&gt;
&lt;br /&gt;
[[File:Email_method.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Reviewer to Author===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the author to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Email_the_author_link.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the author view, we created a new view called author.html.erb and created a form in that file, which asks the user to enter the subject and body. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
We created a method called send_email in the response_controller which handles the functionality for sending an email. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we pass the subject, body, and email from the view to the controller and send them to a method called send_mail_to_author_reviewers which is a part of MailerHelper. This method is responsible for sending emails to the author. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_author.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Author to Reviewers===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the reviewer to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_to_reviewers.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the reviewer view, we created a new view called email_reviewers.html.erb where we created a form that asks the user to enter the subject and body of the email. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
To send an email to all the reviewers, we created a method called send_email in the student_task_controller. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we go ahead and pass the parameters; subject, body, and reviewer.email to the send_mail_to_author_reviewers method from MailerHelper. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_reviewer.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
===RSPEC Testing===&lt;br /&gt;
&lt;br /&gt;
We tested the send_email method used in response_controller.rb and student_task_controller.rb which we have added to achieve the functionality of sending email to reviewers and authors. We have considered four scenarios which can occur while an email has to be sent, namely, user might not give the subject but the body, subject present but no body, both subject and body are present as desired in which case the email is sent on send email button click and the user is redirected to the student task list page and lastly, if there is no subject or body of the email is given, the user is flashed a message and is kept on the same page to fill in the desired fields. Below are the different test scenarios described above:&lt;br /&gt;
&lt;br /&gt;
'''Test 1:''' &lt;br /&gt;
:: [[File:Test1.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 2:''' &lt;br /&gt;
:: [[File:Test2.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 3:'''&lt;br /&gt;
:: [[File:Test3.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 4:'''&lt;br /&gt;
:: [[File:Test4.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test Result:''' We ran the test file using the command '''bundle exec rspec spec/controllers/response_controller_spec.rb''' and below is the test result.&lt;br /&gt;
:: [[File:Test result.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the project for which they want to send email to the reviewers, in the student task view page then click on the right corner of the page where we have the link &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page which will ask then for subject of email and text for the body of email.&lt;br /&gt;
 4. Type the email subject, message and click on send.&lt;br /&gt;
 5. Author can log in to the email to check if the message is received from receivers. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Next to every review that the reviewer is doing, will be a link on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer will be redirected to a page with text box for subject and message. &lt;br /&gt;
 4. Type the email subject, message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
==Future Scope==&lt;br /&gt;
&lt;br /&gt;
1. Currently, only a subject and a text message are provided to send an Email, in future the above functionality can be extended to include attachments in the Email. For example, Reviewer can send an image/screenshot for a failure they have come across to the Author.&lt;br /&gt;
&lt;br /&gt;
2. New functionality to send messages within expertiza&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Author_email.jpeg&amp;diff=145618</id>
		<title>File:Author email.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Author_email.jpeg&amp;diff=145618"/>
		<updated>2022-05-02T02:48:49Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Reviewer_email.jpeg&amp;diff=145617</id>
		<title>File:Reviewer email.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Reviewer_email.jpeg&amp;diff=145617"/>
		<updated>2022-05-02T02:48:34Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145616</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145616"/>
		<updated>2022-05-02T02:37:51Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* Manual Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Flowchart==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UML Diagrams==&lt;br /&gt;
&lt;br /&gt;
==='''Reviewers use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Reviewer_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==='''Author's use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Author_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
===Code Implementation===&lt;br /&gt;
&lt;br /&gt;
Expertiza code base already contains a module 'MailerHelper' which makes use of ActionMailer and contains methods to send emails to different users.&lt;br /&gt;
email_author_reviewers(subject, body, email) will be added which can be used in both the workflows to send an Email.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
From the Reviewer's perspective, the following files will be updated and a new view will be created. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/response/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/response_controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/response/author.html.erb :''' This is the new UI page. A mock up for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From Author's perspective, the following files will be updated and a new partial will be created to render the new view. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/student_task/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/student_task controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/student_task/email_reviewers.html.erb :''' This is the new UI page. A mockup for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===UI===&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Assignment_page.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Message-to-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Author_SS.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Msg-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Implememtation==&lt;br /&gt;
&lt;br /&gt;
The following are the screenshots of the changes that we made in the codebase. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Send Email Method in MailerHelper===&lt;br /&gt;
We created a new method called send_mail_to_author_reviewers(subject, body, email), which accepts 3 parameters; subject, body and email. We used the same method for both sending emails to authors and reviewers.&lt;br /&gt;
&lt;br /&gt;
[[File:Email_method.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Reviewer to Author===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the author to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Email_the_author_link.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the author view, we created a new view called author.html.erb and created a form in that file, which asks the user to enter the subject and body. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
We created a method called send_email in the response_controller which handles the functionality for sending an email. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we pass the subject, body, and email from the view to the controller and send them to a method called send_mail_to_author_reviewers which is a part of MailerHelper. This method is responsible for sending emails to the author. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_author.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Author to Reviewers===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the reviewer to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_to_reviewers.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the reviewer view, we created a new view called email_reviewers.html.erb where we created a form that asks the user to enter the subject and body of the email. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
To send an email to all the reviewers, we created a method called send_email in the student_task_controller. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we go ahead and pass the parameters; subject, body, and reviewer.email to the send_mail_to_author_reviewers method from MailerHelper. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_reviewer.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
===RSPEC Testing===&lt;br /&gt;
&lt;br /&gt;
We tested the send_email method used in response_controller.rb and student_task_controller.rb which we have added to achieve the functionality of sending email to reviewers and authors. We have considered four scenarios which can occur while an email has to be sent, namely, user might not give the subject but the body, subject present but no body, both subject and body are present as desired in which case the email is sent on send email button click and the user is redirected to the student task list page and lastly, if there is no subject or body of the email is given, the user is flashed a message and is kept on the same page to fill in the desired fields. Below are the different test scenarios described above:&lt;br /&gt;
&lt;br /&gt;
'''Test 1:''' &lt;br /&gt;
:: [[File:Test1.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 2:''' &lt;br /&gt;
:: [[File:Test2.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 3:'''&lt;br /&gt;
:: [[File:Test3.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 4:'''&lt;br /&gt;
:: [[File:Test4.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test Result:''' We ran the test file using the command '''bundle exec rspec spec/controllers/response_controller_spec.rb''' and below is the test result.&lt;br /&gt;
:: [[File:Test result.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the project for which they want to send email to the reviewers, in the student task view page then click on the right corner of the page where we have the link &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page which will ask then for subject of email and text for the body of email.&lt;br /&gt;
 4. Type the email subject, message and click on send.&lt;br /&gt;
 5. Author can log in to the email to check if the message is received from receivers. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Next to every review that the reviewer is doing, will be a link on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer will be redirected to a page with text box for subject and message. &lt;br /&gt;
 4. Type the email subject, message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
==Future Scope==&lt;br /&gt;
&lt;br /&gt;
1. Currently, only a subject and a text message are provided to send an Email, in future the above functionality can be extended to include attachments in the Email. For example, Reviewer can send an image/screenshot for a failure they have come across to the Author.&lt;br /&gt;
&lt;br /&gt;
2. New functionality to send messages within expertiza&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145612</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145612"/>
		<updated>2022-05-01T23:41:58Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Flowchart==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UML Diagrams==&lt;br /&gt;
&lt;br /&gt;
==='''Reviewers use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Reviewer_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==='''Author's use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Author_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
===Code Implementation===&lt;br /&gt;
&lt;br /&gt;
Expertiza code base already contains a module 'MailerHelper' which makes use of ActionMailer and contains methods to send emails to different users.&lt;br /&gt;
email_author_reviewers(subject, body, email) will be added which can be used in both the workflows to send an Email.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
From the Reviewer's perspective, the following files will be updated and a new view will be created. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/response/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/response_controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/response/author.html.erb :''' This is the new UI page. A mock up for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From Author's perspective, the following files will be updated and a new partial will be created to render the new view. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/student_task/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/student_task controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/student_task/email_reviewers.html.erb :''' This is the new UI page. A mockup for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===UI===&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Assignment_page.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Message-to-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Author_SS.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Msg-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Implememtation==&lt;br /&gt;
&lt;br /&gt;
The following are the screenshots of the changes that we made in the codebase. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Send Email Method in MailerHelper===&lt;br /&gt;
We created a new method called send_mail_to_author_reviewers(subject, body, email), which accepts 3 parameters; subject, body and email. We used the same method for both sending emails to authors and reviewers.&lt;br /&gt;
&lt;br /&gt;
[[File:Email_method.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Reviewer to Author===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the author to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Email_the_author_link.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the author view, we created a new view called author.html.erb and created a form in that file, which asks the user to enter the subject and body. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
We created a method called send_email in the response_controller which handles the functionality for sending an email. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we pass the subject, body, and email from the view to the controller and send them to a method called send_mail_to_author_reviewers which is a part of MailerHelper. This method is responsible for sending emails to the author. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_author.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Author to Reviewers===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the reviewer to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_to_reviewers.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the reviewer view, we created a new view called email_reviewers.html.erb where we created a form that asks the user to enter the subject and body of the email. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
To send an email to all the reviewers, we created a method called send_email in the student_task_controller. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we go ahead and pass the parameters; subject, body, and reviewer.email to the send_mail_to_author_reviewers method from MailerHelper. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_reviewer.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
===RSPEC Testing===&lt;br /&gt;
&lt;br /&gt;
We tested the send_email method used in response_controller.rb and student_task_controller.rb which we have added to achieve the functionality of sending email to reviewers and authors. We have considered four scenarios which can occur while an email has to be sent, namely, user might not give the subject but the body, subject present but no body, both subject and body are present as desired in which case the email is sent on send email button click and the user is redirected to the student task list page and lastly, if there is no subject or body of the email is given, the user is flashed a message and is kept on the same page to fill in the desired fields. Below are the different test scenarios described above:&lt;br /&gt;
&lt;br /&gt;
'''Test 1:''' &lt;br /&gt;
:: [[File:Test1.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 2:''' &lt;br /&gt;
:: [[File:Test2.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 3:'''&lt;br /&gt;
:: [[File:Test3.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 4:'''&lt;br /&gt;
:: [[File:Test4.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test Result:''' We ran the test file using the command '''bundle exec rspec spec/controllers/response_controller_spec.rb''' and below is the test result.&lt;br /&gt;
:: [[File:Test result.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send.&lt;br /&gt;
 5. Log in to the email to check if the message is received. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
==Future Scope==&lt;br /&gt;
&lt;br /&gt;
1. Currently, only a subject and a text message are provided to send an Email, in future the above functionality can be extended to include attachments in the Email. For example, Reviewer can send an image/screenshot for a failure they have come across to the Author.&lt;br /&gt;
&lt;br /&gt;
2. New functionality to send messages within expertiza&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145611</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145611"/>
		<updated>2022-05-01T23:19:07Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* RSPEC Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Flowchart==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UML Diagrams==&lt;br /&gt;
&lt;br /&gt;
==='''Reviewers use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Reviewer_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==='''Author's use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Author_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
===Code Implementation===&lt;br /&gt;
&lt;br /&gt;
Expertiza code base already contains a module 'MailerHelper' which makes use of ActionMailer and contains methods to send emails to different users.&lt;br /&gt;
email_author_reviewers(subject, body, email) will be added which can be used in both the workflows to send an Email.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
From the Reviewer's perspective, the following files will be updated and a new view will be created. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/response/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/response_controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/response/author.html.erb :''' This is the new UI page. A mock up for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From Author's perspective, the following files will be updated and a new partial will be created to render the new view. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/student_task/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/student_task controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/student_task/email_reviewers.html.erb :''' This is the new UI page. A mockup for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===UI===&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Assignment_page.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Message-to-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Author_SS.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Msg-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Implememtation==&lt;br /&gt;
&lt;br /&gt;
The following are the screenshots of the changes that we made in the codebase. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Send Email Method in MailerHelper===&lt;br /&gt;
We created a new method called send_mail_to_author_reviewers(subject, body, email), which accepts 3 parameters; subject, body and email. We used the same method for both sending emails to authors and reviewers.&lt;br /&gt;
&lt;br /&gt;
[[File:Email_method.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Reviewer to Author===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the author to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Email_the_author_link.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the author view, we created a new view called author.html.erb and created a form in that file, which asks the user to enter the subject and body. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
We created a method called send_email in the response_controller which handles the functionality for sending an email. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we pass the subject, body, and email from the view to the controller and send them to a method called send_mail_to_author_reviewers which is a part of MailerHelper. This method is responsible for sending emails to the author. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_author.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Author to Reviewers===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the reviewer to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_to_reviewers.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the reviewer view, we created a new view called email_reviewers.html.erb where we created a form that asks the user to enter the subject and body of the email. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
To send an email to all the reviewers, we created a method called send_email in the student_task_controller. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we go ahead and pass the parameters; subject, body, and reviewer.email to the send_mail_to_author_reviewers method from MailerHelper. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_reviewer.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
===RSPEC Testing===&lt;br /&gt;
&lt;br /&gt;
We tested the send_email method used in response_controller.rb and student_task_controller.rb which we have added to achieve the functionality of sending email to reviewers and authors. We have considered four scenarios which can occur while an email has to be sent, namely, user might not give the subject but the body, subject present but no body, both subject and body are present as desired in which case the email is sent on send email button click and the user is redirected to the student task list page and lastly, if there is no subject or body of the email is given, the user is flashed a message and is kept on the same page to fill in the desired fields. Below are the different test scenarios described above:&lt;br /&gt;
&lt;br /&gt;
'''Test 1:''' &lt;br /&gt;
:: [[File:Test1.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 2:''' &lt;br /&gt;
:: [[File:Test2.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 3:'''&lt;br /&gt;
:: [[File:Test3.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 4:'''&lt;br /&gt;
:: [[File:Test4.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test Result:''' We ran the test file using the command '''bundle exec rspec spec/controllers/response_controller_spec.rb''' and below is the test result.&lt;br /&gt;
:: [[File:Test result.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send.&lt;br /&gt;
 5. Log in to the email to check if the message is received. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
We are planning to cover the following test cases: &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;,&lt;br /&gt;
    the author must be redirected to email_reviewers_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the reviewers of the authors' work.&lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;,&lt;br /&gt;
    the reviewer must be redirected to email_authors_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the authors of the reviewed work.&lt;br /&gt;
&lt;br /&gt;
We will also be checking the below two edge cases:&lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
 1. Once the email is sent, the author should be redirected to the assignment page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
 2. Once the email is sent, the author should be redirected to the &amp;quot;others work&amp;quot; page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
&lt;br /&gt;
==Future Scope==&lt;br /&gt;
&lt;br /&gt;
1. Currently, only a subject and a text message are provided to send an Email, in future the above functionality can be extended to include attachments in the Email. For example, Reviewer can send an image/screenshot for a failure they have come across to the Author.&lt;br /&gt;
&lt;br /&gt;
2. New functionality to send messages within expertiza&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Test3.jpeg&amp;diff=145610</id>
		<title>File:Test3.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Test3.jpeg&amp;diff=145610"/>
		<updated>2022-05-01T22:37:58Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145609</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=145609"/>
		<updated>2022-05-01T22:33:21Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* RSPEC Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Flowchart==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UML Diagrams==&lt;br /&gt;
&lt;br /&gt;
==='''Reviewers use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Reviewer_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==='''Author's use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Author_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
===Code Implementation===&lt;br /&gt;
&lt;br /&gt;
Expertiza code base already contains a module 'MailerHelper' which makes use of ActionMailer and contains methods to send emails to different users.&lt;br /&gt;
email_author_reviewers(subject, body, email) will be added which can be used in both the workflows to send an Email.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
From the Reviewer's perspective, the following files will be updated and a new view will be created. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/response/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/response_controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/response/author.html.erb :''' This is the new UI page. A mock up for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From Author's perspective, the following files will be updated and a new partial will be created to render the new view. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/student_task/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/student_task controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/student_task/email_reviewers.html.erb :''' This is the new UI page. A mockup for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===UI===&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Assignment_page.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Message-to-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Author_SS.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Msg-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Implememtation==&lt;br /&gt;
&lt;br /&gt;
The following are the screenshots of the changes that we made in the codebase. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Send Email Method in MailerHelper===&lt;br /&gt;
We created a new method called send_mail_to_author_reviewers(subject, body, email), which accepts 3 parameters; subject, body and email. We used the same method for both sending emails to authors and reviewers.&lt;br /&gt;
&lt;br /&gt;
[[File:Email_method.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Reviewer to Author===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the author to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Email_the_author_link.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the author view, we created a new view called author.html.erb and created a form in that file, which asks the user to enter the subject and body. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
We created a method called send_email in the response_controller which handles the functionality for sending an email. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we pass the subject, body, and email from the view to the controller and send them to a method called send_mail_to_author_reviewers which is a part of MailerHelper. This method is responsible for sending emails to the author. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_author.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Email from Author to Reviewers===&lt;br /&gt;
====View====&lt;br /&gt;
We modified the view to add a link that redirects the reviewer to the form. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_to_reviewers.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To create the reviewer view, we created a new view called email_reviewers.html.erb where we created a form that asks the user to enter the subject and body of the email. &lt;br /&gt;
[[File:Author_view.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Controller====&lt;br /&gt;
To send an email to all the reviewers, we created a method called send_email in the student_task_controller. The method also contains validations that throw an error if the user is trying to submit the form without filling out the subject or body. If there are no validation errors, we go ahead and pass the parameters; subject, body, and reviewer.email to the send_mail_to_author_reviewers method from MailerHelper. &lt;br /&gt;
&lt;br /&gt;
[[File:Send_email_reviewer.png|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
===RSPEC Testing===&lt;br /&gt;
&lt;br /&gt;
We tested the send_email method in response_controller.rb and student_task_controller.rb which we have added to achieve the functionality of sending &lt;br /&gt;
email to reviewers and authors.&lt;br /&gt;
&lt;br /&gt;
'''Test 1:'''&lt;br /&gt;
:: [[File:Test1.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 2:'''&lt;br /&gt;
:: [[File:Test2.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 3:'''&lt;br /&gt;
:: [[File:Test3.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test 4:'''&lt;br /&gt;
:: [[File:Test4.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Test Result:'''&lt;br /&gt;
:: [[File:Testresult.jpeg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send.&lt;br /&gt;
 5. Log in to the email to check if the message is received. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
We are planning to cover the following test cases: &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;,&lt;br /&gt;
    the author must be redirected to email_reviewers_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the reviewers of the authors' work.&lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;,&lt;br /&gt;
    the reviewer must be redirected to email_authors_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the authors of the reviewed work.&lt;br /&gt;
&lt;br /&gt;
We will also be checking the below two edge cases:&lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
 1. Once the email is sent, the author should be redirected to the assignment page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
 2. Once the email is sent, the author should be redirected to the &amp;quot;others work&amp;quot; page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
&lt;br /&gt;
==Future Scope==&lt;br /&gt;
&lt;br /&gt;
1. Currently, only a subject and a text message are provided to send an Email, in future the above functionality can be extended to include attachments in the Email. For example, Reviewer can send an image/screenshot for a failure they have come across to the Author.&lt;br /&gt;
&lt;br /&gt;
2. New functionality to send messages within expertiza&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Test_result.jpeg&amp;diff=145608</id>
		<title>File:Test result.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Test_result.jpeg&amp;diff=145608"/>
		<updated>2022-05-01T22:16:17Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Test4.jpeg&amp;diff=145607</id>
		<title>File:Test4.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Test4.jpeg&amp;diff=145607"/>
		<updated>2022-05-01T22:16:02Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Test2.jpeg&amp;diff=145606</id>
		<title>File:Test2.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Test2.jpeg&amp;diff=145606"/>
		<updated>2022-05-01T22:15:33Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Test1.jpeg&amp;diff=145605</id>
		<title>File:Test1.jpeg</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Test1.jpeg&amp;diff=145605"/>
		<updated>2022-05-01T22:12:51Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144711</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144711"/>
		<updated>2022-04-11T21:38:46Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Flowchart==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==UML Diagrams==&lt;br /&gt;
&lt;br /&gt;
==='''Reviewers use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Reviewer_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==='''Author's use case'''===&lt;br /&gt;
&lt;br /&gt;
:: [[File:Author_usecase.png|300px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
===Code Implementation===&lt;br /&gt;
&lt;br /&gt;
Expertiza code base already contains a module 'MailerHelper' which makes use of ActionMailer and contains methods to send emails to different users.&lt;br /&gt;
'''def send_mail_to_user(user, subject, partial_name, password)''' can be used to send the email to an another from reviewer and&lt;br /&gt;
'''def send_mail_to_assigned_reviewers''' can be used to send emails to all reviewers from an author.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
From the Reviewer's perspective, the following files will be updated and a new partial will be created to render the new view. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/response/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/response_controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/response/email_author.html.erb :''' This is the new UI page. A mock up for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From Author's perspective, the following files will be updated and a new partial will be created to render the new view. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/student_task/list.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/student_task controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/student_task/email_reviewers.html.erb :''' This is the new UI page. A mockup for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===UI===&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Email-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Message-to-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Author_SS.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Msg-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
===RSPEC Testing===&lt;br /&gt;
&lt;br /&gt;
Since this is a new Feature, Rspec test cases will be added for all the new methods introduced in the response_controller.rb and student_task controller.rb.&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send.&lt;br /&gt;
 5. Log in to the email to check if the message is received. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
We are planning to cover the following test cases: &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;,&lt;br /&gt;
    the author must be redirected to email_reviewers_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the reviewers of the authors' work.&lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;,&lt;br /&gt;
    the reviewer must be redirected to email_authors_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the authors of the reviewed work.&lt;br /&gt;
&lt;br /&gt;
We will also be checking the below two edge cases:&lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
 1. Once the email is sent, the author should be redirected to the assignment page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
 2. Once the email is sent, the author should be redirected to the &amp;quot;others work&amp;quot; page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
A design pattern is a general repeatable solution to a commonly occurring problem in software design. It is a description or template for how to solve a problem that can be used in many different situations.&lt;br /&gt;
&lt;br /&gt;
We will be implementing the decorator design pattern in our code. The decorator pattern is used to add/extend existing functionality without modifying the existing code. Our code is also going to follow the open-closed principle.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Author_usecase.png&amp;diff=144710</id>
		<title>File:Author usecase.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Author_usecase.png&amp;diff=144710"/>
		<updated>2022-04-11T21:36:32Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144709</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144709"/>
		<updated>2022-04-11T21:35:09Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* Code Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Flowchart==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
===Code Implementation===&lt;br /&gt;
&lt;br /&gt;
Expertiza code base already contains a module 'MailerHelper' which makes use of ActionMailer and contains methods to send emails to different users.&lt;br /&gt;
'''def send_mail_to_user(user, subject, partial_name, password)''' can be used to send the email to an another from reviewer and&lt;br /&gt;
'''def send_mail_to_assigned_reviewers''' can be used to send emails to all reviewers from an author.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
From the Reviewer's perspective, the following files will be updated and a new partial will be created to render the new view. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/response/view.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/response_controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/response/email_author.html.erb :''' This is the new UI page. A mock up for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From Author's perspective, the following files will be updated and a new partial will be created to render the new view. &lt;br /&gt;
&lt;br /&gt;
1. '''app/views/student_task/list.html.erb :''' link to the new view will be added to this file. &amp;lt;br/&amp;gt;&lt;br /&gt;
2. '''app/controllers/student_task controller.rb :''' implementation of the action method for the send button will be added here. Methods from MailerHelper will be used here. &amp;lt;br/&amp;gt;&lt;br /&gt;
3. '''app/views/student_task/email_reviewers.html.erb :''' This is the new UI page. A mockup for the view is presented in the UI section. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===UI===&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Email-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Message-to-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Author_SS.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Msg-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
===RSPEC Testing===&lt;br /&gt;
&lt;br /&gt;
Since this is a new Feature, Rspec test cases will be added for all the new methods introduced in the response_controller.rb and student_task controller.rb.&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send.&lt;br /&gt;
 5. Log in to the email to check if the message is received. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
We are planning to cover the following test cases: &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;,&lt;br /&gt;
    the author must be redirected to email_reviewers_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the reviewers of the authors' work.&lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;,&lt;br /&gt;
    the reviewer must be redirected to email_authors_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the authors of the reviewed work.&lt;br /&gt;
&lt;br /&gt;
We will also be checking the below two edge cases:&lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
 1. Once the email is sent, the author should be redirected to the assignment page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
 2. Once the email is sent, the author should be redirected to the &amp;quot;others work&amp;quot; page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
A design pattern is a general repeatable solution to a commonly occurring problem in software design. It is a description or template for how to solve a problem that can be used in many different situations.&lt;br /&gt;
&lt;br /&gt;
We will be implementing the decorator design pattern in our code. The decorator pattern is used to add/extend existing functionality without modifying the existing code. Our code is also going to follow the open-closed principle.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Reviewer_usecase.png&amp;diff=144708</id>
		<title>File:Reviewer usecase.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Reviewer_usecase.png&amp;diff=144708"/>
		<updated>2022-04-11T21:32:57Z</updated>

		<summary type="html">&lt;p&gt;Abommag: Abommag uploaded a new version of File:Reviewer usecase.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Reviewer_usecase.png&amp;diff=144707</id>
		<title>File:Reviewer usecase.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Reviewer_usecase.png&amp;diff=144707"/>
		<updated>2022-04-11T21:24:53Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144104</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144104"/>
		<updated>2022-04-05T23:33:14Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Flowchart==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Email-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Message-to-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Email-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Msg-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
===RSPEC Testing===&lt;br /&gt;
&lt;br /&gt;
Since this is a new Feature, Rspec test cases will be added for all the new methods introduced in the MailHelper class method.&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send.&lt;br /&gt;
 5. Log in to the email to check if the message is received. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
We are planning to cover the following test cases: &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;,&lt;br /&gt;
    the author must be redirected to email_reviewers_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the reviewers of the authors' work.&lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;,&lt;br /&gt;
    the reviewer must be redirected to email_authors_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the authors of the reviewed work.&lt;br /&gt;
&lt;br /&gt;
We will also be checking the below two edge cases:&lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
 1. Once the email is sent, the author should be redirected to the assignment page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
 2. Once the email is sent, the author should be redirected to the &amp;quot;others work&amp;quot; page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
A design pattern is a general repeatable solution to a commonly occurring problem in software design. It is a description or template for how to solve a problem that can be used in many different situations.&lt;br /&gt;
&lt;br /&gt;
We will be implementing the decorator design pattern in our code. The decorator pattern is used to add/extend existing functionality without modifying the existing code. Our code is also going to follow the open-closed principle.&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144100</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144100"/>
		<updated>2022-04-05T23:30:26Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Flowchart==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|1000px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Email-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Message-to-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Email-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Msg-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
'''Since this is a new Feature, Rspec test cases will be added for all the new methods introduced in the MailHelper class method.'''&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send.&lt;br /&gt;
 5. Log in to the email to check if the message is received. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
We are planning to cover the following test cases: &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;,&lt;br /&gt;
    the author must be redirected to email_reviewers_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the reviewers of the authors' work.&lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
 1. Upon Clicking on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;,&lt;br /&gt;
    the reviewer must be redirected to email_authors_view. &lt;br /&gt;
 2. Check if the recipients of the email are indeed the authors of the reviewed work.&lt;br /&gt;
&lt;br /&gt;
We will also be checking the below two edge cases:&lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
 1. Once the email is sent, the author should be redirected to the assignment page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
 2. Once the email is sent, the author should be redirected to the &amp;quot;others work&amp;quot; page with the corresponding success&lt;br /&gt;
    or failure message&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
A design pattern is a general repeatable solution to a commonly occurring problem in software design. It is a description or template for how to solve a problem that can be used in many different situations.&lt;br /&gt;
&lt;br /&gt;
We will be implementing the decorator design pattern in our code. The decorator pattern is used to add/extend existing functionality without modifying the existing code. Our code is also going to follow the open-closed principle.&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144025</id>
		<title>CSC/ECE 517 Spring 2022 - E2246: Email your authors/reviewers, with complete tests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2246:_Email_your_authors/reviewers,_with_complete_tests&amp;diff=144025"/>
		<updated>2022-04-05T00:07:18Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background ===&lt;br /&gt;
Expertiza is a web application where students can submit and peer-review learning objects (articles, codes, websites, etc). Instructors add and grade the assignments submitted by students to Expertiza. Students can be assigned in teams based on their selection of the topics. It has functionalities such as peer reviews in which students can provide feedback on other's work which helps peer in better developing the project. It is supported by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
This project adds a new feature which will enable a reviewer to send an Email to authors from inside Expertiza or for the author to email all those reviewing them. Often when reviewing another team’s submissions, a reviewer might notice that their deployment link is broken or there is some other issue. Currently, there is no way to email the authors. This features is proposed to solve this issue.&lt;br /&gt;
&lt;br /&gt;
==Scope of the Feature==&lt;br /&gt;
&lt;br /&gt;
- The feature allows authors to send a common Email to all the reviewers to report any issues or updates to their project to be reviewed. &amp;lt;br/&amp;gt;&lt;br /&gt;
- It can allow a reviewer to send an email to a particular author if the reviewer wants to convey any issues found with that particular project. &amp;lt;br/&amp;gt;&lt;br /&gt;
- Reviewers will be anonymous to authors. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Proposed Changes==&lt;br /&gt;
&lt;br /&gt;
As depicted below, Authors will be given a link on their main Assignment page “Send Email to Reviewers” which will take them to a new page where they are given a text box for typing and sending an email to all their reviewers. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Email-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Message-to-R.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Reviewers will be given a similar text box link on their “Other’s Work” page next to each review that they are doing. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Email-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Msg-to-A.png|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Flowchart===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Author's View''' : The flow for authors to email reviewers regarding the work they have been reviewed for:&lt;br /&gt;
&lt;br /&gt;
[[File:Author's view flowchart.jpg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Reviewer's View''' : The flow for reviewers to email authors whose work they have reviewed:&lt;br /&gt;
&lt;br /&gt;
[[File:Reviewers_View_Flowchart.jpg|800px]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
&lt;br /&gt;
Since this is a new Feature, Rspec test cases will be added for all the new methods introduced in the MailHelper class method.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Manual Testing===&lt;br /&gt;
&lt;br /&gt;
For testing purposes, we are using the 'expertiza.debugging@gmail.com' as both author and reviewer. &lt;br /&gt;
There are two views that need to be tested manually. &lt;br /&gt;
&lt;br /&gt;
1. Author View:&lt;br /&gt;
&lt;br /&gt;
The author must follow the following steps:&lt;br /&gt;
 1. Go to the Assignments page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to reviewers&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the author must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send.&lt;br /&gt;
 5. Log in to the email to check if the message is received. &lt;br /&gt;
&lt;br /&gt;
2. Reviewer View:&lt;br /&gt;
&lt;br /&gt;
The reviewer must follow the following steps:&lt;br /&gt;
 1. Go to the other's work page.&lt;br /&gt;
 2. Click on the link which is placed on the right corner of the page called &amp;quot;send email to author&amp;quot;.&lt;br /&gt;
 3. On clicking the above link, the reviewer must be redirected to a page with an email text box. &lt;br /&gt;
 4. Type the email message and click on send. &lt;br /&gt;
 5. Log in to the email to check if the message is received.&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
&lt;br /&gt;
A design pattern is a general repeatable solution to a commonly occurring problem in software design. It is a description or template for how to solve a problem that can be used in many different situations.&lt;br /&gt;
&lt;br /&gt;
We will be implementing the decorator design pattern in our code. The decorator pattern is used to add/extend existing functionality without modifying the existing code. Our code is also going to follow the open-closed principle.&lt;br /&gt;
&lt;br /&gt;
== Team Members ==&lt;br /&gt;
&lt;br /&gt;
Ashritha Bommagani  (abommag@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Abhishek Arvindkumar Upadhyay (aaupadhy@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Harini Bharata (hbharat@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Sri Pallavi Damuluri (sdamulu@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143804</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143804"/>
		<updated>2022-03-28T04:55:55Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
'''submitted_content_controller''' had some problems that violate essential Rails design principles which needed to be rectified.&lt;br /&gt;
&lt;br /&gt;
The following issues were addressed as a part of refactoring this controller:&lt;br /&gt;
&lt;br /&gt;
'''List of Issues in submitted_content_controller.rb'''&lt;br /&gt;
&lt;br /&gt;
* Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
* Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
* Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
* submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
* Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission, according to the ruby method naming conventions, as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity in order to actually proceed with submitting a file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
:: Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Would it be helpful and clean to separate this controller into a submitted_files_controller and a submitted_hyperlinks_controller?&lt;br /&gt;
* The refactor is not necessary or relatively minor because there are only two methods(remove_hyperlink and submit_hyperlink) in submitted_content_controller that are mainly on hyperlinks. Moreover, submission via hyperlink is as simple as it is now, and it doesn't need a controller of its own. It will just overcomplicate things. It is better to keep all methods related to submission under one controller.&lt;br /&gt;
&lt;br /&gt;
===Testing Plan===&lt;br /&gt;
&lt;br /&gt;
This file (submitted_content_controller.rb) has very little coverage, so we have done the manual verification for making sure all the edge cases are taken care of after the refactoring is done. We have also run the following briefed rspec command to verify that our changes do not break any core functions. &lt;br /&gt;
&lt;br /&gt;
Rspec Testing:&lt;br /&gt;
&lt;br /&gt;
1. git clone https://github.com/LeooHsiang/expertiza&lt;br /&gt;
&lt;br /&gt;
2. Change directory to expertiza. Run &amp;quot;bundle install&amp;quot; and rails db:migrate.&lt;br /&gt;
&lt;br /&gt;
3. Start the rails server.&lt;br /&gt;
&lt;br /&gt;
4. Run the following command in a new terminal of the expertiza directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Manual Testing: &lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edge Cases:&lt;br /&gt;
* Return error when the user who is not the assignment's participant trying to do the submission&lt;br /&gt;
* Return 'You or your teammate(s) have already submitted the same hyperlink.' when the same hyperlink already submitted&lt;br /&gt;
* Return error when the URL/hyperlink is invalid&lt;br /&gt;
* Return error when the uploading file is smaller than 5 MB&lt;br /&gt;
* Return error when the uploading file is not pdf or file type is not among specified&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143803</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143803"/>
		<updated>2022-03-28T04:45:07Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* Problem Statement */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
'''submitted_content_controller''' had some problems that violate essential Rails design principles which needed to be rectified.&lt;br /&gt;
&lt;br /&gt;
The following issues were addressed as a part of refactoring this controller:&lt;br /&gt;
&lt;br /&gt;
'''List of Issues in submitted_content_controller.rb'''&lt;br /&gt;
&lt;br /&gt;
* Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
* Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
* Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
* submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
* Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission, according to the ruby method naming conventions, as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity in order to actually proceed with submitting a file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
:: Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Would it be helpful and clean to separate this controller into a submitted_files_controller and a submitted_hyperlinks_controller?&lt;br /&gt;
* The refactor is not necessary or relatively minor because there are only two methods(remove_hyperlink and submit_hyperlink) in submitted_content_controller that are mainly on hyperlinks. Moreover, submission via hyperlink is as simple as it is now, and it doesn't need a controller of its own. It will just overcomplicate things. It is better to keep all methods related to submission under one controller.&lt;br /&gt;
&lt;br /&gt;
===Testing Plan===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Rspec Testing:&lt;br /&gt;
&lt;br /&gt;
1. git clone https://github.com/LeooHsiang/expertiza&lt;br /&gt;
&lt;br /&gt;
2. Change directory to expertiza. Run &amp;quot;bundle install&amp;quot; and rails db:migrate.&lt;br /&gt;
&lt;br /&gt;
3. Start the rails server.&lt;br /&gt;
&lt;br /&gt;
4. Run the following command in a new terminal of the expertiza directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Manual Testing: &lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edge Cases:&lt;br /&gt;
* Return error when the user who is not the assignment's participant trying to do the submission&lt;br /&gt;
* Return 'You or your teammate(s) have already submitted the same hyperlink.' when the same hyperlink already submitted&lt;br /&gt;
* Return error when the URL/hyperlink is invalid&lt;br /&gt;
* Return error when the uploading file is smaller than 5 MB&lt;br /&gt;
* Return error when the uploading file is not pdf or file type is not among specified&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143802</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143802"/>
		<updated>2022-03-28T04:44:45Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* List of Issues in submitted_content_controller.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
'''submitted_content_controller''' had some problems that violate essential Rails design principles which needed to be rectified.&lt;br /&gt;
&lt;br /&gt;
The following issues were addressed as a part of refactoring this controller:&lt;br /&gt;
&lt;br /&gt;
::List of Issues in submitted_content_controller.rb&lt;br /&gt;
&lt;br /&gt;
* Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
* Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
* Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
* submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
* Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission, according to the ruby method naming conventions, as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity in order to actually proceed with submitting a file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
:: Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Would it be helpful and clean to separate this controller into a submitted_files_controller and a submitted_hyperlinks_controller?&lt;br /&gt;
* The refactor is not necessary or relatively minor because there are only two methods(remove_hyperlink and submit_hyperlink) in submitted_content_controller that are mainly on hyperlinks. Moreover, submission via hyperlink is as simple as it is now, and it doesn't need a controller of its own. It will just overcomplicate things. It is better to keep all methods related to submission under one controller.&lt;br /&gt;
&lt;br /&gt;
===Testing Plan===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Rspec Testing:&lt;br /&gt;
&lt;br /&gt;
1. git clone https://github.com/LeooHsiang/expertiza&lt;br /&gt;
&lt;br /&gt;
2. Change directory to expertiza. Run &amp;quot;bundle install&amp;quot; and rails db:migrate.&lt;br /&gt;
&lt;br /&gt;
3. Start the rails server.&lt;br /&gt;
&lt;br /&gt;
4. Run the following command in a new terminal of the expertiza directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Manual Testing: &lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edge Cases:&lt;br /&gt;
* Return error when the user who is not the assignment's participant trying to do the submission&lt;br /&gt;
* Return 'You or your teammate(s) have already submitted the same hyperlink.' when the same hyperlink already submitted&lt;br /&gt;
* Return error when the URL/hyperlink is invalid&lt;br /&gt;
* Return error when the uploading file is smaller than 5 MB&lt;br /&gt;
* Return error when the uploading file is not pdf or file type is not among specified&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143801</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143801"/>
		<updated>2022-03-28T04:43:07Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* Problem Statement */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
'''submitted_content_controller''' had some problems that violate essential Rails design principles which needed to be rectified.&lt;br /&gt;
&lt;br /&gt;
The following issues were addressed as a part of refactoring this controller:&lt;br /&gt;
&lt;br /&gt;
===List of Issues in submitted_content_controller.rb===&lt;br /&gt;
&lt;br /&gt;
* Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
* Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
* Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
* submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
* Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission, according to the ruby method naming conventions, as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity in order to actually proceed with submitting a file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
:: Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Would it be helpful and clean to separate this controller into a submitted_files_controller and a submitted_hyperlinks_controller?&lt;br /&gt;
* The refactor is not necessary or relatively minor because there are only two methods(remove_hyperlink and submit_hyperlink) in submitted_content_controller that are mainly on hyperlinks. Moreover, submission via hyperlink is as simple as it is now, and it doesn't need a controller of its own. It will just overcomplicate things. It is better to keep all methods related to submission under one controller.&lt;br /&gt;
&lt;br /&gt;
===Testing Plan===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Rspec Testing:&lt;br /&gt;
&lt;br /&gt;
1. git clone https://github.com/LeooHsiang/expertiza&lt;br /&gt;
&lt;br /&gt;
2. Change directory to expertiza. Run &amp;quot;bundle install&amp;quot; and rails db:migrate.&lt;br /&gt;
&lt;br /&gt;
3. Start the rails server.&lt;br /&gt;
&lt;br /&gt;
4. Run the following command in a new terminal of the expertiza directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Manual Testing: &lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edge Cases:&lt;br /&gt;
* Return error when the user who is not the assignment's participant trying to do the submission&lt;br /&gt;
* Return 'You or your teammate(s) have already submitted the same hyperlink.' when the same hyperlink already submitted&lt;br /&gt;
* Return error when the URL/hyperlink is invalid&lt;br /&gt;
* Return error when the uploading file is smaller than 5 MB&lt;br /&gt;
* Return error when the uploading file is not pdf or file type is not among specified&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143800</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143800"/>
		<updated>2022-03-28T04:32:04Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* Solutions devised */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
'''submitted_content_controller''' had some problems that violate essential Rails design principles which needed to be rectified.&lt;br /&gt;
&lt;br /&gt;
The following issues were addressed as a part of refactoring this controller:&lt;br /&gt;
&lt;br /&gt;
* Renaming methods to more appropriate and functionality specific names.&lt;br /&gt;
* some methods being too long which needed to be broken down.&lt;br /&gt;
* Remove or change the comment for the methods to be more meaningful and reflective on the actual functionality.&lt;br /&gt;
&lt;br /&gt;
===List of Issues in submitted_content_controller.rb===&lt;br /&gt;
&lt;br /&gt;
* Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
* Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
* Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
* submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
* Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission, according to the ruby method naming conventions, as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity in order to actually proceed with submitting a file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
:: Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Would it be helpful and clean to separate this controller into a submitted_files_controller and a submitted_hyperlinks_controller?&lt;br /&gt;
* The refactor is not necessary or relatively minor because there are only two methods(remove_hyperlink and submit_hyperlink) in submitted_content_controller that are mainly on hyperlinks. Moreover, submission via hyperlink is as simple as it is now, and it doesn't need a controller of its own. It will just overcomplicate things. It is better to keep all methods related to submission under one controller.&lt;br /&gt;
&lt;br /&gt;
===Testing Plan===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Rspec Testing:&lt;br /&gt;
&lt;br /&gt;
1. git clone https://github.com/LeooHsiang/expertiza&lt;br /&gt;
&lt;br /&gt;
2. Change directory to expertiza. Run &amp;quot;bundle install&amp;quot; and rails db:migrate.&lt;br /&gt;
&lt;br /&gt;
3. Start the rails server.&lt;br /&gt;
&lt;br /&gt;
4. Run the following command in a new terminal of the expertiza directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Manual Testing: &lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edge Cases:&lt;br /&gt;
* Return error when the user who is not the assignment's participant trying to do the submission&lt;br /&gt;
* Return 'You or your teammate(s) have already submitted the same hyperlink.' when the same hyperlink already submitted&lt;br /&gt;
* Return error when the URL/hyperlink is invalid&lt;br /&gt;
* Return error when the uploading file is smaller than 5 MB&lt;br /&gt;
* Return error when the uploading file is not pdf or file type is not among specified&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143739</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143739"/>
		<updated>2022-03-28T01:29:49Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
'''submitted_content_controller''' had some problems that violate essential Rails design principles which needed to be rectified.&lt;br /&gt;
&lt;br /&gt;
The following issues were addressed as a part of refactoring this controller:&lt;br /&gt;
&lt;br /&gt;
* Renaming methods to more appropriate and functionality specific names.&lt;br /&gt;
* some methods being too long which needed to be broken down.&lt;br /&gt;
* Remove or change the comment for the methods to be more meaningful and reflective on the actual functionality.&lt;br /&gt;
&lt;br /&gt;
===List of Issues in submitted_content_controller.rb===&lt;br /&gt;
&lt;br /&gt;
* Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
* Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
* Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
* submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
* Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity in order to actually proceed with submitting a file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
:: Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Would it be helpful and clean to separate this controller into a submitted_files_controller and a submitted_hyperlinks_controller?&lt;br /&gt;
* The refactor is not necessary or relatively minor because there are only two methods(remove_hyperlink and submit_hyperlink) in submitted_content_controller that are mainly on hyperlinks. Moreover, submission via hyperlink is as simple as it is now, and it doesn't need a controller of its own. It will just overcomplicate things. It is better to keep all methods related to submission under one controller.&lt;br /&gt;
&lt;br /&gt;
===Testing Plan===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Rspec Testing:&lt;br /&gt;
&lt;br /&gt;
1. git clone https://github.com/LeooHsiang/expertiza&lt;br /&gt;
&lt;br /&gt;
2. Change directory to expertiza. Run &amp;quot;bundle install&amp;quot; and rails db:migrate.&lt;br /&gt;
&lt;br /&gt;
3. Start the rails server.&lt;br /&gt;
&lt;br /&gt;
4. Run the following command in a new terminal of the expertiza directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Manual Testing: &lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edge Cases:&lt;br /&gt;
* Return error when the user who is not the assignment's participant trying to do the submission&lt;br /&gt;
* Return 'You or your teammate(s) have already submitted the same hyperlink.' when the same hyperlink already submitted&lt;br /&gt;
* Return error when the URL/hyperlink is invalid&lt;br /&gt;
* Return error when the uploading file is smaller than 5 MB&lt;br /&gt;
* Return error when the uploading file is not pdf or file type is not among specified&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143738</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143738"/>
		<updated>2022-03-28T01:28:45Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* List of Issues in submitted_content_controller.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
'''submitted_content_controller''' had some problems that violate essential Rails design principles which needed to be rectified.&lt;br /&gt;
&lt;br /&gt;
The following issues were addressed as a part of refactoring this controller:&lt;br /&gt;
&lt;br /&gt;
* Renaming methods to more appropriate and functionality specific names.&lt;br /&gt;
* some methods being too long which needed to be broken down.&lt;br /&gt;
* Remove or change the comment for the methods to be more meaningful and reflective on the actual functionality.&lt;br /&gt;
&lt;br /&gt;
===List of Issues in submitted_content_controller.rb===&lt;br /&gt;
&lt;br /&gt;
* Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
* Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
* Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
* submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
* Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity in order to actually proceed with submitting a file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
:: Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Would it be helpful and clean to separate this controller into a submitted_files_controller and a submitted_hyperlinks_controller?&lt;br /&gt;
* The refactor is not necessary or relatively minor because there are only two methods(remove_hyperlink and submit_hyperlink) in submitted_content_controller that are mainly on hyperlinks. Moreover, submission via hyperlink is as simple as it is now, and it doesn't need a controller of its own. It will just overcomplicate things. It is better to keep all methods related to submission under one controller.&lt;br /&gt;
&lt;br /&gt;
===Testing Plan===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Rspec Testing:&lt;br /&gt;
&lt;br /&gt;
1. git clone https://github.com/LeooHsiang/expertiza&lt;br /&gt;
&lt;br /&gt;
2. Change directory to expertiza. Run &amp;quot;bundle install&amp;quot; and rails db:migrate.&lt;br /&gt;
&lt;br /&gt;
3. Start the rails server.&lt;br /&gt;
&lt;br /&gt;
4. Run the following command in a new terminal of the expertiza directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Manual Testing: &lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Edge Cases:&lt;br /&gt;
* Return error when the user who is not the assignment's participant trying to do the submission&lt;br /&gt;
* Return 'You or your teammate(s) have already submitted the same hyperlink.' when the same hyperlink already submitted&lt;br /&gt;
* Return error when the URL/hyperlink is invalid&lt;br /&gt;
* Return error when the uploading file is smaller than 5 MB&lt;br /&gt;
* Return error when the uploading file is not pdf or file type is not among specified&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143392</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143392"/>
		<updated>2022-03-21T23:59:28Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* E2221. Refactoring of submitted_content_controller */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
This controller has some problems that violate some essential Rails design principles. There are few methods in this controller that are far too long and need to be broken down into multiple methods. A few methods need to be commented as well. Few Methods need to be renamed. &lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Problems and solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
:: Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Testing===&lt;br /&gt;
Please see the manual and rspec testing in the video below&lt;br /&gt;
&lt;br /&gt;
Inorder to make sure the core functionalities of the Expertiza not break by our refactoring, we did rspec testing using the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143388</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143388"/>
		<updated>2022-03-21T23:56:56Z</updated>

		<summary type="html">&lt;p&gt;Abommag: /* E2221. Refactoring of submitted_content_controller */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
This controller has some problems that violate some essential Rails design principles. There are few methods in this controller that are far too long and need to be broken down into multiple methods. A few methods need to be commented as well. Few Methods need to be renamed. &lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Problems and solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
:: * '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Testing===&lt;br /&gt;
Please see the manual and rspec testing in the video below&lt;br /&gt;
&lt;br /&gt;
Inorder to make sure the core functionalities of the Expertiza not break by our refactoring, we did rspec testing using the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143386</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143386"/>
		<updated>2022-03-21T23:56:05Z</updated>

		<summary type="html">&lt;p&gt;Abommag: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E2221. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
This controller has some problems that violate some essential Rails design principles. There are few methods in this controller that are far too long and need to be broken down into multiple methods. A few methods need to be commented as well. Few Methods need to be renamed. &lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Problems and solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view - expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
:: Therefore, the comment is invalid. So we removed the comment on line 67 because it was redundant.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them:&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication of user, for content size and content integrity.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
::Too many nested if-else statements inside this method, can we do something better?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:: * '''Solution :''' Renamed the folder_action method to perform_folder_action so that method name is more indicative of the actions performed by it.&lt;br /&gt;
Since we are not working with objects and params is a method in ruby, changing the if-else statements would not give any advantage. Even changing into case statements would not be advantageous to the code.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code in both submitted_content_controller and submitted_folder_container where necessary to describe the function a method is performing for better understanding of code. We kept all the comments in sync with the code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
:: * '''Solution :''' The perform_folder_action method in submitted_content_controller and the methods following it are all related to actions such as delete, move, rename, copy or create folders. Since all these methods are related to folder actions, we created a new class and controller to perform these actions. We moved all the related code to a new submitted_folder_controller. The submitted_folder_controller has single responsibility of handling folder related actions. This will made the previously long code  more readable and understandable.&lt;br /&gt;
&lt;br /&gt;
::'''submitted_folder_controller.rb''' looks like below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===Testing===&lt;br /&gt;
Please see the manual and rspec testing in the video below&lt;br /&gt;
&lt;br /&gt;
Inorder to make sure the core functionalities of the Expertiza not break by our refactoring, we did rspec testing using the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rspec spec/controllers/submitted_content_controller_spec.rb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://drive.google.com/file/d/1Y7edau8A0nOVaGah1wg3OcK5eGVcGLjh/view?usp=sharing '''Manual Testing Video with voice over''']&lt;br /&gt;
&lt;br /&gt;
===References===&lt;br /&gt;
&lt;br /&gt;
#[https://github.com/expertiza/expertiza Expertiza on GitHub]&lt;br /&gt;
#[https://github.com/LeooHsiang/expertiza/tree/beta Forked Repository Link]&lt;br /&gt;
#[http://expertiza.ncsu.edu/ Expertiza website] &lt;br /&gt;
#[https://expertiza.csc.ncsu.edu/index.php/Main_Page Expertiza Documentation]&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143076</id>
		<title>CSC/ECE 517 Spring 2022 - E2221. Refactor submitted content controller.rb</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2022_-_E2221._Refactor_submitted_content_controller.rb&amp;diff=143076"/>
		<updated>2022-03-20T21:53:03Z</updated>

		<summary type="html">&lt;p&gt;Abommag: Created page with &amp;quot;==E1553. Refactoring of submitted_content_controller==  This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source p...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==E1553. Refactoring of submitted_content_controller==&lt;br /&gt;
&lt;br /&gt;
This page provides a description of the refactoring done on 'submitted_content_controller', a part of the Open Source project - Expertiza, at North Carolina State University. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===About Expertiza===&lt;br /&gt;
&lt;br /&gt;
[http://expertiza.ncsu.edu/ Expertiza] is an open source project based on [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments, enforce deadlines etc. It also allows the instructor to create list of topics from which students can bid for their project requirements. Students can form teams in Expertiza to work on various projects and assignments. Students can also review other student's or team's work and provide useful information on the scope of improvement of their project. Expertiza supports submission across various document types, including the URLs and wiki pages.&lt;br /&gt;
&lt;br /&gt;
===Background on submitted_content_controller===&lt;br /&gt;
&lt;br /&gt;
The submitted_content_controller controls everything a user submits to expertiza. It contains the methods to submit assignment related information such as submit &amp;amp; remove hyperlinks, files and other relevant information that could be part of the assignment. It also handles views based on the user roles and permissions they have. The project involved working out on few issues of designing in the controller to incorporate the OODD principles and ruby design principles so that the readability of code could be improved.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
This controller has some problems that violate some essential Rails design principles. There are few methods in this controller that are far too long and need to be broken down into multiple methods. A few methods need to be commented as well. Few Methods need to be renamed. &lt;br /&gt;
&lt;br /&gt;
===Files modified and created in the project===&lt;br /&gt;
&lt;br /&gt;
We worked on the 'submitted_content_controller.rb' and created a new controller file while refactoring and named it 'submitted_folder_controller'.&lt;br /&gt;
&lt;br /&gt;
===Problems and solutions devised===&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 1 :''' Remove the comment  “# hence use team count for the check”. &lt;br /&gt;
&lt;br /&gt;
:: Removed the comment on line 19 because the code no longer checks the team count.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 2 :'''  Change the method name view to something more informative of the method.&lt;br /&gt;
&lt;br /&gt;
:: The original code uses the generic 'view' method name to display a view corresponding to a case when submissions cannot be accepted, for instance in the case when a deadline is passed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def view&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.get_current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The function name view is changed to prevent_submission as this is called when @assignment.submission_allowed(topic_id) is false which essentially means user should not be able to submit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def prevent_submission&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    # @assignment is used to store the assignment of the participant&lt;br /&gt;
    @assignment = @participant.assignment&lt;br /&gt;
    # @can_submit is the flag indicating if the user can submit or not in current stage&lt;br /&gt;
    @can_submit = false&lt;br /&gt;
    @stage = @assignment.current_stage(SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id))&lt;br /&gt;
    redirect_to action: 'edit', id: params[:id], view: true&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 3 :''' Check the validity of the comment ”# Note: This is not used yet in the view until we all decide to do so”.&lt;br /&gt;
&lt;br /&gt;
:: remove_hyperlink is used in the view&lt;br /&gt;
&lt;br /&gt;
expertiza/app/views/submitted_content/_hyperlink.html.erb&lt;br /&gt;
&lt;br /&gt;
Therefore, the comment is invalid. So we removed the comment on line 67.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 4 :'''  submit_file method is long. Try to break it into multiple methods.&lt;br /&gt;
&lt;br /&gt;
:: The submit_file method was defined as below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(participant.user_id)&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', &amp;quot;/&amp;quot;)&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(&amp;quot; &amp;quot;, '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, &amp;quot;wb&amp;quot;) {|f| f.write(file.read) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if get_file_type(safe_filename) == &amp;quot;zip&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    # Send link to update the review to all the reviewers assigned to this reviewee&lt;br /&gt;
    mail_assigned_reviewers(team)&lt;br /&gt;
    # participant.assignment.email(participant.id) rescue nil&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Solution :''' The changes made for submit_file and reasons for them&lt;br /&gt;
&lt;br /&gt;
:: '''def get_file_upload(participant, file, file_content) :'''  The main reason for creating this new method from submit_file is that in order to submit a file, we need to first upload the file for submission, so that's a two related but different actions. Therefore, this method handles the work needed to be done for uploading a file for submission. The refactor is needed for making the submit_file shorter and more readable.&lt;br /&gt;
&lt;br /&gt;
:: '''def notify_reviewers(participant):''' Originally, submit_file has a final step to notify all reviewers assigned to this reviewee/submission after the file is submitted. The action of notify reviewers can be refactored into its own method from the submit_file method since they are two different actions, and now notify_reviewers method can be reused if needed for other type of submission such as hyperlink.&lt;br /&gt;
&lt;br /&gt;
Also, added some error codes in submit_file method additionally for authentication.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def submit_file&lt;br /&gt;
    participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    # check if the current user id is same as participant user id&lt;br /&gt;
    # Validate the user and on failure redirect to edit function for Submitting a file.&lt;br /&gt;
    unless current_user_id?(participant.user_id)&lt;br /&gt;
      flash[:error] = &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file = params[:uploaded_file]&lt;br /&gt;
    file_size_limit = 5&lt;br /&gt;
&lt;br /&gt;
    # Check if file size is greater than the specified limit then redirect to edit function&lt;br /&gt;
    unless check_content_size(file, file_size_limit)&lt;br /&gt;
      flash[:error] = &amp;quot;File size must smaller than #{file_size_limit}MB&amp;quot;&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    file_content = file.read&lt;br /&gt;
&lt;br /&gt;
    # check if file type is not among specified then redirect to edit function&lt;br /&gt;
    unless check_content_type_integrity(file_content)&lt;br /&gt;
      flash[:error] = 'File type error'&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
      return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    # Submit the file successfully&lt;br /&gt;
    full_filename = get_file_upload(participant, file, file_content)&lt;br /&gt;
    assignment = Assignment.find(participant.parent_id)&lt;br /&gt;
    team = participant.team&lt;br /&gt;
    SubmissionRecord.create(team_id: team.id,&lt;br /&gt;
                            content: full_filename,&lt;br /&gt;
                            user: participant.name,&lt;br /&gt;
                            assignment_id: assignment.id,&lt;br /&gt;
                            operation: &amp;quot;Submit File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, participant.name, 'The file has been submitted.', request)&lt;br /&gt;
    notify_reviewers(participant)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def get_file_upload(participant, file, file_content)&lt;br /&gt;
    participant.team.set_student_directory_num&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = '/'&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    curr_directory = if params[:origin] == 'review'&lt;br /&gt;
                       participant.review_file_path(params[:response_map_id]).to_s + @current_folder.name&lt;br /&gt;
                     else&lt;br /&gt;
                       participant.team.path.to_s + @current_folder.name&lt;br /&gt;
                     end&lt;br /&gt;
    FileUtils.mkdir_p(curr_directory) unless File.exist? curr_directory&lt;br /&gt;
    safe_filename = file.original_filename.tr('\\', '/')&lt;br /&gt;
    safe_filename = FileHelper.sanitize_filename(safe_filename) # new code to sanitize file path before upload*&lt;br /&gt;
    full_filename = curr_directory + File.split(safe_filename).last.tr(' ', '_') # safe_filename #curr_directory +&lt;br /&gt;
    File.open(full_filename, 'wb') { |f| f.write(file_content) }&lt;br /&gt;
    if params['unzip']&lt;br /&gt;
      SubmittedContentHelper.unzip_file(full_filename, curr_directory, true) if file_type(safe_filename) == 'zip'&lt;br /&gt;
    end&lt;br /&gt;
    return full_filename&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def notify_reviewers(participant)&lt;br /&gt;
    participant.mail_assigned_reviewers&lt;br /&gt;
&lt;br /&gt;
    if params[:origin] == 'review'&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to action: 'edit', id: participant.id&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 5 :''' Change the method name folder_action to something like perform_folder_action.&lt;br /&gt;
&lt;br /&gt;
:: * '''Solution :''' Rename the folder_action method to perform_folder_action&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
     @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
     return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
     @current_folder = DisplayOption.new&lt;br /&gt;
     @current_folder.name = '/'&lt;br /&gt;
     @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
     if params[:faction][:delete]&lt;br /&gt;
       delete_selected_files&lt;br /&gt;
     elsif params[:faction][:rename]&lt;br /&gt;
       rename_selected_file&lt;br /&gt;
     elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
     elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
     elsif params[:faction][:create]&lt;br /&gt;
       create_new_folder&lt;br /&gt;
     end&lt;br /&gt;
     redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
   end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 6 :''' We have commented the code where necessary to describe the function a method is performing for better understanding of code.&lt;br /&gt;
&lt;br /&gt;
*  '''Issue 7 :''' Some of the actions in the code (from line 218 to 285) could perhaps be moved to another class.&lt;br /&gt;
&lt;br /&gt;
:: * '''Solution :''' Created a new class and separated the methods perform_folder_action and all files related methods into this new controlled and named it submitted_folder_container.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def perform_folder_action&lt;br /&gt;
    @participant = AssignmentParticipant.find(params[:id])&lt;br /&gt;
    return unless current_user_id?(@participant.user_id)&lt;br /&gt;
&lt;br /&gt;
    @current_folder = DisplayOption.new&lt;br /&gt;
    @current_folder.name = &amp;quot;/&amp;quot;&lt;br /&gt;
    @current_folder.name = FileHelper.sanitize_folder(params[:current_folder][:name]) if params[:current_folder]&lt;br /&gt;
    if params[:faction][:delete]&lt;br /&gt;
      delete_selected_files&lt;br /&gt;
    elsif params[:faction][:rename]&lt;br /&gt;
      rename_selected_file&lt;br /&gt;
    elsif params[:faction][:move]&lt;br /&gt;
      move_selected_file&lt;br /&gt;
    elsif params[:faction][:copy]&lt;br /&gt;
      copy_selected_file&lt;br /&gt;
    elsif params[:faction][:create]&lt;br /&gt;
      create_new_folder&lt;br /&gt;
    end&lt;br /&gt;
    redirect_to action: 'edit', id: @participant.id&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Raises error if there are issues with downloading of current selected folder and file in it&lt;br /&gt;
  def download&lt;br /&gt;
    begin&lt;br /&gt;
      folder_name = params['current_folder']['name']&lt;br /&gt;
      file_name = params['download']&lt;br /&gt;
      raise &amp;quot;Folder_name is nil.&amp;quot; if folder_name.nil?&lt;br /&gt;
      raise &amp;quot;File_name is nil.&amp;quot; if file_name.nil?&lt;br /&gt;
      raise &amp;quot;Cannot send a whole folder.&amp;quot; if File.directory?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
      raise &amp;quot;File does not exist.&amp;quot; unless File.exist?(folder_name + &amp;quot;/&amp;quot; + file_name)&lt;br /&gt;
&lt;br /&gt;
      send_file(folder_name + &amp;quot;/&amp;quot; + file_name, disposition: 'inline')&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def controller_locale&lt;br /&gt;
    locale_for_student&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Moves file from current location/directory to specified directory/location and raises error if any problem occurs&lt;br /&gt;
  def move_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:move]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.move_file(old_filename, newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The file was successfully moved from \&amp;quot;/#{params[:filenames][params[:chk_files]]}\&amp;quot; to \&amp;quot;/#{params[:faction][:move]}\&amp;quot;&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem moving the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # To rename a selected file, checks any discrepancies in new file name, if new filename is same as some existing filename in current directory&lt;br /&gt;
  # error is flashed.&lt;br /&gt;
  def rename_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:rename])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file already exists in this directory with the name \&amp;quot;#{params[:faction][:rename]}\&amp;quot;&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
&lt;br /&gt;
      File.send(&amp;quot;rename&amp;quot;, old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem renaming the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to delete selected file&lt;br /&gt;
  def delete_selected_files&lt;br /&gt;
    filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    FileUtils.rm_r(filename)&lt;br /&gt;
    participant = Participant.find_by(id: params[:id])&lt;br /&gt;
    assignment = participant.try(:assignment)&lt;br /&gt;
    team = participant.try(:team)&lt;br /&gt;
    SubmissionRecord.create(team_id: team.try(:id),&lt;br /&gt;
                            content: filename,&lt;br /&gt;
                            user: participant.try(:name),&lt;br /&gt;
                            assignment_id: assignment.try(:id),&lt;br /&gt;
                            operation: &amp;quot;Remove File&amp;quot;)&lt;br /&gt;
    ExpertizaLogger.info LoggerMessage.new(controller_name, @participant.name, 'The selected file has been deleted.', request)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to copy selected file&lt;br /&gt;
  def copy_selected_file&lt;br /&gt;
    old_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + params[:filenames][params[:chk_files]]&lt;br /&gt;
    new_filename = params[:directories][params[:chk_files]] + &amp;quot;/&amp;quot; + FileHelper.sanitize_filename(params[:faction][:copy])&lt;br /&gt;
    begin&lt;br /&gt;
      raise &amp;quot;A file with this name already exists. Please delete the existing file before copying.&amp;quot; if File.exist?(new_filename)&lt;br /&gt;
      raise &amp;quot;The referenced file does not exist.&amp;quot; unless File.exist?(old_filename)&lt;br /&gt;
&lt;br /&gt;
      FileUtils.cp_r(old_filename, new_filename)&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = &amp;quot;There was a problem copying the file: &amp;quot; + e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Function to create new folder&lt;br /&gt;
  def create_new_folder&lt;br /&gt;
    newloc = @participant.dir_path&lt;br /&gt;
    newloc += &amp;quot;/&amp;quot;&lt;br /&gt;
    newloc += params[:faction][:create]&lt;br /&gt;
    begin&lt;br /&gt;
      FileHelper.create_directory_from_path(newloc)&lt;br /&gt;
      flash[:note] = &amp;quot;The directory #{params[:faction][:create]} was created.&amp;quot;&lt;br /&gt;
    rescue StandardError =&amp;gt; e&lt;br /&gt;
      flash[:error] = e.message&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
end&lt;/div&gt;</summary>
		<author><name>Abommag</name></author>
	</entry>
</feed>