|
|
Line 4: |
Line 4: |
| The project involved refactoring some parts of the controller to incorporate the OODD principles so that the readability of code could be improved. | | The project involved refactoring some parts of the controller to incorporate the OODD principles so that the readability of code could be improved. |
|
| |
|
| ==Introduction to Expertiza== | | ==About Expertiza== |
| [http://expertiza.ncsu.edu/ Expertiza] is a peer review based system which provides incremental learning from the class. This project has been developed together by faculty and students using [http://rubyonrails.org/ Ruby on Rails] framework. Expertiza allows the instructor to create, edit and delete assignments, create new assignment topics, assign them to a particular class or selected students, have students work on teams and then review each other's assignments at the end. For the students, they can signup for topics, form teams, and submit their projects and assignments. | | The [http://expertiza.ncsu.edu/ Expertiza] platform employs a divide-and-conquer strategy for creating reusable learning objects via active-learning exercises built entirely on [http://rubyonrails.org/ Ruby on Rails] framework. Students get to choose from a list of tasks to complete either individually or in teams. They then prepare their work and submit it to a peer-review mechanism. On submission, other students can assess their peers work and provide feedback. Expertiza encourages students to collaborate in order to improve the learning experiences from one another. It aids their learning by making them translate what is taught in the lectures and apply those concepts to a real-world issue. |
| Students then review the work done by other students and give suggestions to improve. Teams after reviews are allotted scores and they can refer to the peer comments to further improve their work. It also supports submission of different file types for assignments, including the URLs and wiki pages.
| |
|
| |
|
| == Project Description == | | == Project Description == |
| '''submitted_content_Controller''' had some problems that violate some essential Rails design principles which needed to be rectified. There are few methods in this controller that are far too long and need to be broken down into multiple methods. A few methods need to be commented as well. Few Methods need to be renamed. | | '''submitted_content_Controller''' had some problems that violate essential Rails design principles which needed to be rectified. Issues included some methods being too long which needed to be broken down, a few methods needed better naming and a few that were no longer needed. |
|
| |
|
|
| |
| ===Create Method===
| |
| The method '''Create''' is called when an instructor tries to create a team manually. This works for both, creating ''assignment teams'' and ''course teams''. Assignment teams are teams made to do a particular assignment together and ''Course Teams'' are teams which are made for the whole course.
| |
|
| |
| ===Delete Method===
| |
| The method '''Delete''' is called when an instructor tries to delete a team manually. This works for both, deleting ''assignment teams'' and ''course teams''.
| |
|
| |
| ===List Method===
| |
| The method '''List''' lists all the team nodes and the instructor is able to expand each team node to see the user nodes as well.
| |
|
| |
| ===Inherit Method===
| |
| The method '''Inherit''' inherits teams from course to assignments, but the “Inherit Teams From Course” option should not display when either 1) we are editing a course object or 2) the current assignment object does not have a course associated with it.
| |
|
| |
| ===Running Tests===
| |
| rspec spec/controllers/submitted_content_controller_spec.rb
| |
|
| |
| ===Files Modified===
| |
| 1. teams_controller.rb
| |
| 2. team.rb
| |
| 3. signed_up_team.rb
| |
| 4. routes.rb
| |
| 5. app/views/teams/new.html.erb
| |
|
| |
| == Refactoring ==
| |
| [https://en.wikipedia.org/wiki/Code_refactoring '''Refactoring'''] is restructuring of code without the need of changing any external behavior. It reduces complexity and improves readability. It also becomes easy to extend the application with respect to different modules and their functionalities.
| |
| Some common techniques to refactor are:
| |
|
| |
| * Moving methods to appropriate modules
| |
| * Breaking methods into more meaningful functionality
| |
| * Creating more generalized code.
| |
| * Renaming methods and variable.
| |
| * Inheritance
| |
|
| |
| == Tasks ==
| |
|
| |
| ===Refactoring delete method===
| |
| Description: The delete method manipulates a waitlist. This code is moved to signed_up_team.rb model class.
| |
|
| |
| Initially, the code was:
| |
|
| |
| def delete
| |
| # delete records in team, teams_users, signed_up_teams table
| |
| @team = Team.find_by(id: params[:id])
| |
| unless @team.nil?
| |
| course = Object.const_get(session[:team_type]).find(@team.parent_id)
| |
| @signed_up_team = SignedUpTeam.where(team_id: @team.id)
| |
| @teams_users = TeamsUser.where(team_id: @team.id)
| |
| if @signed_up_team == 1 && !@signUps.first.is_waitlisted # this team hold a topic
| |
| # if there is another team in waitlist, make this team hold this topic
| |
| topic_id = @signed_up_team.first.topic_id
| |
| next_wait_listed_team = SignedUpTeam.where(topic_id: topic_id, is_waitlisted: true).first
| |
| # if slot exist, then confirm the topic for this team and delete all waitlists for this team
| |
| SignUpTopic.assign_to_first_waiting_team(next_wait_listed_team) if next_wait_listed_team
| |
| end
| |
| @sign_up_team.destroy_all if @sign_up_team
| |
| @teams_users.destroy_all if @teams_users
| |
| @team.destroy if @team
| |
| undo_link("The team \"#{@team.name}\" has been successfully deleted.")
| |
| end
| |
| redirect_to :back
| |
| end
| |
|
| |
| Which was changed to:
| |
|
| |
| def delete
| |
| # delete records in team, teams_users, signed_up_teams table
| |
| @team = Team.find_by(id: params[:id])
| |
| unless @team.nil?
| |
| course = Object.const_get(session[:team_type]).find(@team.parent_id)
| |
| @signed_up_team = SignedUpTeam.where(team_id: @team.id)
| |
| @teams_users = TeamsUser.where(team_id: @team.id)
| |
| # On team deletion topic team was holding will be assigned to first team in waitlist.
| |
| SignedUpTeam.assign_topic_to_first_in_waitlist_post_team_deletion(@signed_up_team, @signups)
| |
| @sign_up_team.destroy_all if @sign_up_team
| |
| @teams_users.destroy_all if @teams_users
| |
| @team.destroy if @team
| |
| undo_link("The team \"#{@team.name}\" has been successfully deleted.")
| |
| end
| |
| redirect_to :back
| |
| end
| |
|
| |
| and a new method was introduced in signed_up_team.rb model:
| |
| # this method checks when a team is deleted if there is a team in waitlist for the topic
| |
| # deleted team was holding, then assign topic to first team in waitlist
| |
| def self.assign_topic_to_first_in_waitlist_post_team_deletion (signed_up_team, signups)
| |
| if signed_up_team == 1 && !signups.first.is_waitlisted # this team hold a topic
| |
| # if there is another team in waitlist, make this team hold this topic
| |
| topic_id = signed_up_team.first.topic_id
| |
| next_wait_listed_team = SignedUpTeam.where(topic_id: topic_id, is_waitlisted: true).first
| |
| # if slot exist, then confirm the topic for this team and delete all waitlists for this team
| |
| SignUpTopic.assign_to_first_waiting_team(next_wait_listed_team) if next_wait_listed_team
| |
| end
| |
| end
| |
|
| |
| ===Refactoring inherit method===
| |
|
| |
| Description: The code that copies a list is moved to team.rb model class.
| |
|
| |
| Initially, the code was:
| |
| def inherit
| |
| assignment = Assignment.find(params[:id])
| |
| if assignment.course_id >= 0
| |
| course = Course.find(assignment.course_id)
| |
| teams = course.get_teams
| |
| unless teams.empty?
| |
| teams.each do |team|
| |
| team.copy(assignment.id)
| |
| end
| |
| else
| |
| flash[:note] = "No teams were found when trying to inherit."
| |
| end
| |
| else
| |
| flash[:error] = "No course was found for this assignment."
| |
| end
| |
| redirect_to controller: 'teams', action: 'list', id: assignment.id
| |
| end
| |
|
| |
| Which was changed to:
| |
| def inherit
| |
| assignment = Assignment.find(params[:id])
| |
| if assignment.course_id >= 0
| |
| course = Course.find(assignment.course_id)
| |
| teams = course.get_teams
| |
| unless teams.empty?
| |
| # copy_assignment method copies teams to assignment
| |
| Team.copy_assignment(teams,assignment)
| |
| else
| |
| flash[:note] = "No teams were found when trying to inherit."
| |
| end
| |
| else
| |
| flash[:error] = "No course was found for this assignment."
| |
| end
| |
| redirect_to controller: 'teams', action: 'list', id: assignment.id
| |
| end
| |
|
| |
| and a new method was introduced in team.rb model:
| |
| def self.copy_assignment(teams,assignment)
| |
| teams.each do |team|
| |
| team.copy(assignment.id)
| |
| end
| |
| end
| |
|
| |
| ===Refactoring create method===
| |
|
| |
| Description: It creates new teams against a parent id
| |
|
| |
| Initially the create method was:
| |
|
| |
| def create
| |
| parent = Object.const_get(session[:team_type]).find(params[:id])
| |
| begin
| |
| Team.check_for_existing(parent, params[:team][:name], session[:team_type])
| |
| @team = Object.const_get(session[:team_type] + 'Team').create(name: params[:team][:name], parent_id: parent.id)
| |
| TeamNode.create(parent_id: parent.id, node_object_id: @team.id)
| |
| undo_link("The team \"#{@team.name}\" has been successfully created.")
| |
| redirect_to action: 'list', id: parent.id
| |
| rescue TeamExistsError
| |
| flash[:error] = $ERROR_INFO
| |
| redirect_to action: 'new', id: parent.id
| |
| end
| |
| end
| |
|
| |
| Which changed to:
| |
|
| |
| def create
| |
| begin
| |
| parent = get_parent_and_check_if_exists(params[:id])
| |
| @team = Object.const_get(session[:team_type] + 'Team').create(name: params[:team][:name], parent_id: parent.id)
| |
| TeamNode.create(parent_id: parent.id, node_object_id: @team.id)
| |
| undo_link("The team \"#{@team.name}\" has been successfully created.")
| |
| redirect_to action: 'list', id: parent.id
| |
| rescue TeamExistsError
| |
| flash_and_redirect_on_update_or_create_error('new', parent_id)
| |
| end
| |
| end
| |
|
| |
| # called to fetch parent and check if team with same name and type already exists.
| |
| def get_parent_and_check_if_exists(parent_id)
| |
| parent = Object.const_get(session[:team_type]).find(parent_id)
| |
| Team.check_for_existing(parent, params[:team][:name], session[:team_type])
| |
| return parent
| |
| end
| |
|
| |
| # to flash and redirect the user when there is any update or create error
| |
| def flash_and_redirect_on_update_or_create_error(action, id)
| |
| flash[:error] = $ERROR_INFO
| |
| redirect_to action: action, id: id
| |
| end
| |
|
| |
| ===Refactoring update method===
| |
|
| |
| Description: It updates an existing team name
| |
|
| |
| Initially the update method was:
| |
|
| |
| def update
| |
| @team = Team.find(params[:id])
| |
| parent = Object.const_get(session[:team_type]).find(@team.parent_id)
| |
| begin
| |
| Team.check_for_existing(parent, params[:team][:name], session[:team_type])
| |
| @team.name = params[:team][:name]
| |
| @team.save
| |
| flash[:success] = "The team \"#{@team.name}\" has been successfully updated."
| |
| undo_link("")
| |
| redirect_to action: 'list', id: parent.id
| |
| rescue TeamExistsError
| |
| flash[:error] = $ERROR_INFO
| |
| redirect_to action: 'edit', id: @team.id
| |
| end
| |
| end
| |
|
| |
| Which changed to:
| |
|
| |
| # It updates an existing team name
| |
| def update
| |
| @team = Team.find(params[:id])
| |
| begin
| |
| parent = get_parent_and_check_if_exists(@team.parent_id)
| |
| @team.name = params[:team][:name]
| |
| @team.save
| |
| flash[:success] = "The team \"#{@team.name}\" has been successfully updated."
| |
| undo_link("")
| |
| redirect_to action: 'list', id: parent.id
| |
| rescue TeamExistsError
| |
| flash_and_redirect_on_update_or_create_error('edit', @team.id)
| |
| end
| |
| end
| |
|
| |
| # called to fetch parent and check if team with same name and type already exists.
| |
| def get_parent_and_check_if_exists(parent_id)
| |
| parent = Object.const_get(session[:team_type]).find(parent_id)
| |
| Team.check_for_existing(parent, params[:team][:name], session[:team_type])
| |
| return parent
| |
| end
| |
|
| |
| # to flash and redirect the user when there is any update or create error
| |
| def flash_and_redirect_on_update_or_create_error(action, id)
| |
| flash[:error] = $ERROR_INFO
| |
| redirect_to action: action, id: id
| |
| end
| |
|
| |
|
| |
| ===Create Teams===
| |
|
| |
| The new method self.create_teams() is created in Team.rb model and placed the common of create_teams method.
| |
| # This function is used to create teams with random names.
| |
| # Instructors can call by clicking "Create temas" icon anc then click "Create teams" at the bottom.
| |
| def self.create_teams(session,params)
| |
| parent = Object.const_get(session[:team_type]).find(params[:id])
| |
| Team.randomize_all_by_parent(parent, session[:team_type], params[:team_size].to_i)
| |
| end
| |
|
| |
| Exiting code of create_teams() method in teams_controller.rb
| |
|
| |
| # This function is used to create teams with random names.
| |
| # Instructors can call by clicking "Create temas" icon anc then click "Create teams" at the bottom.
| |
| def create_teams
| |
| parent = Object.const_get(session[:team_type]).find(params[:id])
| |
| Team.randomize_all_by_parent(parent, session[:team_type], params[:team_size].to_i)
| |
| undo_link("Random teams have been successfully created.")
| |
| ExpertizaLogger.info LoggerMessage.new(controller_name, '', 'Random teams have been successfully created', request)
| |
| redirect_to action: 'list', id: parent.id
| |
| end
| |
|
| |
| Modified the teams_controller.rb file and it is now using the Team.create_teams(session,params) present in Team.rb model to create teams.
| |
|
| |
| # This function is used to create teams with random names.
| |
| # Instructors can call by clicking "Create temas" icon anc then click "Create teams" at the bottom.
| |
| def create_teams
| |
| Team.create_teams(session,params)
| |
| undo_link("Random teams have been successfully created.")
| |
| ExpertizaLogger.info LoggerMessage.new(controller_name, '', 'Random teams have been successfully created', request)
| |
| redirect_to action: 'list', id: parent.id
| |
| end
| |
|
| |
| ===signUps should be signups===
| |
| Existing code for the signUps nouns are modified to signups.
| |
|
| |
| Existing code teams_controller.rb
| |
|
| |
| def delete
| |
| # delete records in team, teams_users, signed_up_teams table
| |
| @team = Team.find_by(id: params[:id])
| |
| unless @team.nil?
| |
| course = Object.const_get(session[:team_type]).find(@team.parent_id)
| |
| @signed_up_team = SignedUpTeam.where(team_id: @team.id)
| |
| @teams_users = TeamsUser.where(team_id: @team.id)
| |
|
| |
| SignedUpTeam.assign_topic_to_first_in_waitlist_post_team_deletion(@signed_up_team, @signUps)
| |
|
| |
| @sign_up_team.destroy_all if @sign_up_team
| |
| @teams_users.destroy_all if @teams_users
| |
| @team.destroy if @team
| |
| undo_link("The team \"#{@team.name}\" has been successfully deleted.")
| |
| end
| |
| redirect_to :back
| |
| end
| |
|
| |
| Modified code in teams_controller.rb
| |
|
| |
| def delete
| |
| # delete records in team, teams_users, signed_up_teams table
| |
| @team = Team.find_by(id: params[:id])
| |
| unless @team.nil?
| |
| course = Object.const_get(session[:team_type]).find(@team.parent_id)
| |
| @signed_up_team = SignedUpTeam.where(team_id: @team.id)
| |
| @teams_users = TeamsUser.where(team_id: @team.id)
| |
|
| |
| SignedUpTeam.assign_topic_to_first_in_waitlist_post_team_deletion(@signed_up_team, @signups)
| |
|
| |
| @sign_up_team.destroy_all if @sign_up_team
| |
| @teams_users.destroy_all if @teams_users
| |
| @team.destroy if @team
| |
| undo_link("The team \"#{@team.name}\" has been successfully deleted.")
| |
| end
| |
| redirect_to :back
| |
| end
| |
|
| |
| Existing code signed_up_team.rb
| |
|
| |
| def self.assign_topic_to_first_in_waitlist_post_team_deletion (signed_up_team, signUps)
| |
| if signed_up_team == 1 && !signups.first.is_waitlisted # this team hold a topic
| |
| # if there is another team in waitlist, make this team hold this topic
| |
| topic_id = signed_up_team.first.topic_id
| |
| next_wait_listed_team = SignedUpTeam.where(topic_id: topic_id, is_waitlisted: true).first
| |
| # if slot exist, then confirm the topic for this team and delete all waitlists for this team
| |
| SignUpTopic.assign_to_first_waiting_team(next_wait_listed_team) if next_wait_listed_team
| |
| end
| |
| end
| |
|
| |
| Modified code in signed_up_team.rb
| |
|
| |
| def self.assign_topic_to_first_in_waitlist_post_team_deletion (signed_up_team, signups)
| |
| if signed_up_team == 1 && !signups.first.is_waitlisted # this team hold a topic
| |
| # if there is another team in waitlist, make this team hold this topic
| |
| topic_id = signed_up_team.first.topic_id
| |
| next_wait_listed_team = SignedUpTeam.where(topic_id: topic_id, is_waitlisted: true).first
| |
| # if slot exist, then confirm the topic for this team and delete all waitlists for this team
| |
| SignUpTopic.assign_to_first_waiting_team(next_wait_listed_team) if next_wait_listed_team
| |
| end
| |
| end
| |
|
| |
| == Testing the submitted_content_controller ==
| |
|
| |
| === Instructions for testing Rspecs ===
| |
|
| |
| 1. git clone https://github.com/Neelkanth7/expertiza.git
| |
|
| |
| 2. Change to the expertiza directory and then perform "bundle install" and rake db:migrate.
| |
|
| |
| 3. Start the rails server
| |
|
| |
| 4. In a new terminal and in the expertiza directory, perform the following commands:
| |
| i. rspec spec/controllers/submitted_content_controller_spec.rb
| |
|
| |
|
| |
|
| |
| ===Testing Inherit Method===
| |
|
| |
|
| |
| ===Testing Create Method===
| |
|
| |
|
| |
| ===Testing Delete Method===
| |
|
| |
|
| |
| ===Testing List Method===
| |
|
| |
|
|
| |
|