<?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=Tmainka</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=Tmainka"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Tmainka"/>
	<updated>2026-06-13T20:27: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_Fall_2014/oss_E1458_sst&amp;diff=90686</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90686"/>
		<updated>2014-10-29T19:32:09Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* External Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
Although ResponseController is a complex class, we managed to improve its code significantly through refactoring. We made use of [https://codeclimate.com/ Code Climate] in order to run analysis of our changes against the original Expertiza code. We have managed to reduce the overall complexity of this class from 719 to 581 and duplication from 685 to 410. &lt;br /&gt;
Also one of the major refactoring was performed on &amp;quot;rereview&amp;quot; method. We have managed to reduce its complexity from 129 to 91 by extracting methods.&lt;br /&gt;
&lt;br /&gt;
'''Original ResponseController on Codeclimate:'''&amp;lt;ref&amp;gt;https://codeclimate.com/github/expertiza/expertiza/ResponseController&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-original.png]]&lt;br /&gt;
[[File:rereview-original.png]]&lt;br /&gt;
&lt;br /&gt;
'''ResponseController on Codeclimate after Refactoring:'''&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-new.png]]&lt;br /&gt;
[[File:rereview-new.png]]&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90684</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90684"/>
		<updated>2014-10-29T19:31:09Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* External Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
Although ResponseController is a complex class, we managed to improve its code significantly through refactoring. We made use of [https://codeclimate.com/ Code Climate] in order to run analysis of our changes against the original Expertiza code. We have managed to reduce the overall complexity of this class from 719 to 581 and duplication from 685 to 410. &lt;br /&gt;
Also one of the major refactoring was performed on &amp;quot;rereview&amp;quot; method. We have managed to reduce its complexity from 129 to 91 by extracting methods.&lt;br /&gt;
&lt;br /&gt;
'''Original ResponseController on Codeclimate:'''&amp;lt;ref&amp;gt;https://codeclimate.com/github/expertiza/expertiza/ResponseController&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-original.png]]&lt;br /&gt;
[[File:rereview-original.png]]&lt;br /&gt;
&lt;br /&gt;
'''ResponseController on Codeclimate after Refactoring:'''&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-new.png]]&lt;br /&gt;
[[File:rereview-new.png]]&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90683</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90683"/>
		<updated>2014-10-29T19:30:36Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* External Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
Although ResponseController is a complex class, we managed to improve its code significantly through refactoring. We made use of [https://codeclimate.com/ Code Climate] in order to run analysis of our changes against the original Expertiza code. We have managed to reduce the overall complexity of this class from 719 to 581 and duplication from 685 to 410. &lt;br /&gt;
Also one of the major refactoring was performed on &amp;quot;rereview&amp;quot; method. We have managed to reduce its complexity from 129 to 91 by extracting methods.&lt;br /&gt;
&lt;br /&gt;
'''Original ResponseController on Codeclimate:'''&amp;lt;ref&amp;gt;https://codeclimate.com/github/expertiza/expertiza/ResponseController&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-original.png]]&lt;br /&gt;
[[File:rereview-original.png]]&lt;br /&gt;
&lt;br /&gt;
'''ResponseController on Codeclimate after Refactoring:'''&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-new.png]]&lt;br /&gt;
[[File:rereview-new.png]]&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;reference/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90680</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90680"/>
		<updated>2014-10-29T19:27:03Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
Although ResponseController is a complex class, we managed to improve its code significantly through refactoring. We made use of [https://codeclimate.com/ Code Climate] in order to run analysis of our changes against the original Expertiza code. We have managed to reduce the overall complexity of this class from 719 to 581 and duplication from 685 to 410. &lt;br /&gt;
Also one of the major refactoring was performed on &amp;quot;rereview&amp;quot; method. We have managed to reduce its complexity from 129 to 91 by extracting methods.&lt;br /&gt;
&lt;br /&gt;
'''Original ResponseController on Codeclimate:'''&amp;lt;ref&amp;gt;https://codeclimate.com/github/expertiza/expertiza/ResponseController&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-original.png]]&lt;br /&gt;
[[File:rereview-original.png]]&lt;br /&gt;
&lt;br /&gt;
'''ResponseController on Codeclimate after Refactoring:'''&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-new.png]]&lt;br /&gt;
[[File:rereview-new.png]]&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90677</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90677"/>
		<updated>2014-10-29T19:25:34Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
