| Name | Total Lines | Lines of Code | Total Coverage | Code Coverage |
|---|---|---|---|---|
| app/models/submission.rb | 209 | 146 | 82.78%
|
81.51%
|
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.
1 require 'fileutils' # FileUtils used here |
2 |
3 # Handle for getting student submissions. Actual instance depend |
4 # on whether an assignment is a group or individual assignment. |
5 # Use Assignment.submission_by(user) to retrieve the correct submission. |
6 class Submission < ActiveRecord::Base |
7 after_create :create_result |
8 before_validation(:bump_old_submissions, :on => :create) |
9 |
10 validates_numericality_of :submission_version, :only_integer => true |
11 belongs_to :grouping |
12 has_one :result, :dependent => :destroy |
13 has_many :submission_files, :dependent => :destroy |
14 has_many :annotations, :through => :submission_files |
15 has_many :test_results, :dependent => :destroy |
16 belongs_to :remark_result, :class_name => "Result" |
17 |
18 validates_associated :remark_result |
19 |
20 def self.create_by_timestamp(grouping, timestamp) |
21 if !timestamp.kind_of? Time |
22 raise "Expected a timestamp of type Time" |
23 end |
24 repo = grouping.group.repo |
25 revision = repo.get_revision_by_timestamp(timestamp) |
26 submission = self.generate_new_submission(grouping, revision) |
27 repo.close |
28 return submission |
29 end |
30 |
31 def self.create_by_revision_number(grouping, revision_number) |
32 repo = grouping.group.repo |
33 revision = repo.get_revision(revision_number) |
34 submission = self.generate_new_submission(grouping, revision) |
35 repo.close |
36 return submission |
37 end |
38 |
39 def self.generate_new_submission(grouping, revision) |
40 new_submission = Submission.new |
41 new_submission.grouping = grouping |
42 new_submission.submission_version = 1 |
43 new_submission.submission_version_used = true |
44 new_submission.revision_timestamp = revision.timestamp |
45 new_submission.revision_number = revision.revision_number |
46 |
47 new_submission.transaction do |
48 begin |
49 new_submission.populate_with_submission_files(revision) |
50 rescue Repository::FileDoesNotExist => e |
51 #populate the submission with no files instead of raising an exception |
52 end |
53 new_submission.save |
54 end |
55 return new_submission |
56 end |
57 |
58 # For group submissions, actions here must only be accessible to members |
59 # that has inviter or accepted status. This check is done when fetching |
60 # the user or group submission from an assignment (see controller). |
61 |
62 # Handles file submissions. Late submissions have a status of "late" |
63 def submit(user, file, submission_time, sdir=SUBMISSIONS_PATH) |
64 filename = file.original_filename |
65 |
66 # create a backup if file already exists |
67 dir = submit_dir(sdir) |
68 filepath = File.join(dir, filename) |
69 create_backup(filename, sdir) if File.exists?(filepath) |
70 |
71 # create a submission_file record |
72 submission_file = submission_files.create do |f| |
73 f.user = user |
74 f.filename = file.original_filename |
75 f.submitted_at = submission_time |
76 f.submission_file_status = "late" if assignment.due_date < submission_time |
77 end |
78 |
79 # upload file contents to file system |
80 File.open(filepath, "wb") { |f| f.write(file.read) } if submission_file.save |
81 return submission_file |
82 end |
83 |
84 # Delete all records of filename in submissions and store in backup folder |
85 # (for now, called "BACKUP") |
86 def remove_file(filename) |
87 # get all submissions for this filename |
88 files = submission_files.all(:conditions => ["filename = ?", filename]) |
89 return unless files && !files.empty? |
90 files.each { |f| f.destroy } # destroy all records first |
91 |
92 _adir = submit_dir |
93 backup_dir = File.join(_adir, "BACKUP") |
94 FileUtils.mkdir_p(backup_dir) |
95 |
96 source_file = File.join(_adir, filename) |
97 dest_file = File.join(backup_dir, filename) |
98 FileUtils.mv(source_file, dest_file, :force => true) |
99 end |
100 |
101 |
102 # Query functions ------------------------------------------------------- |
103 # Figure out which assignment this submission is for |
104 def assignment |
105 return self.grouping.assignment |
106 end |
107 |
108 def has_result? |
109 return !result.nil? |
110 end |
111 |
112 # Does this submission have a remark result? |
113 def has_remark? |
114 return !remark_result.nil? |
115 end |
116 |
117 # Does this submission have a remark request submitted? |
118 # remark_results in 'unmarked' state have not been submitted by the student yet (just saved) |
119 # Submitted means that the remark request can be viewed by instructors and TAs and is no |
120 # longer editable by the student. |
121 # Saved means that the remark request cannot be viewed by instructors or TAs yet and |
122 # the student can still make changes to the request details. |
123 def remark_submitted? |
124 return (self.has_remark? && remark_result.marking_state != Result::MARKING_STATES[:unmarked]) |
125 end |
126 |
127 # Helper methods |
128 def populate_with_submission_files(revision, path="/") |
129 # Remember that assignments have folders within repositories - these |
130 # will be "spoofed" as root... |
131 if path == '/' |
132 path = assignment.repository_folder |
133 end |
134 |
135 # First, go through directories... |
136 directories = revision.directories_at_path(path) |
137 directories.each do |directory_name, directory| |
138 populate_with_submission_files(revision, File.join(path, directory.name)) |
139 end |
140 files = revision.files_at_path(path) |
141 files.each do |filename, file| |
142 new_file = SubmissionFile.new |
143 new_file.submission = self |
144 new_file.filename = file.name |
145 new_file.path = file.path |
146 new_file.save |
147 end |
148 end |
149 |
150 #=== Description |
151 # Helper class method to find a submission by providing a group_name and |
152 # and an assignment short identifier. |
153 #=== Returns |
154 # nil if no such submission exists. |
155 def self.get_submission_by_group_and_assignment(group_n, ass_si) |
156 assignment = Assignment.find_by_short_identifier(ass_si) |
157 group = Group.find_by_group_name(group_n) |
158 if !assignment.nil? && !group.nil? |
159 grouping = group.grouping_for_assignment(assignment.id) |
160 return grouping.current_submission_used |
161 else |
162 return nil |
163 end |
164 end |
165 |
166 def create_remark_result |
167 remark_result = Result.new |
168 self.remark_result = remark_result |
169 remark_result.marking_state = Result::MARKING_STATES[:unmarked] |
170 remark_result.submission_id = self.id |
171 remark_result.save |
172 self.save |
173 end |
174 |
175 def create_remark_result_object |
176 remark_result = Result.new |
177 self.remark_result = remark_result |
178 remark_result.marking_state = Result::MARKING_STATES[:unmarked] |
179 remark_result.submission_id = self.id |
180 remark_result.save |
181 self.save |
182 end |
183 |
184 private |
185 |
186 def create_result |
187 result = Result.new |
188 self.result = result |
189 result.marking_state = Result::MARKING_STATES[:unmarked] |
190 result.save |
191 end |
192 |
193 # Bump any old Submissions down the line and ensure no submission has |
194 # submission_version_used == true |
195 def bump_old_submissions |
196 while grouping.reload.has_submission? |
197 old_submission = grouping.current_submission_used |
198 if self.submission_version.nil? or self.submission_version <= old_submission.submission_version |
199 self.submission_version = old_submission.submission_version + 1 |
200 end |
201 old_submission.submission_version_used = false |
202 old_submission.save |
203 old_result = old_submission.result |
204 old_result.released_to_students = false |
205 old_result.save |
206 end |
207 end |
208 |
209 end |
Generated on Tue Feb 07 00:07:36 -0500 2012 with rcov 0.9.10