CSC/ECE 517 Spring 2015/oss E1507 DG

From Expertiza_Wiki
Jump to navigation Jump to search

E1507. Refactoring Review Files Controller & Submitted Content Controller

This page provides a description of the Expertiza based OSS project. This project aimed at refactoring the Review Files Controller & Submitted Content Controller as well as fixing the bug #483

What is Expertiza

Expertiza is a Open Source Rails application where students can submit and peer-review learning objects (articles, code, web sites, etc). It is used in select courses at NC State and by professors at several other colleges and universities. This Open Source application can be cloned from Github, the latest active branch is "Rails 4".

Project Desicription<ref>https://docs.google.com/document/d/1J0WUBtYV_MDhpEQ-50z8gXE-OrvVkpEaZxvn_9RCAsM/edit#</ref>

There are 5 major goals for this project:

1. Fix Bug #483<ref>https://github.com/expertiza/expertiza/issues/483</ref>, which causes some error and prevent users to get access to the submitted_content page.

2.Break up the complex methods such as get_comments, show_code_file_diff. Anything that can be modularized should be modularized (Single Responsibility)

3.While breaking up the complex methods, look out for possible helper functions. If there are any, move them to the review_files_helper.rb

4.Remove commented out code from the controller

5.Refactor the file based on Global Rules<ref>https://docs.google.com/document/d/1qQD7fcypFk77nq7Jx7ZNyCNpLyt1oXKaq5G-W7zkV3k/edit?usp=sharing</ref>.

Bug #483

In "Your works" view, students can only submit links but no files.

This is caused by commit f313711 where the line 13 in submitted_content/_main.html.erb was commented out.

<%#= render partial: 'submitted_content/submitted_files', locals: {participant: @participant, stage: @stage} %>

But after uncommented line 13 in submitted_content/_main.html.erb and refresh the page, the Rails Server stopped responding.

Refactoring Review Files Controller & Submitted Content Controller

What they do

This review_files_controller.rb is responsible for handling the review files of the participants. This controller helps in uploading newer versions of reviews for an assignment and also in displaying all the versions (and diff between versions/code) with the help of submitted_content_controller.rb.

What’s wrong with them

There are quite a few complex functions inside these controllers. These functions can easily be broken up into much more smaller methods with specific functionalities. They also need to be refactored to meet the Global Rules.



Changes Made

Files involved

1. review_files_controller.rb

2. submitted_content_controller.rb

3. review_files_helper.rb

4. review_comments_helper.rb

5. submitted_content/_main.html.erb

6. model/assignment.rb

For Bug #483 fixing

Git log can be viewed in commit aa37e2e

1. In submitted_content_controller.rb, line 19.

if @assignment.max_team_size > 1 && @participant.team.nil?
     flash[:error] = "This is a team assignment. Before submitting your work, you must <a style='color: blue;' href='../../student_teams/view/?student_id=#{params[:id]}'>create a team</a>, 
                     even if you will be the only member of the team"
     redirect_to controller: 'student_task', action: 'view', id: params[:id]
else if @participant.team.nil?
     #create a new team for current user before submission
     team = AssignmentTeam.create_team_and_node(@assignment.id)
     team.add_member(User.find(@participant.user_id),@assignment.id)
end

This else if must be a mistake, so we changed it to:

elsif @participant.team.nil?

2. In model/assignment.rb, line 489.

Course.find(self.course_id).get_path

The Course model doesn't have an attribute called get_path, it should be directory_path, so we changed it to

Course.find(self.course_id).directory_path

3. In submitted_content/_main.html.erb, line 18.

<% if participant.assignment.is_coding_assignment%>
     <%= link_to "Code Review Dashboard", :controller => 'review_files',
       :action => 'show_all_submitted_files',
       :participant_id => assignment_participant.id,
       :stage => stage %>
   
<% end %>

As in this page there doesn't have a parameter called assignment_participant, as it need to get the participant's id, so we changed this line to:

:participant_id => participant.id

4. In config/routes.rb. Added one more routes

post :submit_file

Refactoring review_files_controller.rb

1. Changed and and or to && and || to meet the requirements in the Global Rules.

2. In def get_comments, deleted unused variable:

newobj = ReviewComment.where(review_file_id: params[:file_id]);

3. In def show_all_submitted_files, deleted unused variable:

file_path = ReviewFile.get_file(code_review_dir, versions.sort.last,base_filename)

4. In def show_all_submitted_files, deleted unused variable:

code_review_dir = ReviewFilesHelper::get_code_review_file_dir(AssignmentParticipant.find(auth[base_filename][versions.sort.last]))