Although ResponseController is a complex class, we managed to improve its code significantly through refactoring. We made use of [https://codeclimate.com/ Code Climate] in order to run analysis of our changes against the original Expertiza code. We have managed to reduce the overall complexity of this class from 719 to 581 and duplication from 685 to 410. &lt;br /&gt;
Also one of the major refactoring was performed on &amp;quot;rereview&amp;quot; method. We have managed to reduce its complexity from 129 to 91 by extracting methods.&lt;br /&gt;
&lt;br /&gt;
'''Original ResponseController on Codeclimate:'''&amp;lt;ref&amp;gt;https://codeclimate.com/github/expertiza/expertiza/ResponseController &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-original.png]]&lt;br /&gt;
[[File:rereview-original.png]]&lt;br /&gt;
&lt;br /&gt;
'''ResponseController on Codeclimate after Refactoring:'''&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-new.png]]&lt;br /&gt;
[[File:rereview-new.png]]&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90674</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90674"/>
		<updated>2014-10-29T19:24:36Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
Although ResponseController is a complex class, we managed to improve its code significantly through refactoring. We made use of [https://codeclimate.com/ Code Climate] in order to run analysis of our changes against the original Expertiza code. We have managed to reduce the overall complexity of this class from 719 to 581 and duplication from 685 to 410. &lt;br /&gt;
Also one of the major refactoring was performed on &amp;quot;rereview&amp;quot; method. We have managed to reduce its complexity from 129 to 91 by extracting methods.&lt;br /&gt;
&lt;br /&gt;
'''Original ResponseController on Codeclimate:'''&amp;lt;ref&amp;gt;[https://codeclimate.com/github/expertiza/expertiza/ResponseController &amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-original.png]]&lt;br /&gt;
[[File:rereview-original.png]]&lt;br /&gt;
&lt;br /&gt;
'''ResponseController on Codeclimate after Refactoring:'''&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-new.png]]&lt;br /&gt;
[[File:rereview-new.png]]&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90673</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90673"/>
		<updated>2014-10-29T19:24:00Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
