Rcov C0 Coverage Information - RCov

app/models/flexible_criterion.rb

Name Total Lines Lines of Code Total Coverage Code Coverage
app/models/flexible_criterion.rb 211 141
96.21%
94.33%

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 require 'csv'
3 # Represents a flexible criterion used to mark an assignment that
4 # has the marking_scheme_type attribute set to 'flexible'.
5 class FlexibleCriterion < ActiveRecord::Base
6 
7   set_table_name "flexible_criteria" # set table name correctly
8   belongs_to :assignment, :counter_cache => true
9 
10   has_many :marks, :as => :markable, :dependent => :destroy
11 
12   has_many :criterion_ta_associations,
13            :as => :criterion,
14            :dependent => :destroy
15 
16   has_many :tas, :through => :criterion_ta_associations
17 
18   validates_associated :assignment,
19                   :message => 'association is not strong with an assignment'
20   validates_uniqueness_of :flexible_criterion_name,
21                           :scope => :assignment_id,
22                           :message => 'is already taken'
23   validates_presence_of :flexible_criterion_name, :assignment_id, :max
24   validates_numericality_of :assignment_id,
25                         :only_integer => true,
26                         :greater_than => 0,
27                         :message => "can only be whole number greater than 0"
28   validates_numericality_of :max,
29                             :message => "must be a number greater than 0.0",
30                             :greater_than => 0.0
31 
32 #  before_save :update_assigned_groups_count
33 
34   DEFAULT_MAX = 1
35 
36   def update_assigned_groups_count
37     result = []
38     tas.each do |ta|
39       result = result.concat(ta.get_groupings_by_assignment(assignment))
40     end
41     self.assigned_groups_count = result.uniq.length
42   end
43 
44   # Creates a CSV string from all the flexible criteria related to an assignment.
45   #
46   # ===Returns:
47   #
48   # A string. see new_from_csv_row for format reference.
49   def self.create_csv(assignment)
50     csv_string = FasterCSV.generate do |csv|
51       # TODO temporary until Assignment gets its criteria method
52       criteria = FlexibleCriterion.find_all_by_assignment_id(assignment.id, :order => :position)
53       criteria.each do |c|
54         criterion_array = [c.flexible_criterion_name, c.max, c.description]
55         csv << criterion_array;
56       end
57     end
58     return csv_string
59   end
60 
61   # Instantiate a FlexibleCriterion from a CSV row and attach it to the supplied
62   # assignment.
63   #
64   # ===Params:
65   #
66   # row::         An array representing one CSV file row. Should be in the following
67   #               format: [name, max, description] where description is optional.
68   # assignment::  The assignment to which the newly created criterion should belong.
69   #
70   # ===Raises:
71   #
72   # CSV::IllegalFormatError:: If the row does not contains enough information, if the max value
73   #                           is zero (or doesn't evaluate to a float) or if the
74   #                           supplied name is not unique.
75   def self.new_from_csv_row(row, assignment)
76     if row.length < 2
77       raise CSV::IllegalFormatError.new(I18n.t('criteria_csv_error.incomplete_row'))
78     end
79     criterion = FlexibleCriterion.new
80     criterion.assignment = assignment
81     criterion.flexible_criterion_name = row[0]
82     # assert that no other criterion uses the same name for the same assignment.
83     if (FlexibleCriterion.find_all_by_assignment_id_and_flexible_criterion_name(assignment.id, criterion.flexible_criterion_name).size != 0)
84       raise CSV::IllegalFormatError.new(I18n.t('criteria_csv_error.name_not_unique'))
85     end
86     criterion.max = row[1]
87     if (criterion.max == 0)
88       raise CSV::IllegalFormatError.new(I18n.t('criteria_csv_error.max_zero'))
89     end
90     criterion.description = row[2] if !row[2].nil?
91     criterion.position = next_criterion_position(assignment)
92     if !criterion.save
93       raise CSV::IllegalFormatError.new(criterion.errors)
94     end
95     return criterion
96   end
97 
98   # Parse a flexible criteria CSV file.
99   #
100   # ===Params:
101   #
102   # file::          A file object which will be tried for parsing.
103   # assignment::    The assignment to which the new criteria should belong to.
104   # invalid_lines:: An object to recieve all encountered _invalid_ lines.
105   #                 Strings representing the faulty line followed by
106   #                 a human readable error message are appended to the object
107   #                 via the << operator.
108   #
109   #                 *Hint*: An array allows for easy
110   #                 access to single invalid lines.
111   #
112   # ===Returns:
113   #
114   # The number of successfully created criteria.
115   def self.parse_csv(file, assignment, invalid_lines = nil)
116     nb_updates = 0
117     FasterCSV.parse(file.read) do |row|
118       next if FasterCSV.generate_line(row).strip.empty?
119       begin
120         FlexibleCriterion.new_from_csv_row(row, assignment)
121         nb_updates += 1
122       rescue CSV::IllegalFormatError => e
123         invalid_lines << row.join(',') + ": " + e.message unless invalid_lines.nil?
124       end
125     end
126     return nb_updates
127   end
128 
129   # ===Returns:
130   #
131   # The position that should receive the next criterion for an assignment.
132   def self.next_criterion_position(assignment)
133     # TODO temporary, until Assignment gets its criteria method
134     #      nevermind the fact that this computation should really belong in assignment
135     last_criterion = FlexibleCriterion.find_last_by_assignment_id(assignment.id, :order => :position)
136     return last_criterion.position + 1 unless last_criterion.nil?
137     return 1
138   end
139 
140   def get_weight
141     return 1
142   end
143 
144   def all_assigned_groups
145     result = []
146     tas.each do |ta|
147       result = result.concat(ta.get_groupings_by_assignment(assignment))
148     end
149     return result.uniq
150   end
151 
152   def add_tas(ta_array)
153     ta_array = Array(ta_array)
154     associations = criterion_ta_associations.all(:conditions => {:ta_id => ta_array})
155     ta_array.each do |ta|
156       if (ta.criterion_ta_associations & associations).size < 1
157         criterion_ta_associations.create(:ta => ta, :criterion => self, :assignment => self.assignment)
158       end
159     end
160   end
161 
162   def get_name
163     return flexible_criterion_name
164   end
165 
166   def remove_tas(ta_array)
167     ta_array = Array(ta_array)
168     associations_for_criteria = criterion_ta_associations.all(:conditions => {:ta_id => ta_array})
169     ta_array.each do |ta|
170       # & is the mathematical set intersection operator between two arrays
171       assoc_to_remove = (ta.criterion_ta_associations & associations_for_criteria)
172       if assoc_to_remove.size > 0
173         criterion_ta_associations.delete(assoc_to_remove)
174         assoc_to_remove.first.destroy
175       end
176     end
177   end
178 
179   def get_ta_names
180     return criterion_ta_associations.collect {|association| association.ta.user_name}
181   end
182 
183   def has_associated_ta?(ta)
184     if !ta.ta?
185       return false
186     end
187     return !(criterion_ta_associations.find_by_ta_id(ta.id) == nil)
188   end
189 
190   def add_tas_by_user_name_array(ta_user_name_array)
191     result = ta_user_name_array.map{|ta_user_name|
192       Ta.find_by_user_name(ta_user_name)}.compact
193     add_tas(result)
194   end
195 
196   # Returns an array containing the criterion names that didn't exist
197   def self.assign_tas_by_csv(csv_file_contents, assignment_id)
198     failures = []
199     FasterCSV.parse(csv_file_contents) do |row|
200       criterion_name = row.shift # Knocks the first item from array
201       criterion = FlexibleCriterion.find_by_assignment_id_and_flexible_criterion_name(assignment_id, criterion_name)
202       if criterion.nil?
203         failures.push(criterion_name)
204       else
205         criterion.add_tas_by_user_name_array(row) # The rest of the array
206       end
207     end
208     return failures
209   end
210 
211 end

Generated on Tue Feb 07 00:07:36 -0500 2012 with rcov 0.9.10