class RubricsController

Constants

NUM_LEVELS

max number of rubric levels allowed

Public Instance Methods

add_csv_criterion(values, levels, assignment) click to toggle source
# File lib/benchmarking/submission_files/rubrics_controller.rb, line 204
def add_csv_criterion(values, levels, assignment)
 #must have at least 2 values - name and weight
 return nil if values.length < 2
 criterion = RubricCriterion.new
 criterion.assignment = assignment
 criterion.rubric_criterion_name = values.shift
 criterion.weight = values.shift
 criterion.position = assignment.rubric_criteria.maximum('position') + 1
 create_levels(criterion, levels)
 #the rest of the values are level descriptions
 values.each_with_index do |value, index|
   criterion['level_' + index.to_s + '_description'] = value
 end
 return nil if !criterion.valid? || !criterion.save
 criterion
end
create() click to toggle source
# File app/controllers/rubrics_controller.rb, line 28
def create
  @assignment = Assignment.find(params[:assignment_id])
  @criteria = @assignment.rubric_criteria
  if @criteria.length > 0
    new_position = @criteria.last.position + 1
  else
    new_position = 1
  end
  @criterion = RubricCriterion.new
  @criterion.assignment = @assignment
  @criterion.weight = RubricCriterion::DEFAULT_WEIGHT
  @criterion.set_default_levels
  @criterion.position = new_position
  unless @criterion.update_attributes(params[:rubric_criterion])
    @errors = @criterion.errors
    render :add_criterion_error
    return
  end
  @criteria.reload
  render :create_and_edit
end
create_csv_rubric(assignment) click to toggle source
# File lib/benchmarking/submission_files/rubrics_controller.rb, line 78
def create_csv_rubric(assignment)
  csv_string = FasterCSV.generate do |csv|
    #first line is level names
    levels_array = get_level_names(assignment)
    csv << levels_array
    assignment.rubric_criteria.each do |criterion|
      criterion_array = [criterion.rubric_criterion_name,criterion.weight]
      (0..NUM_LEVELS - 1).each do |i|
        criterion_array.push(criterion['level_' + i.to_s + '_description'])
      end
      csv << criterion_array
    end
  end
  csv_string
end
create_levels(criterion, levels) click to toggle source
# File lib/benchmarking/submission_files/rubrics_controller.rb, line 221
def create_levels(criterion, levels)
 levels.each_with_index do |level, index|
   criterion['level_' + index.to_s + '_name'] = level
 end
   criterion.save
end
create_yml_rubric(assignment) click to toggle source
# File lib/benchmarking/submission_files/rubrics_controller.rb, line 94
def create_yml_rubric(assignment)
  #we reconstruct a yaml object representing a rubric which is
  # {levels => array, criteria => array}
  yml_string = ''
  #need to get the level names from the first criterion
  levels_array = get_level_names(assignment)

  #this will store all the criteria objects
  criteria_array = []
  assignment.rubric_criteria.each do |criterion|
     #for each criterion we need to reconstruct a yaml object which is
     # {title => string, weight => int, levels => array}

     #get the level_descriptions
     level_descriptions = {}
     (0..NUM_LEVELS - 1).each do |i|
       level_descriptions[i]= criterion['level_' + i.to_s + '_description']
     end

     #this creates the yaml object for a criterion and adds it to the array
     criteria_array.push({'title' => criterion.rubric_criterion_name,
        'weight' => criterion.weight,
        'levels' => level_descriptions})
  end

  #call to_yaml to generate yaml string for the rubric
  #TODO/FIXME: find a better way to create yaml as to_yaml puts everything in a
  # (seemingly) random order.
  yml_string << {'levels' => levels_array, 'criteria' => criteria_array}.to_yaml
  yml_string
end
csv_upload() click to toggle source
# File app/controllers/rubrics_controller.rb, line 71
def csv_upload
  file = params[:csv_upload][:rubric]
  @assignment = Assignment.find(params[:assignment_id])
  encoding = params[:encoding]
  if request.post? && !file.blank?
    begin
      RubricCriterion.transaction do
        invalid_lines = []
        nb_updates = RubricCriterion.parse_csv(file, @assignment, invalid_lines, encoding)
        unless invalid_lines.empty?
          flash[:error] = I18n.t('csv_invalid_lines') + invalid_lines.join(', ')
        end
        if nb_updates > 0
          flash[:notice] = I18n.t('rubric_criteria.upload.success',
            :nb_updates => nb_updates)
        end
      end
    end
  end
  redirect_to :action => 'index', :id => @assignment.id
