Rcov C0 Coverage Information - RCov

app/controllers/submissions_controller.rb

Name Total Lines Lines of Code Total Coverage Code Coverage
app/controllers/submissions_controller.rb 493 407
55.17%
50.12%

Key

Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.

Coverage Details

1 require 'fastercsv'
2 
3 class SubmissionsController < ApplicationController
4   include SubmissionsHelper
5   include PaginationHelper
6   
7   before_filter    :authorize_only_for_admin, :except => [:populate_file_manager, :browse,
8   :index, :file_manager, :update_files, 
9   :download, :s_table_paginate, :collect_and_begin_grading, 
10   :manually_collect_and_begin_grading, :repo_browser, :populate_repo_browser, :update_converted_pdfs]
11   before_filter    :authorize_for_ta_and_admin, :only => [:browse, :index, :s_table_paginate, :collect_and_begin_grading, 
12   :manually_collect_and_begin_grading, :repo_browser, :populate_repo_browser, :update_converted_pdfs]
13   before_filter    :authorize_for_student, :only => [:file_manager, :populate_file_manager, :update_files]
14   before_filter    :authorize_for_user, :only => [:download]
15   
16   S_TABLE_PARAMS = {
17     :model => Grouping, 
18     :per_pages => [15, 30, 50, 100, 150, 500, 1000],
19     :filters => {
20       'none' => {
21         :display => I18n.t("browse_submissions.show_all"),
22         :proc => lambda { |params, to_include|
23           return params[:assignment].groupings.all(:include => to_include)}},
24       'unmarked' => {
25         :display => I18n.t("browse_submissions.show_unmarked"), 
26         :proc => lambda { |params, to_include| return params[:assignment].groupings.all(:include => [to_include]).select{|g| !g.has_submission? || (g.has_submission? && g.current_submission_used.result.marking_state == Result::MARKING_STATES[:unmarked]) } }},
27       'partial' => {
28         :display => I18n.t("browse_submissions.show_partial"),
29         :proc => lambda { |params, to_include| return params[:assignment].groupings.all(:include => [to_include]).select{|g| g.has_submission? && g.current_submission_used.result.marking_state == Result::MARKING_STATES[:partial] } }},
30       'complete' => {
31         :display => I18n.t("browse_submissions.show_complete"),
32         :proc => lambda { |params, to_include| return params[:assignment].groupings.all(:include => [to_include]).select{|g| g.has_submission? && g.current_submission_used.result.marking_state == Result::MARKING_STATES[:complete] } }},
33       'released' => {
34         :display => I18n.t("browse_submissions.show_released"),
35         :proc => lambda { |params, to_include| return params[:assignment].groupings.all(:include => [to_include]).select{|g| g.has_submission? && g.current_submission_used.result.released_to_students} }},
36       'assigned' => {
37         :display => I18n.t("browse_submissions.show_assigned_to_me"),
38         :proc => lambda { |params, to_include| return params[:assignment].ta_memberships.find_all_by_user_id(params[:user_id], :include => [:grouping => to_include]).collect{|m| m.grouping} }}
39     },
40     :sorts => {
41       'group_name' => lambda { |a,b| a.group.group_name.downcase <=> b.group.group_name.downcase},
42       'repo_name' => lambda { |a,b| a.group.repo_name.downcase <=> b.group.repo_name.downcase },
43       'revision_timestamp' => lambda { |a,b|
44         return -1 if !a.has_submission?
45         return 1 if !b.has_submission?
46         return a.current_submission_used.revision_timestamp <=> b.current_submission_used.revision_timestamp
47       },
48       'marking_state' => lambda { |a,b|
49         return -1 if !a.has_submission?
50         return 1 if !b.has_submission?
51         return a.current_submission_used.result.marking_state <=> b.current_submission_used.result.marking_state
52       },
53       'total_mark' => lambda { |a,b|
54         return -1 if !a.has_submission?
55         return 1 if !b.has_submission?
56         return a.current_submission_used.result.total_mark <=> b.current_submission_used.result.total_mark
57       },
58       'grace_credits_used' => lambda { |a,b|
59         return a.grace_period_deduction_sum <=> b.grace_period_deduction_sum
60       }
61     }
62   }
63         
64   def repo_browser
65     @grouping = Grouping.find(params[:id])
66     @assignment = @grouping.assignment
67     @path = params[:path] || '/'
68     @previous_path = File.split(@path).first
69     @repository_name = @grouping.group.repository_name
70     repo = @grouping.group.repo
71     begin
72       if !params[:revision_timestamp].nil?
73         @revision_number = repo.get_revision_by_timestamp(Time.parse(params[:revision_timestamp])).revision_number
74       elsif !params[:revision_number].nil?
75         @revision_number = params[:revision_number].to_i
76       else
77         @revision_number = repo.get_latest_revision.revision_number
78       end
79       @revision = repo.get_revision(@revision_number)
80       @revision_timestamp = @revision.timestamp
81       repo.close
82     rescue Exception => e
83       flash[:error] = e.message
84       @revision_number = repo.get_latest_revision.revision_number
85       @revision_timestamp = repo.get_latest_revision.timestamp
86       repo.close
87     end
88   end
89   
90   def populate_repo_browser
91     @grouping = Grouping.find(params[:id])
92     @assignment = @grouping.assignment
93     @path = params[:path] || '/'
94     @revision_number = params[:revision_number]
95     @previous_path = File.split(@path).first
96     @grouping.group.access_repo do |repo|
97       begin
98         @revision = repo.get_revision(params[:revision_number].to_i)
99         @directories = @revision.directories_at_path(File.join(@assignment.repository_folder, @path))
100         @files = @revision.files_at_path(File.join(@assignment.repository_folder, @path))
101       rescue Exception => @find_revision_error
102         render :action => 'repo_browser/find_revision_error'
103         return
104       end
105       @table_rows = {}
106       @files.sort.each do |file_name, file|
107         @table_rows[file.id] = construct_repo_browser_table_row(file_name, file)
108       end
109       @directories.sort.each do |directory_name, directory|
110         @table_rows[directory.id] = construct_repo_browser_directory_table_row(directory_name, directory)
111       end
112       render :action => 'repo_browser/populate_repo_browser'
113     end
114   end
115  
116   def file_manager
117     @assignment = Assignment.find(params[:id])
118 
119     @grouping = current_user.accepted_grouping_for(@assignment.id)
120 
121     if @grouping.nil?
122       redirect_to :controller => 'assignments', :action => 'student_interface', :id => params[:id]
123       return
124     end
125 
126     user_group = @grouping.group
127     @path = params[:path] || '/'
128     
129     user_group.access_repo do |repo|
130       @revision = repo.get_latest_revision
131       @files = @revision.files_at_path(File.join(@assignment.repository_folder, @path))
132       @missing_assignment_files = []
133       @assignment.assignment_files.each do |assignment_file|
134         if !@revision.path_exists?(File.join(@assignment.repository_folder,
135         assignment_file.filename))
136           @missing_assignment_files.push(assignment_file)
137         end
138       end
139     end
140   end
141   
142   def populate_file_manager
143     @assignment = Assignment.find(params[:id])
144     @grouping = current_user.accepted_grouping_for(@assignment.id)   
145     user_group = @grouping.group
146     revision_number= params[:revision_number]
147     @path = params[:path] || '/'
148     @previous_path = File.split(@path).first
149     
150     user_group.access_repo do |repo|
151       if revision_number.nil?
152         @revision = repo.get_latest_revision
153       else
154        @revision = repo.get_revision(revision_number.to_i)
155       end
156       @directories = @revision.directories_at_path(File.join(@assignment.repository_folder, @path))
157       @files = @revision.files_at_path(File.join(@assignment.repository_folder, @path))
158       @table_rows = {}
159       @files.sort.each do |file_name, file|
160         @table_rows[file.id] = construct_file_manager_table_row(file_name, file)
161       end
162       if @grouping.repository_external_commits_only?
163         @directories.sort.each do |directory_name, directory|
164           @table_rows[directory.id] = construct_file_manager_dir_table_row(directory_name, directory)
165         end
166       end
167       render :action => 'file_manager_populate'
168     end
169   end
170   
171   def manually_collect_and_begin_grading
172     @grouping = Grouping.find(params[:id])
173     @revision_number = params[:current_revision_number].to_i
174     SubmissionCollector.instance.manually_collect_submission(@grouping,
175       @revision_number)
176     redirect_to :action => 'update_converted_pdfs', :id => @grouping.id
177   end
178 
179   def collect_and_begin_grading
180     assignment = Assignment.find(params[:id])
181     grouping = Grouping.find(params[:grouping_id])
182     if !assignment.submission_rule.can_collect_now?
183       flash[:error] = I18n.t("browse_submissions.could_not_collect",
184         :group_name => grouping.group.group_name)
185     else
186       #Push grouping to the priority queue
187       SubmissionCollector.instance.push_grouping_to_priority_queue(grouping)
188       flash[:success] = I18n.t("collect_submissions.priority_given")
189     end
190     redirect_to :action => 'browse', :id => assignment.id
191   end
192 
193   def collect_all_submissions
194     assignment = Assignment.find(params[:id], :include => [:groupings])
195     if !assignment.submission_rule.can_collect_now?
196       flash[:error] = I18n.t("collect_submissions.could_not_collect",
197         :assignment_identifier => assignment.short_identifier)
198     else
199       submission_collector = SubmissionCollector.instance
200       submission_collector.push_groupings_to_queue(assignment.groupings)
201       flash[:success] = I18n.t("collect_submissions.collection_job_started",
202         :assignment_identifier => assignment.short_identifier)
203     end
204     redirect_to :action => 'browse', :id => assignment.id
205   end
206 
207   def update_converted_pdfs
208     @grouping = Grouping.find(params[:id])
209     @submission = @grouping.current_submission_used
210     @pdf_count= 0
211     @converted_count = 0
212     @submission.submission_files.each do |file|
213       if file.is_pdf?
214         @pdf_count += 1
215         if file.is_converted
216           @converted_count += 1
217         end
218       end
219     end
220   end
221 
222   def browse
223     if current_user.ta?
224       params[:filter] = 'assigned'
225     else
226       if params[:filter] == nil or params[:filter].blank?
227         params[:filter] = 'none'    
228       end
229     end
230     if params[:sort_by] == nil or params[:sort_by].blank?
231       params[:sort_by] = 'group_name'
232     end 
233     @assignment = Assignment.find(params[:id])
234     @groupings, @groupings_total = handle_paginate_event(
235       S_TABLE_PARAMS,                                     # the data structure to handle filtering and sorting
236         { :assignment => @assignment,                     # the assignment to filter by
237           :user_id => current_user.id},                   # the submissions accessable by the current user
238       params)                                             # additional parameters that affect things like sorting
239 
240     #Eager load all data only for those groupings that will be displayed
241     sorted_groupings = @groupings
242     @groupings = Grouping.find(:all, :conditions => {:id => sorted_groupings},
243       :include => [:assignment, :group, :grace_period_deductions,
244         {:current_submission_used => :result},
245         {:accepted_student_memberships => :user}])
246 
247     #re-sort @groupings by the previous order, because eager loading query
248     #messed up the grouping order
249     @groupings = sorted_groupings.map do |sorted_grouping|
250       @groupings.detect do |unsorted_grouping|
251         unsorted_grouping == sorted_grouping
252       end
253     end
254 
255     @current_page = params[:page].to_i()
256     @per_page = params[:per_page]
257     @filters = get_filters(S_TABLE_PARAMS)
258     @per_pages = S_TABLE_PARAMS[:per_pages]
259     @desc = params[:desc]
260     @filter = params[:filter]
261     @sort_by = params[:sort_by]
262   end 
263 
264   def index
265     @assignments = Assignment.all(:order => :id)
266     render :action => 'index', :layout => 'sidebar'
267   end
268 
269   # controller handles transactional submission of files
270   def update_files
271     assignment_id = params[:id]
272     assignment = Assignment.find(assignment_id)
273     path = params[:path] || '/'
274     grouping = current_user.accepted_grouping_for(assignment_id)
275     if grouping.repository_external_commits_only?
276       raise I18n.t("student.submission.external_submit_only")
277     end
278     if !grouping.is_valid?
279       redirect_to :action => :file_manager, :id => assignment_id
280       return
281     end
282     grouping.group.access_repo do |repo|
283 
284       assignment_folder = File.join(assignment.repository_folder, path)
285 
286       # Get the revision numbers for the files that we've seen - these
287       # values will be the "expected revision numbers" that we'll provide
288       # to the transaction to ensure that we don't overwrite a file that's
289       # been revised since the user last saw it.
290       file_revisions = params[:file_revisions].nil? ? [] : params[:file_revisions]
291 
292       # The files that will be replaced - just give an empty array
293       # if params[:replace_files] is nil
294       replace_files = params[:replace_files].nil? ? {} : params[:replace_files]
295 
296       # The files that will be deleted
297       delete_files = params[:delete_files].nil? ? {} : params[:delete_files]
298 
299       # The files that will be added
300       new_files = params[:new_files].nil? ? {} : params[:new_files]
301 
302       # Create transaction, setting the author.  Timestamp is implicit.
303       txn = repo.get_transaction(current_user.user_name)
304 
305       log_messages = []
306       begin
307         # delete files marked for deletion
308         delete_files.keys.each do |filename|
309           txn.remove(File.join(assignment_folder, filename), file_revisions[filename])
310           log_messages.push(I18n.t("markus_logger.student_deleted_file", :user_name => current_user.user_name, :file_name => filename, :assignment => assignment.short_identifier))
311         end
312 
313         # Replace files
314         replace_files.each do |filename, file_object|
315           # Sometimes the file pointer of file_object is at the end of the file.
316           # In order to avoid empty uploaded files, rewind it to be save.
317           file_object.rewind
318           txn.replace(File.join(assignment_folder, filename), file_object.read, file_object.content_type, file_revisions[filename])
319           log_messages.push(I18n.t("markus_logger.student_replaced_file", :user_name => current_user.user_name, :file_name => filename, :assignment => assignment.short_identifier))
320         end
321 
322         # Add new files
323         new_files.each do |file_object|
324           # sanitize_file_name in SubmissionsHelper
325           if file_object.original_filename.nil?
326             raise I18n.t("student.submission.invalid_file_name")
327           end
328           # Sometimes the file pointer of file_object is at the end of the file.
329           # In order to avoid empty uploaded files, rewind it to be save.
330           file_object.rewind
331           txn.add(File.join(assignment_folder, sanitize_file_name(file_object.original_filename)), file_object.read, file_object.content_type)
332           log_messages.push(I18n.t("markus_logger.student_submitted_file", :user_name => current_user.user_name, :file_name => file_object.original_filename, :assignment => assignment.short_identifier))
333         end
334 
335         # finish transaction
336         if !txn.has_jobs?
337           flash[:transaction_warning] = I18n.t("student.submission.no_action_detected")
338           redirect_to :action => "file_manager", :id => assignment_id
339           return
340         end
341         if !repo.commit(txn)
342           flash[:update_conflicts] = txn.conflicts
343         else
344           flash[:success] = I18n.t('update_files.success')
345           # flush log messages
346           m_logger = MarkusLogger.instance
347           log_messages.each do |msg|
348             m_logger.log(msg)
349           end
350         end
351 
352         # Are we past collection time?
353         if assignment.submission_rule.can_collect_now?
354           flash[:commit_notice] = assignment.submission_rule.commit_after_collection_message(grouping)
355         end
356         redirect_to :action => "file_manager", :id => assignment_id
357 
358       rescue Exception => e
359         raise e
360         flash[:commit_error] = e.message
361         redirect_to :action => "file_manager", :id => assignment_id
362       end
363     end
364   end
365   
366   def download
367     @assignment = Assignment.find(params[:id])
368     # find_appropriate_grouping can be found in SubmissionsHelper
369 
370     @grouping = find_appropriate_grouping(@assignment.id, params)
371 
372     revision_number = params[:revision_number]
373     path = params[:path] || '/'
374     @grouping.group.access_repo do |repo|
375       if revision_number.nil?
376         @revision = repo.get_latest_revision
377       else
378         @revision = repo.get_revision(revision_number.to_i)
379       end
380 
381       begin
382        file = @revision.files_at_path(File.join(@assignment.repository_folder, path))[params[:file_name]]
383        file_contents = repo.download_as_string(file)
384       rescue Exception => e
385         render :text => I18n.t("student.submission.missing_file", :file_name => params[:file_name], :message => e.message)
386         return
387       end
388     
389       if SubmissionFile.is_binary?(file_contents)
390         # If the file appears to be binary, send it as a download
391         send_data file_contents, :disposition => 'attachment', :filename => params[:file_name]
392       else
393         # Otherwise, blast it out to the screen
394         render :text => file_contents, :layout => 'sanitized_html'
395       end
396     end
397   end 
398 
399   def update_submissions
400     return unless request.post?
401     assignment = Assignment.find(params[:id])
402     errors = []
403     groupings = []
404     if params[:ap_select_full] == 'true'
405       # We should have been passed a filter
406       if params[:filter].blank?
407         raise I18n.t("student.submission.expect_filter")
408       end
409       # Get all Groupings for this filter
410       groupings = S_TABLE_PARAMS[:filters][params[:filter]][:proc].call({:assignment => assignment, :user_id => current_user.id})
411     else
412       # User selected particular Grouping IDs
413       if params[:groupings].nil?
414         errors.push(I18n.t('results.must_select_a_group'))
415       else
416         groupings = assignment.groupings.find(params[:groupings])
417       end
418     end
419 
420     log_message = ""       
421     if !params[:release_results].nil?
422       changed = set_release_on_results(groupings, true, errors)
423       log_message = I18n.t("markus_logger.marks_released_for_assignment",
424                             :assignment_id => assignment.id,
425                             :assignment => assignment.short_identifier,
426                             :number_groups => changed)
427     elsif !params[:unrelease_results].nil?
428       changed = set_release_on_results(groupings, false, errors)
429       log_message = I18n.t("markus_logger.marks_unreleased_for_assignment",
430                             :assignment_id => assignment.id,
431                             :assignment => assignment.short_identifier,
432                             :number_groups => changed)
433     end
434 
435 
436     if !groupings.empty?
437       assignment.set_results_average
438     end
439 
440     if changed > 0
441       flash[:success] = I18n.t('results.successfully_changed', {:changed => changed})
442       m_logger = MarkusLogger.instance
443       m_logger.log(log_message)
444     end
445     flash[:errors] = errors
446     
447     redirect_to :action => 'browse', :id => params[:id]    
448   end
449   
450   def unrelease
451     return unless request.post?
452     if params[:groupings].nil?
453       flash[:release_results] = I18n.t("assignment.group.select_a_group")
454     else
455       params[:groupings].each do |g|
456         g.unrelease_results
457       end
458       m_logger = MarkusLogger.instance
459       assignment = Assignment.find(params[:id])
460       m_logger.log(I18n.t("markus_logger.marks_unreleased_for_assignment",
461                   :assignment_id => assignment.id,
462                   :assignment => assignment.short_identifier,
463                   :number_groups => params[:groupings].length))
464     end
465     redirect_to :action => 'browse', :id => params[:id]
466   end
467   
468   # See Assignment.get_simple_csv_report for details
469   def download_simple_csv_report
470     assignment = Assignment.find(params[:id])
471     send_data assignment.get_simple_csv_report, :disposition => 'attachment', :type => 'application/vnd.ms-excel', :filename => "#{assignment.short_identifier} simple report.csv"
472   end
473   
474   # See Assignment.get_detailed_csv_report for details
475   def download_detailed_csv_report
476     assignment = Assignment.find(params[:id])
477     send_data assignment.get_detailed_csv_report, :disposition => 'attachment', :type => 'application/vnd.ms-excel', :filename => "#{assignment.short_identifier} detailed report.csv"
478   end
479   
480   # See Assignment.get_svn_export_commands for details
481   def download_svn_export_commands
482     assignment = Assignment.find(params[:id])
483     svn_commands = assignment.get_svn_export_commands
484     send_data svn_commands.join("\n"), :disposition => 'attachment', :type => 'text/plain', :filename => "#{assignment.short_identifier}_svn_exports"
485   end
486 
487   # See Assignment.get_svn_repo_list for details
488   def download_svn_repo_list
489     assignment = Assignment.find(params[:id])
490     send_data assignment.get_svn_repo_list, :disposition => 'attachment', :type => 'text/plain', :filename => "#{assignment.short_identifier}_svn_repo_list"
491   end
492 
493 end

Generated on Thu Sep 09 00:10:34 -0400 2010 with rcov 0.9.8