5. The method def get_comments is too complex, so we modularized part of its code in review_comments_helper.rb, we created a new method: def self.populate_comments, which returns handle, comment, authorflag these three variables.

 def self.populate_comments(params, authorflag, comment)
   assignmentparticipant = AssignmentParticipant.find(params[:participant_id])
   current_participant = AssignmentParticipant.where(parent_id: assignmentparticipant[:parent_id], user_id: session[:user].id).first
   if current_participant.id.to_s == params[:participant_id]
     authorflag = 1
   else
     authorflag = 0
   end
   member = []
   if assignmentparticipant.assignment.team_assignment
     assignmentparticipant.team.get_participants.each_with_index {|member1, index|
       member[index] = member1.id
     }
   end
   if (comment[:reviewer_participant_id] ==  current_participant.id)
     handle = "Me :"
     authorflag = 0
   elsif member.include? comment[:reviewer_participant_id] || comment[:reviewer_participant_id] == assignmentparticipant.id
     handle = "Author :"
     authorflag = 0
   else
     handle = "Reviewer"+comment[:reviewer_participant_id].to_s
   end
   return handle, comment, authorflag
 end

6. Rewrited all :key => value to key: value format according to the requirements in the Global Rules<ref>https://docs.google.com/document/d/1qQD7fcypFk77nq7Jx7ZNyCNpLyt1oXKaq5G-W7zkV3k/edit</ref>.

7. The method def show_code_files_diffIn is too complex, we created a new method: def self.populate_shareObj in review_files_helper.rb to perform part of the show_code_files_diff.

 def self.populate_shareObj(processor)
   first_line_num = []
   second_line_num = []
   first_offset = []
   second_offset = []
   offsetswithcomments_file1 = []
   offsetswithcomments_file2 = []
   first_offset << 0
   second_offset << 0
   first_count = 0
   second_count = 0
   for i in (0..processor.absolute_line_num)
     first_offset = ReviewFile.get_first_offset(processor, i, @first_offset)
     second_offset = ReviewFile.get_second_offset(processor, i, @second_offset)
     first_line_num_new = Hash.new
     first_line_num_new = ReviewFile.get_first_line_num(processor, i, first_count)
     first_line_num << first_line_num[:first_line_num]
     first_count = first_line_num[:first_count]
     second_line_num_new = Hash.new
     second_line_num_new = ReviewFile.get_second_line_num(processor, i,second_count)
     second_line_num << second_line_num[:second_line_num]
     second_count = second_line_num[:second_count]
     # Remove newlines at the end of this line of code
     processor = ReviewFile.get_first_file_array(processor, i)
     processor = ReviewFile.get_second_file_array(processor, i)
     shareObj = Hash.new()
     shareObj['linearray1'] = processor.first_file_array
     shareObj['linearray2'] = processor.second_file_array
     shareObj['comparator'] = processor.comparison_array
     shareObj['linenumarray1'] = first_line_num
     shareObj['linenumarray2'] = second_line_num
     shareObj['offsetarray1'] = first_offset
     shareObj['offsetarray2'] = second_offset
     return first_line_num, second_line_num, first_count, second_count, shareObj
   end
 end

8. In review_files_helper.rb, created a new method: def self.find_review_files, which contains some statements in def show_all_submitted_files.

 def self.find_review_files(participant) 
   # Find all files over all versions submitted by the team
   all_review_files = Array.new
   if participant.assignment.team_assignment
     participant.team.get_participants.each_with_index { |member,index|
       all_review_files += ReviewFile.where(author_participant_id: member.id)
     }
   else
     all_review_files = ReviewFile.where(author_participant_id: @participant.id)
   end
   all_review_files
 end

9. In review_files_helper.rb, created a new method: def self.find_review_versions, which contains some statements in def show_all_submitted_files.

 def self.find_review_versions(all_review_files) 
   file_version_map = Hash.new
   all_review_files.each_with_index do |each_file,index|
     file_version_map[File.basename(each_file.filepath)] = Array.new unless
     file_version_map[File.basename(each_file.filepath)]
     file_version_map[File.basename(each_file.filepath)] << each_file.version_number
   end
   return file_version_map
 end

Refactoring submitted_content_controller.rb

1. Changed and and or to && and || to meet the requirements in the Global Rules.

2. Rewrited all :key => value to key: value format.

3. Rewrited all param['string'] to params[:string].

4. Added one more routes post :folder_action to config/routes.rb

5. Changed all array.size == 0 to array.zero?

6. Changed all find_by_x(val) and where("x=val") to where(x: val)

7. In def remove_hyperlink, deleted redundant line:

@participant = AssignmentParticipant.find(params[:id])

8. In def download, deleted commented line:

#folder_name = FileHelper::sanitize_folder(@current_folder.name)

Results Screenshot

After fixing the bug #483, now the submit files function works.

The file is stored at:

References

<references/>