end
delete() click to toggle source
# File lib/benchmarking/submission_files/rubrics_controller.rb, line 45
def delete
  return unless request.delete?
  @criterion = RubricCriterion.find(params[:id])
   #delete all marks associated with this criterion
  Mark.delete_all(['rubric_criterion_id = :c', {:c => @criterion.id}])
  @criterion.destroy
  flash.now[:success] = I18n.t('criterion_deleted_success')
end
destroy() click to toggle source
# File app/controllers/rubrics_controller.rb, line 50
def destroy
  @criterion = RubricCriterion.find(params[:id])
  @assignment = @criterion.assignment
  @criteria = @assignment.rubric_criteria
  #delete all marks associated with this criterion
  @criterion.destroy
  flash.now[:success] = I18n.t('criterion_deleted_success')
end
download_csv() click to toggle source
# File app/controllers/rubrics_controller.rb, line 59
def download_csv
  @assignment = Assignment.find(params[:assignment_id])
  file_out = RubricCriterion.create_csv(@assignment)
  send_data(file_out, :type => 'text/csv', :filename => "#{@assignment.short_identifier}_rubric_criteria.csv", :disposition => 'inline')
end
download_rubric() click to toggle source
# File lib/benchmarking/submission_files/rubrics_controller.rb, line 54
def download_rubric
   @assignment = Assignment.find(params[:id])
   format = params[:format]
   case format
   when 'csv'
     file_out = create_csv_rubric(@assignment)
   when 'yml'
     file_out = create_yml_rubric(@assignment)
   end
   send_data(file_out, :type => 'text/csv', :disposition => 'inline')
 end
download_yml() click to toggle source
# File app/controllers/rubrics_controller.rb, line 65
def download_yml
   assignment = Assignment.find(params[:assignment_id])
   file_out = assignment.export_rubric_criteria_yml
   send_data(file_out, :type => 'text/plain', :filename => "#{assignment.short_identifier}_rubric_criteria.yml", :disposition => 'inline')
end
edit() click to toggle source
# File app/controllers/rubrics_controller.rb, line 10
def edit
  @criterion = RubricCriterion.find(params[:id])
end
get_level_names(assignment) click to toggle source

given an assignment, return the names of the levels in the assignment’s rubric

# File lib/benchmarking/submission_files/rubrics_controller.rb, line 68
def get_level_names(assignment)
  first_criterion = assignment.rubric_criteria.first
  return nil if first_criterion.nil?
  levels_array = []
  (0..NUM_LEVELS - 1).each do |i|
    levels_array.push(first_criterion['level_' + i.to_s + '_name'])
  end
  levels_array
end
index() click to toggle source
# File app/controllers/rubrics_controller.rb, line 5
def index
  @assignment = Assignment.find(params[:assignment_id])
  @criteria = @assignment.rubric_criteria(:order => 'position')
end
move_criterion() click to toggle source
# File app/controllers/rubrics_controller.rb, line 173
def move_criterion
  position = params[:position].to_i
  if params[:direction] == 'up'
    offset = -1
  elsif  params[:direction] == 'down'
    offset = 1
  else
    render :nothing => true
    return
  end
  @assignment = Assignment.find(params[:assignment_id])
  @criteria = @assignment.rubric_criteria
  criterion = @criteria.find(params[:id])
  index = @criteria.index(criterion)
  other_criterion = @criteria[index + offset]
  if other_criterion.nil?
    render :nothing => true
    return
  end
  position = criterion.position
  criterion.position = index + offset
  other_criterion.position = index
  unless criterion.save and other_criterion.save
    flash[:error] = I18n.t('rubrics.move_criterion.error')
  end
  @criteria.reload
end
new() click to toggle source
# File app/controllers/rubrics_controller.rb, line 23
def new
  @assignment = Assignment.find(params[:assignment_id])
  @criterion = RubricCriterion.new
end
parse_csv_rubric(file, assignment) click to toggle source
# File lib/benchmarking/submission_files/rubrics_controller.rb, line 155
def parse_csv_rubric(file, assignment)
 num_update = 0
 flash[:invalid_lines] = []  # store lines that were not processed
 # read each line of the file and update rubric
 # flag
 first_line = true
 levels = nil
 FasterCSV.parse(file.read) do |row|
  next if FasterCSV.generate_line(row).strip.empty?
  begin
    if first_line #get the row of levels
      levels = row
      first_line = false
    elsif add_csv_criterion(row, levels, assignment) == nil
      raise row.join(',')
    else
      num_update += 1
    end
  rescue RuntimeError => e
    flash[:invalid_lines] << e.message
  end
 end