Although ResponseController is a complex class, we managed to improve its code significantly through refactoring. We made use of [https://codeclimate.com/ Code Climate] in order to run analysis of our changes against the original Expertiza code. We have managed to reduce the overall complexity of this class from 719 to 581 and duplication from 685 to 410. &lt;br /&gt;
Also one of the major refactoring was performed on &amp;quot;rereview&amp;quot; method. We have managed to reduce its complexity from 129 to 91 by extracting methods.&lt;br /&gt;
&lt;br /&gt;
'''Original ResponseController on Codeclimate:&amp;lt;ref&amp;gt;[https://codeclimate.com/github/expertiza/expertiza/ResponseController &amp;lt;/ref&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-original.png]]&lt;br /&gt;
[[File:rereview-original.png]]&lt;br /&gt;
&lt;br /&gt;
'''ResponseController on Codeclimate after Refactoring:'''&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-new.png]]&lt;br /&gt;
[[File:rereview-new.png]]&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90671</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90671"/>
		<updated>2014-10-29T19:20:01Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
Although ResponseController is a complex class, we managed to improve its code significantly through refactoring. We made use of [https://codeclimate.com/ Code Climate] in order to run analysis of our changes against the original Expertiza code. We have managed to reduce the overall complexity of this class from 719 to 581 and duplication from 685 to 410. &lt;br /&gt;
Also one of the major refactoring was performed on &amp;quot;rereview&amp;quot; method. We have managed to reduce its complexity from 129 to 91 by extracting methods.&lt;br /&gt;
&lt;br /&gt;
===='''Original ResponseController on Codeclimate:&amp;lt;ref&amp;gt;[https://codeclimate.com/github/expertiza/expertiza/ResponseController &amp;lt;/ref&amp;gt;'''====&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-original.png]]&lt;br /&gt;
[[File:rereview-original.png]]&lt;br /&gt;
&lt;br /&gt;
===='''ResponseController on Codeclimate after Refactoring:'''====&lt;br /&gt;
&lt;br /&gt;
[[File:EXP-new.png]]&lt;br /&gt;
[[File:rereview-new.png]]&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-new.png&amp;diff=90662</id>
		<title>File:Rereview-new.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-new.png&amp;diff=90662"/>
		<updated>2014-10-29T19:07:13Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: uploaded a new version of &amp;amp;quot;File:Rereview-new.png&amp;amp;quot;: Reverted to version as of 19:05, 29 October 2014&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-new.png&amp;diff=90661</id>
		<title>File:Rereview-new.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-new.png&amp;diff=90661"/>
		<updated>2014-10-29T19:06:58Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: uploaded a new version of &amp;amp;quot;File:Rereview-new.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90660</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90660"/>
		<updated>2014-10-29T19:06:15Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
Although ResponseController is a complex class, we managed to improve its code significantly through refactoring. We made use of [https://codeclimate.com/ Code Climate] in order to run analysis of our changes against the original Expertiza code. &lt;br /&gt;
&lt;br /&gt;
[[File:EXP-original.png]]&lt;br /&gt;
[[File:rereview-original.png]]&lt;br /&gt;
[[File:EXP-new.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:rereview-new.png]]&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-new.png&amp;diff=90659</id>
		<title>File:Rereview-new.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-new.png&amp;diff=90659"/>
		<updated>2014-10-29T19:05:56Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: uploaded a new version of &amp;amp;quot;File:Rereview-new.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-original.png&amp;diff=90657</id>
		<title>File:Rereview-original.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-original.png&amp;diff=90657"/>
		<updated>2014-10-29T19:02:37Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: uploaded a new version of &amp;amp;quot;File:Rereview-original.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-original.png&amp;diff=90656</id>
		<title>File:Rereview-original.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-original.png&amp;diff=90656"/>
		<updated>2014-10-29T19:01:02Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: uploaded a new version of &amp;amp;quot;File:Rereview-original.png&amp;amp;quot;: Reverted to version as of 18:50, 29 October 2014&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-original.png&amp;diff=90655</id>
		<title>File:Rereview-original.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-original.png&amp;diff=90655"/>
		<updated>2014-10-29T19:00:23Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: uploaded a new version of &amp;amp;quot;File:Rereview-original.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:EXP-new.png&amp;diff=90651</id>
		<title>File:EXP-new.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:EXP-new.png&amp;diff=90651"/>
		<updated>2014-10-29T18:58:26Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:EXP-original.png&amp;diff=90650</id>
		<title>File:EXP-original.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:EXP-original.png&amp;diff=90650"/>
		<updated>2014-10-29T18:58:08Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-new.png&amp;diff=90648</id>
		<title>File:Rereview-new.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-new.png&amp;diff=90648"/>
		<updated>2014-10-29T18:51:00Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-original.png&amp;diff=90647</id>
		<title>File:Rereview-original.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Rereview-original.png&amp;diff=90647"/>
		<updated>2014-10-29T18:50:37Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Expertiza-new.png&amp;diff=90646</id>
		<title>File:Expertiza-new.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Expertiza-new.png&amp;diff=90646"/>
		<updated>2014-10-29T18:50:14Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90642</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90642"/>
		<updated>2014-10-29T18:43:28Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90504</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90504"/>
		<updated>2014-10-29T14:47:35Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Expertiza-original.png&amp;diff=90501</id>
		<title>File:Expertiza-original.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Expertiza-original.png&amp;diff=90501"/>
		<updated>2014-10-29T14:43:23Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90500</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=90500"/>
		<updated>2014-10-29T14:39:56Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. It supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions, finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89845</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89845"/>
		<updated>2014-10-27T04:01:49Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* External Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.46.19.211:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/sjoshi6/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89843</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89843"/>
		<updated>2014-10-27T03:54:50Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Removal of redundant methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
Edit method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def edit&lt;br /&gt;
    @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
    @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
    @return = params[:return]&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map_id==@map.map_id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
    end&lt;br /&gt;
    @response = Response.where(map_id: @map.map_id, version_num:  @largest_version_num.version_num).first&lt;br /&gt;
    @modified_object = @response.response_id&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
    # Check whether this is a custom rubric&lt;br /&gt;
    if @map.questionnaire.section.eql? &amp;quot;Custom&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;custom_update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      # end of special code (except for the end below, to match the if above)&lt;br /&gt;
      #**********************&lt;br /&gt;
      render :action =&amp;gt; 'response'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
New_feedback method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def new_feedback&lt;br /&gt;
    review = Response.find(params[:id])&lt;br /&gt;
    if review&lt;br /&gt;
      reviewer = AssignmentParticipant.where(user_id: session[:user].id, parent_id:  review.map.assignment.id).first&lt;br /&gt;
      map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id:  reviewer.id).first&lt;br /&gt;
      if map.nil?&lt;br /&gt;
        map = FeedbackResponseMap.create(:reviewed_object_id =&amp;gt; review.id, :reviewer_id =&amp;gt; reviewer.id, :reviewee_id =&amp;gt; review.map.reviewer.id)&lt;br /&gt;
      end&lt;br /&gt;
      redirect_to :action =&amp;gt; 'new', :id =&amp;gt; map.map_id, :return =&amp;gt; &amp;quot;feedback&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
      redirect_to :back&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
View method:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def view&lt;br /&gt;
    @response = Response.find(params[:id])&lt;br /&gt;
    return if redirect_when_disallowed(@response)&lt;br /&gt;
    @map = @response.map&lt;br /&gt;
    get_content&lt;br /&gt;
    @review_scores = Array.new&lt;br /&gt;
    @question_type = Array.new&lt;br /&gt;
    @questions.each do |question|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; Score.where(response_id: @map.response_id, question_id:  question.id).first&lt;br /&gt;
      @question_type &amp;lt;&amp;lt; QuestionType.find_by_question_id(question.id)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89842</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89842"/>
		<updated>2014-10-27T03:50:14Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''E1458: Expertiza - Refactoring ResponseController'''&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89786</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89786"/>
		<updated>2014-10-27T01:56:20Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Moved methods from Response Controller to appropriate models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89783</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89783"/>
		<updated>2014-10-27T01:55:25Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Creation of a Kludge */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added two methods named 'handle_jace_kludge' and 'check_user_name_jace?'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89782</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89782"/>
		<updated>2014-10-27T01:54:37Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Creation of a Kludge */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def check_user_name_jace?&lt;br /&gt;
    return @assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id&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 handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89779</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89779"/>
		<updated>2014-10-27T01:49:10Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Project Description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the model's responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89778</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89778"/>
		<updated>2014-10-27T01:48:18Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Background */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the  Expertiza project with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89776</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89776"/>
		<updated>2014-10-27T01:44:48Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Refactoring carried out */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the Open Source Software project Expertiza with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was handled by denying incorrect access using the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89775</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89775"/>
		<updated>2014-10-27T01:43:45Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Refactoring carried out */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the Open Source Software project Expertiza with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89773</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89773"/>
		<updated>2014-10-27T01:43:19Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Refactoring carried out */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the Open Source Software project Expertiza with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. &lt;br /&gt;
  It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations.&lt;br /&gt;
* For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89770</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89770"/>
		<updated>2014-10-27T01:39:50Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Creation of a Kludge */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the Open Source Software project Expertiza with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jace’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89769</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89769"/>
		<updated>2014-10-27T01:38:10Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Perform Authorization correctly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the Open Source Software project Expertiza with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was done incorrectly via the redirect_when_disallowed method. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response is applied to, or if they are an instructor or Teaching Assistant for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor and neither the Teaching Assistant for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? method which does the authorization check and allows the user to perform the action only if he/she has the correct permissions.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89762</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89762"/>
		<updated>2014-10-27T01:13:59Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the Open Source Software project Expertiza with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89761</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89761"/>
		<updated>2014-10-27T01:13:39Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
Expertiza[http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the Open Source Software project Expertiza with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89760</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89760"/>
		<updated>2014-10-27T01:12:29Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Expertiza - Refactoring ResponseController */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
Expertiza[1] is a peer review based course management system. Expertiza supports project submission,team creation, and review of the submitted material  including URLs and wiki pages. Students can manage teammates and can conduct reviews on other's topics and projects.&lt;br /&gt;
Expertiza is an open source project based on Ruby on Rails.&lt;br /&gt;
&lt;br /&gt;
== Background==&lt;br /&gt;
As a part of the OSS project 1 we were expected to refactor the Response Controller of Expertiza. Response Controller is responsible for managing the review versions and finding the latest responses and fetching the review scores. This wiki provides a detailed walk through of our contributions to the Open Source Software project Expertiza with a focus on refactoring.&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89754</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89754"/>
		<updated>2014-10-27T00:55:59Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Expertiza - Refactoring ResponseController */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Expertiza==&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
'''redirect_when_disallowed''' Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We replaced the '''redirect_when_disallowed''' Method by '''action_allowed?''' Method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
:1. [http://wikis.lib.ncsu.edu/index.php/Expertiza Expertiza]&lt;br /&gt;
&lt;br /&gt;
:2. [http://152.7.99.43:3000/ VCL Link]&lt;br /&gt;
&lt;br /&gt;
:3. [https://github.com/nixtish/expertiza Git repository]&lt;br /&gt;
&lt;br /&gt;
:4. [https://docs.google.com/a/ncsu.edu/document/d/1Z0xjFZu-Zy-xm73YyUVUgFCtfWgRwhN1rZuThoyF-U0/edit Steps to setup Expertiza]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89728</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89728"/>
		<updated>2014-10-27T00:17:58Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Moved methods from Response Controller to appropriate models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
redirect_when_disallowed Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; So we moved it to the '''Response model'''. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Similarly, the logic for determining whether a review is current or not(i.e., the review was done during the current assignment phase) is not a controller's responsibility and thus was moved to the '''Response model'''. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89727</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89727"/>
		<updated>2014-10-27T00:12:58Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Moved methods from Response Controller to appropriate models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
redirect_when_disallowed Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* Sorting review versions is not a controller responsibility; SO we moved it to the '''Response model'''. Similarly, the logic for determining whether a review is current or not(i.e., was done during the current assignment phase) was moved to the Response model from the controller. This is a query that is made about a review (actually, about a response, which may be a review, author feedback, etc.).  It should be placed in the appropriate model class.*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89725</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89725"/>
		<updated>2014-10-27T00:01:32Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Moved methods from Response Controller to appropriate models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
redirect_when_disallowed Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* /*TODO for wiki Sorting review versions is not a controller responsibility; it would be better to do this in a model class (which class?)  Ditto for determining whether a review is current (i.e., was done during the current assignment phase).  This is a query that is made about a review (actually, about a response, which may be a review, author feedback, etc.).  It should be placed in the appropriate model class.*/&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 def self.getAllResponseVersions&lt;br /&gt;
    #get all previous versions of responses for the response map.&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.where(map_id: @map.id)&lt;br /&gt;
&lt;br /&gt;
    @prev.each do |element|&lt;br /&gt;
      @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return @review_scores&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def self.get_largest_version_number(review_scores)&lt;br /&gt;
    @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
    @largest_version_num=@sorted[0]&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89720</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89720"/>
		<updated>2014-10-26T23:58:56Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Cleaning up of the rereview moethod */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
redirect_when_disallowed Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is '''81''' lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #**********************&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* /*TODO for wiki Sorting review versions is not a controller responsibility; it would be better to do this in a model class (which class?)  Ditto for determining whether a review is current (i.e., was done during the current assignment phase).  This is a query that is made about a review (actually, about a response, which may be a review, author feedback, etc.).  It should be placed in the appropriate model class.*/&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89712</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89712"/>
		<updated>2014-10-26T23:52:16Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Creation of a Kludge */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
redirect_when_disallowed Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is ___ lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #**********************&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def handle_jace_kludge&lt;br /&gt;
    # ** if assignment belongs to Jace handle it depending on the assignment id **&lt;br /&gt;
    if @assignment.id &amp;lt; 469&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response'&lt;br /&gt;
    else&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* /*TODO for wiki Sorting review versions is not a controller responsibility; it would be better to do this in a model class (which class?)  Ditto for determining whether a review is current (i.e., was done during the current assignment phase).  This is a query that is made about a review (actually, about a response, which may be a review, author feedback, etc.).  It should be placed in the appropriate model class.*/&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89709</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89709"/>
		<updated>2014-10-26T23:51:28Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Cleaning up of the rereview moethod */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
redirect_when_disallowed Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is ___ lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
   @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @review_scores=response.getAllResponseVersions&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @largest_version_num = Response.get_largest_version_number(@review_scores)&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
&lt;br /&gt;
      @sorted_deadlines = DueDate.sort_deadlines(due_dates)&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.where(map_id: params[:id], version_num:  @largest_version_num.version_num).first&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
          @review_scores &amp;lt;&amp;lt; Score.where(response_id: @response.response_id, question_id:  question.id).first&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      # Check whether this is Jace's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
          handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (check_user_name_jace? &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;)&lt;br /&gt;
        handle_jace_kludge&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #**********************&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Code snippet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* /*TODO for wiki Sorting review versions is not a controller responsibility; it would be better to do this in a model class (which class?)  Ditto for determining whether a review is current (i.e., was done during the current assignment phase).  This is a query that is made about a review (actually, about a response, which may be a review, author feedback, etc.).  It should be placed in the appropriate model class.*/&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89706</id>
		<title>CSC/ECE 517 Fall 2014/oss E1458 sst</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014/oss_E1458_sst&amp;diff=89706"/>
		<updated>2014-10-26T23:46:09Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: /* Perform Authorization correctly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Expertiza - Refactoring ResponseController=&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
&lt;br /&gt;
The response controller allows the user to create and edit responses to questionnaires such as performing a review, rating a teammate or giving feedback to a reviewer.&lt;br /&gt;
Our project requirement was to perform the following changes :&lt;br /&gt;
* Perform authorization properly.&lt;br /&gt;
* Remove the duplicated methods.&lt;br /&gt;
* Reduce the complexity of the rereview method.&lt;br /&gt;
* Move the functionality incorporated in the controller, to the model, as it is the models responsibility to implement this functionality.&lt;br /&gt;
&lt;br /&gt;
==Refactoring carried out==&lt;br /&gt;
&lt;br /&gt;
The following changes have been made in the project, as described in the requirements document.&lt;br /&gt;
&lt;br /&gt;
===Perform Authorization correctly===&lt;br /&gt;
&lt;br /&gt;
* Authorization to perform actions was not checked correctly. It is supposed to be done through the action_allowed? method at the beginning of the class definition. Different authorizations are required for different operations. For example, someone should be allowed to view a response if they wrote the response, or they are the person or on the team whose work the response applied to, or if they are an instructor or TA for the class.  The person who wrote a response should be allowed to edit it, but not the person/team who was being reviewed, nor the instructor or TA for the class.&lt;br /&gt;
* Earlier, the authorization was denied by the redirect_when_disallowed method, which was a more error-prone way of controlling access.  This method has now been removed, and now the class has an action_allowed? Method which does the authorization check and allows the user to perform the action if it is allowed.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
redirect_when_disallowed Method was used for authorization purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def redirect_when_disallowed(response)&lt;br /&gt;
    # For author feedback, participants need to be able to read feedback submitted by other teammates.&lt;br /&gt;
    # If response is anything but author feedback, only the person who wrote feedback should be able to see it.&lt;br /&gt;
    if response.map.read_attribute(:type) == 'FeedbackResponseMap' &amp;amp;&amp;amp; response.map.assignment.team_assignment?&lt;br /&gt;
      team = response.map.reviewer.team&lt;br /&gt;
      unless team.has_user session[:user]&lt;br /&gt;
        redirect_to '/denied?reason=You are not on the team that wrote this feedback'&lt;br /&gt;
      else&lt;br /&gt;
        return false&lt;br /&gt;
      end&lt;br /&gt;
      response.map.read_attribute(:type)&lt;br /&gt;
    end&lt;br /&gt;
    !current_user_id?(response.map.reviewer.user_id)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  def action_allowed?&lt;br /&gt;
    case params[:action]&lt;br /&gt;
      when 'view', 'edit', 'delete', 'rereview', 'update'&lt;br /&gt;
        if response.map.read_attribute(:type) == 'FeedbackResponseMap'&lt;br /&gt;
          team = response.map.reviewer.team&lt;br /&gt;
          if team.has_user session[:user]&lt;br /&gt;
           flag= true&lt;br /&gt;
          else&lt;br /&gt;
            flag=false&lt;br /&gt;
          end&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        flag=true&lt;br /&gt;
    end&lt;br /&gt;
    return flag&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Removal of redundant methods===&lt;br /&gt;
&lt;br /&gt;
* There were two copies of the '''edit, new_feedback and view methods'''.  The second being the newer one, and, according to the rules for method definition, is the one that is currently in use because the latest version overrides the previous versions. We refactored the code by removing the redundant methods for edit, new_feedback and view.&lt;br /&gt;
&lt;br /&gt;
===Cleaning up of the rereview moethod===&lt;br /&gt;
* The rereview method was 98 lines long. We refactored the code by turning several parts of it into methods. Now the code is ___ lines long.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def rereview&lt;br /&gt;
    @map=ResponseMap.find(params[:id])&lt;br /&gt;
    get_content&lt;br /&gt;
    array_not_empty=0&lt;br /&gt;
    @review_scores=Array.new&lt;br /&gt;
    @prev=Response.all&lt;br /&gt;
    #get all versions and find the latest version&lt;br /&gt;
    for element in @prev&lt;br /&gt;
      if (element.map.id==@map.map.id)&lt;br /&gt;
        array_not_empty=1&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; element&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    latestResponseVersion&lt;br /&gt;
    #sort all the available versions in descending order.&lt;br /&gt;
    if @prev.present?&lt;br /&gt;
      @sorted=@review_scores.sort { |m1, m2| (m1.version_num and m2.version_num) ? m2.version_num &amp;lt;=&amp;gt; m1.version_num : (m1.version_num ? -1 : 1) }&lt;br /&gt;
      @largest_version_num=@sorted[0]&lt;br /&gt;
      @latest_phase=@largest_version_num.created_at&lt;br /&gt;
      due_dates = DueDate.where([&amp;quot;assignment_id = ?&amp;quot;, @assignment.id])&lt;br /&gt;
      @sorted_deadlines=Array.new&lt;br /&gt;
      @sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m1.due_at &amp;lt;=&amp;gt; m2.due_at : (m1.due_at ? -1 : 1) }&lt;br /&gt;
      current_time=Time.new.getutc&lt;br /&gt;
      #get the highest version numbered review&lt;br /&gt;
      next_due_date=@sorted_deadlines[0]&lt;br /&gt;
      #check in which phase the latest review was done.&lt;br /&gt;
      for deadline_version in @sorted_deadlines&lt;br /&gt;
        if (@largest_version_num.created_at &amp;lt; deadline_version.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
      for deadline_time in @sorted_deadlines&lt;br /&gt;
        if (current_time &amp;lt; deadline_time.due_at)&lt;br /&gt;
          break&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
    #check if the latest review is done in the current phase.&lt;br /&gt;
    #if latest review is in current phase then edit the latest one.&lt;br /&gt;
    #else create a new version and update it.&lt;br /&gt;
    # editing the latest review&lt;br /&gt;
    if (deadline_version.due_at== deadline_time.due_at)&lt;br /&gt;
      #send it to edit here&lt;br /&gt;
      @header = &amp;quot;Edit&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @response = Response.find_by_map_id_and_version_num(params[:id], @largest_version_num.version_num)&lt;br /&gt;
      return if redirect_when_disallowed(@response)&lt;br /&gt;
      @modified_object = @response.response_id&lt;br /&gt;
      @map = @response.map&lt;br /&gt;
      get_content&lt;br /&gt;
      @review_scores = Array.new&lt;br /&gt;
      @questions.each {&lt;br /&gt;
          |question|&lt;br /&gt;
        @review_scores &amp;lt;&amp;lt; Score.find_by_response_id_and_question_id(@response.response_id, question.id)&lt;br /&gt;
      }&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end&lt;br /&gt;
    else&lt;br /&gt;
      #else create a new version and update it.&lt;br /&gt;
      @header = &amp;quot;New&amp;quot;&lt;br /&gt;
      @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
      @feedback = params[:feedback]&lt;br /&gt;
      @map = ResponseMap.find(params[:id])&lt;br /&gt;
      @return = params[:return]&lt;br /&gt;
      @modified_object = @map.map_id&lt;br /&gt;
      get_content&lt;br /&gt;
      #**********************&lt;br /&gt;
      # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;create&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&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;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Code snippet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Creation of a Kludge===&lt;br /&gt;
&lt;br /&gt;
* The rereview method contained a special code to check whether an assignment is “Jen’s assignment”; this was the first assignment that was ever created with a multipart rubric.  It was hard-coded into the system, rather than working on a rubric that was created in the normal way.  It is impossible to remove this code without breaking that assignment. It is now implemented as a separate method named handle_jace_kludge.&lt;br /&gt;
&lt;br /&gt;
Before Refactoring:&lt;br /&gt;
&lt;br /&gt;
The following code was present in the rereview method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #**********************&lt;br /&gt;
 # Check whether this is Jen's assgt. &amp;amp; if so, use her rubric&lt;br /&gt;
      if (@assignment.instructor_id == User.find_by_name(&amp;quot;jace_smith&amp;quot;).id) &amp;amp;&amp;amp; @title == &amp;quot;Review&amp;quot;&lt;br /&gt;
        if @assignment.id &amp;lt; 469&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response'&lt;br /&gt;
        else&lt;br /&gt;
          @next_action = &amp;quot;update&amp;quot;&lt;br /&gt;
          render :action =&amp;gt; 'custom_response_2011'&lt;br /&gt;
        end&lt;br /&gt;
      else&lt;br /&gt;
        # end of special code (except for the end below, to match the if above)&lt;br /&gt;
        #**********************&lt;br /&gt;
        render :action =&amp;gt; 'response'&lt;br /&gt;
      end     &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After Refactoring:&lt;br /&gt;
&lt;br /&gt;
We added a method named 'handle_jace_kludge'.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Code snippet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Moved methods from Response Controller to appropriate models===&lt;br /&gt;
&lt;br /&gt;
* /*TODO for wiki Sorting review versions is not a controller responsibility; it would be better to do this in a model class (which class?)  Ditto for determining whether a review is current (i.e., was done during the current assignment phase).  This is a query that is made about a review (actually, about a response, which may be a review, author feedback, etc.).  It should be placed in the appropriate model class.*/&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014&amp;diff=89688</id>
		<title>CSC/ECE 517 Fall 2014</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014&amp;diff=89688"/>
		<updated>2014-10-26T23:16:27Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[CSC/ECE_517_Fall_2014/sample_page]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a 22 as]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 19 mx]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 3 zq]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 4 lf]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 4 wl]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a a7 ch]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 25 rs]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 25 jf]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 8 os]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 8 sn]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 15 gs]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 10 hu]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 20 kv]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 21 as]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 24 sa]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 26 sn]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 6 rl]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 2 ss]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 16 av]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 1 rm]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 1 sj]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 23 ss]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 20 rn]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 22 sp]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 26 gn]]&lt;br /&gt;
&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 13 va]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 9 aa]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 9 kn]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 11 ap]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 25 ks]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 7 kz]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a_6_bn]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a 10 zz]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a 16 va]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a F1415 rv]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a_3_cp]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1b 26 sa]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b_28_cg]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b 29 ry]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b 30 cs]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b_33_jy]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b_27_js]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/oss E1465 oak]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/oss_M1456_kdv]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/oss_E1456_akk]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/oss_M1455_asa]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/oss_E1458_sst]]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014&amp;diff=89683</id>
		<title>CSC/ECE 517 Fall 2014</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2014&amp;diff=89683"/>
		<updated>2014-10-26T23:03:28Z</updated>

		<summary type="html">&lt;p&gt;Tmainka: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[CSC/ECE_517_Fall_2014/sample_page]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a 22 as]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 19 mx]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 3 zq]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 4 lf]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 4 wl]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a a7 ch]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 25 rs]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 25 jf]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 8 os]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 8 sn]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 15 gs]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 10 hu]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 20 kv]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 21 as]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 24 sa]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 26 sn]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 6 rl]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 2 ss]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 16 av]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 1 rm]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 1 sj]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 23 ss]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 20 rn]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 22 sp]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 26 gn]]&lt;br /&gt;
&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 13 va]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 9 aa]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 9 kn]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 11 ap]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 25 ks]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1a 7 kz]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a_6_bn]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a 10 zz]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a 16 va]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a F1415 rv]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1a_3_cp]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/ch1b 26 sa]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b_28_cg]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b 29 ry]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b 30 cs]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b_33_jy]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/ch1b_27_js]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/oss E1465 oak]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/oss_M1456_kdv]]&lt;br /&gt;
*[[CSC/ECE 517 Fall 2014/oss_E1456_akk]]&lt;br /&gt;
*[[CSC/ECE_517_Fall_2014/oss_M1455_asa]]&lt;br /&gt;
*[[CSC/ECE_517 Fall 2014/oss_E1458_sts]]&lt;/div&gt;</summary>
		<author><name>Tmainka</name></author>
	</entry>
</feed>