end
parse_yml_rubric(file, assignment) click to toggle source
# File lib/benchmarking/submission_files/rubrics_controller.rb, line 179
def parse_yml_rubric(file, assignment)
  flash.now[:invalid_lines] = []
  rubric = YAML.load(file.read)
  level_names = rubric['levels']
  criteria = rubric['criteria']

  criteria.each do |c|
    criterion = RubricCriterion.new
    criterion.assignment = assignment
    criterion.rubric_criterion_name = c['title']
    criterion.weight = c['weight']
    criterion.position = assignment.rubric_criteria.maximum('position') + 1
    levels = c['levels']
    i = 0
    0..NUM_LEVELS do |i|
      criterion['level_' + i.to_s + '_description'] = levels[i]
    end
    if !criterion.valid? || !criterion.save
      flash.now[:invalid_lines] << c.to_s
    else
      create_levels(criterion, level_names)
    end
  end
end
update() click to toggle source
# File app/controllers/rubrics_controller.rb, line 14
def update
  @criterion = RubricCriterion.find(params[:id])
  unless @criterion.update_attributes(params[:rubric_criterion])
    render :errors
    return
  end
  flash.now[:success] = I18n.t('criterion_saved_success')
end
update_positions() click to toggle source

This method handles the drag/drop RubricCriteria sorting

# File app/controllers/rubrics_controller.rb, line 159
def update_positions
  unless request.post?
    render :nothing => true
    return
  end
  @assignment = Assignment.find(params[:assignment_id])
  @criteria = @assignment.rubric_criteria
  params[:rubric_criteria_pane_list].each_with_index do |id, position|
    if id != ''
      RubricCriterion.update(id, :position => position + 1)
    end
  end
end
upload_rubric() click to toggle source
# File lib/benchmarking/submission_files/rubrics_controller.rb, line 127
def upload_rubric
 file = params[:upload_rubric][:rubric]
 file_type = params[:upload_rubric][:file_type]
 @assignment = Assignment.find(params[:id])
 if request.post? && !file.blank? && !file_type.blank?
   begin
     RubricCriterion.transaction do
       case file_type
       when 'csv'
         parse_csv_rubric(file, @assignment)
       when 'yml'
         parse_yml_rubric(file, @assignment)
       end
       unless flash[:invalid_lines].empty?
         raise I18n.t('csv_invalid_lines')
       end
       flash[:success] = 'Rubric added/updated.'
     end
   rescue Exception => e
     flash[:error] = I18n.t('csv_valid_format')
   end
 end



 redirect_to :action => 'index', :id => @assignment.id
end
yml_upload() click to toggle source
# File app/controllers/rubrics_controller.rb, line 93
def yml_upload
  criteria_with_errors = ActiveSupport::OrderedHash.new
  assignment = Assignment.find(params[:assignment_id])
  encoding = params[:encoding]
  unless request.post?
    redirect_to :action => 'index', :id => assignment.id
    return
  end
  file = params[:yml_upload][:rubric]
  if !file.nil? && !file.blank?
    begin
      if encoding != nil
        file = StringIO.new(Iconv.iconv('UTF-8', encoding, file.read).join)
      end
      rubrics = YAML::load(file)
    rescue ArgumentError => e
      flash[:error] = I18n.t('rubric_criteria.upload.error') + '  ' +
         I18n.t('rubric_criteria.upload.syntax_error', :error => "#{e}")
      redirect_to :action => 'index', :id => assignment.id
      return
    end
    unless rubrics
      flash[:error] = I18n.t('rubric_criteria.upload.error') +
        '  ' + I18n.t('rubric_criteria.upload.empty_error')
      redirect_to :action => 'index', :id => assignment.id
      return
    end
    successes = 0
    i = 1
    rubrics.each do |key|
      begin
        RubricCriterion.create_or_update_from_yml_key(key, assignment)
        successes += 1
      rescue RuntimeError => e
        #collect the names of the criterion that contains an error in it.
        criteria_with_errors[i] = key.at(0)
        i = i + 1
        flash[:error] = I18n.t('rubric_criteria.upload.syntax_error', :error => "#{e}")
      end
    end

    bad_criteria_names = ''
    i = 0
    # Create a String from the OrderedHash of bad criteria seperated by commas.
    criteria_with_errors.each_value do |keys|
      if i == 0
        bad_criteria_names = keys
        i = i + 1
      else
        bad_criteria_names = bad_criteria_names + ', ' + keys
      end
    end

    if successes < rubrics.length
      flash[:error] = I18n.t('rubric_criteria.upload.error') + ' ' + bad_criteria_names
    end

    if successes > 0
      flash[:notice] = I18n.t('rubric_criteria.upload.success', :nb_updates => successes)
    end
  end
  redirect_to :action => 'index', :assignment_id => assignment.id
end