• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MarkUsProject / Markus / 12593910406

03 Jan 2025 06:44AM UTC coverage: 91.72% (-0.01%) from 91.732%
12593910406

Pull #7311

github

web-flow
Merge 7921401ea into 1221da9ce
Pull Request #7311: Scale rubric criterion levels on max_mark update

624 of 1365 branches covered (45.71%)

Branch coverage included in aggregate %.

35 of 40 new or added lines in 3 files covered. (87.5%)

2 existing lines in 1 file now uncovered.

41183 of 44216 relevant lines covered (93.14%)

120.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.63
/app/controllers/criteria_controller.rb
1
class CriteriaController < ApplicationController
1✔
2
  before_action { authorize! }
96✔
3

4
  layout 'assignment_content'
1✔
5

6
  def index
1✔
7
    @assignment = Assignment.find(params[:assignment_id])
12✔
8
    if @assignment.marking_started?
12✔
9
      flash_now(:notice, I18n.t('assignments.due_date.marking_started_warning'))
×
10
    end
11
    @criteria = @assignment.criteria
12✔
12
  end
13

14
  def new
1✔
15
    @assignment = Assignment.find(params[:assignment_id])
6✔
16
    if @assignment.released_marks.any?
6✔
17
      flash_now(:error, t('criteria.errors.released_marks'))
×
18
      head :bad_request
×
19
    end
20
  end
21

22
  def create
1✔
23
    @assignment = Assignment.find(params[:assignment_id])
16✔
24
    if @assignment.released_marks.any?
16✔
25
      flash_now(:error, t('criteria.errors.released_marks'))
×
26
      head :bad_request
×
27
      return
×
28
    end
29
    @criterion = Criterion.new(
16✔
30
      type: params[:criterion_type],
31
      name: params[:new_criterion_prompt],
32
      assignment: @assignment,
33
      max_mark: params[:max_mark_prompt],
34
      position: @assignment.next_criterion_position
35
    )
36
    @criterion.set_default_levels if @criterion.is_a? RubricCriterion
16✔
37

38
    if @criterion.save
16✔
39
      flash_now(:success, t('flash.actions.create.success',
12✔
40
                            resource_name: @criterion.class.model_name.human))
41
    else
42
      @criterion.errors.full_messages.each do |message|
4✔
43
        flash_message(:error, message)
×
44
      end
45
      head :unprocessable_entity
4✔
46
    end
47
  end
48

49
  def edit
1✔
50
    @criterion = record
12✔
51
    @assignment = @criterion.assignment
12✔
52
    if @assignment.released_marks.any?
12✔
53
      flash_now(:notice, t('criteria.errors.released_marks'))
×
54
    end
55
  end
56

57
  def destroy
1✔
58
    @criterion = record
5✔
59
    @assignment = @criterion.assignment
5✔
60
    if @assignment.released_marks.any?
5✔
61
      flash_now(:error, t('criteria.errors.released_marks'))
×
62
      return
×
63
    end
64
    # Delete all marks associated with this criterion.
65
    @criterion.destroy
5✔
66
    flash_message(:success, t('flash.criteria.destroy.success'))
5✔
67
  end
68

69
  def update
1✔
70
    @criterion = record
14✔
71
    @assignment = @criterion.assignment
14✔
72
    if @assignment.released_marks.any?
14✔
73
      flash_now(:error, t('criteria.errors.released_marks'))
×
74
      head :bad_request
×
75
      return
×
76
    end
77
    if @criterion.is_a? RubricCriterion
14✔
78
      original_max_mark = @criterion.max_mark # need this to caclulate possible level scale
6✔
79
      # update everything except levels and assignments
80
      properly_updated = @criterion.update(rubric_criterion_params.except(:levels_attributes, :assignment_files))
6✔
81
      # update levels with a scale factor if necessary
82
      if rubric_criterion_params[:levels_attributes]
6✔
NEW
83
        properly_updated &&= @criterion.update_levels(rubric_criterion_params[:levels_attributes],
×
84
                                                      @criterion.reload.max_mark / original_max_mark)
85
      end
86
      unless rubric_criterion_params[:assignment_files].nil?
6✔
87
        assignment_files = AssignmentFile.find(rubric_criterion_params[:assignment_files].reject(&:empty?))
×
88
      end
89
    elsif @criterion.is_a? FlexibleCriterion
8✔
90
      properly_updated = @criterion.update(flexible_criterion_params.except(:assignment_files))
6✔
91
      unless flexible_criterion_params[:assignment_files].nil?
6✔
92
        assignment_files = AssignmentFile.find(flexible_criterion_params[:assignment_files].reject(&:empty?))
×
93
      end
94
    else
95
      properly_updated = @criterion.update(checkbox_criterion_params.except(:assignment_files))
2✔
96
      unless checkbox_criterion_params[:assignment_files].nil?
2✔
97
        assignment_files = AssignmentFile.find(checkbox_criterion_params[:assignment_files].reject(&:empty?))
×
98
      end
99
    end
100
    # delete old associated criteria_assignment_files_join
101
    old_criteria_assignment_files_join = @criterion.criteria_assignment_files_joins
14✔
102
    old_criteria_assignment_files_join.destroy_all
14✔
103
    # create new corresponding criteria_assignment_files_join
104
    assignment_files.to_a.each do |assignment_file|
14✔
105
      @criterion.criteria_assignment_files_joins.create(
×
106
        assignment_file: assignment_file
107
      )
108
    end
109
    if properly_updated
14✔
110
      flash_now(:success, t('flash.actions.update.success',
10✔
111
                            resource_name: @criterion.class.model_name.human))
112
    else
113
      @criterion.errors.full_messages.each do |message|
4✔
114
        flash_message(:error, message)
×
115
      end
116
      head :unprocessable_entity
4✔
117
    end
118
  end
119

120
  # Handles the drag/drop criteria sorting.
121
  def update_positions
1✔
122
    @assignment = Assignment.find(params[:assignment_id])
4✔
123

124
    Criterion.transaction do
4✔
125
      params[:criterion].each_with_index do |id, index|
4✔
126
        found_criterion = @assignment.criteria.find(id)
6✔
127
        found_criterion.update(position: index + 1)
4✔
128
      end
129
    rescue StandardError
130
      flash_message(:error, t('criteria.errors.criteria_not_found'))
2✔
131
      raise ActiveRecord::Rollback
2✔
132
    end
133
    head :ok
4✔
134
  end
135

136
  def download
1✔
137
    assignment = Assignment.find(params[:assignment_id])
2✔
138
    criteria = assignment.criteria
2✔
139
    yml_criteria = criteria.reduce({}) { |a, b| a.merge b.to_yml }
8✔
140
    send_data yml_criteria.to_yaml,
2✔
141
              filename: "#{assignment.short_identifier}_criteria.yml",
142
              disposition: 'attachment'
143
  end
144

145
  def upload
1✔
146
    assignment = Assignment.find(params[:assignment_id])
24✔
147
    if assignment.released_marks.any?
24✔
148
      flash_message(:error, t('criteria.errors.released_marks'))
×
149
      redirect_to action: 'index', id: assignment.id
×
150
      return
×
151
    end
152

153
    begin
154
      data = process_file_upload(['.yml'])
24✔
155
    rescue Psych::SyntaxError => e
156
      flash_message(:error, t('upload_errors.syntax_error', error: e.to_s))
3✔
157
    rescue StandardError => e
158
      flash_message(:error, e.message)
3✔
159
    else
160
      ApplicationRecord.transaction do
18✔
161
        successes = Criterion.upload_criteria_from_yaml(assignment, data[:contents])
18✔
162
        flash_message(:success, I18n.t('upload_success', count: successes)) if successes > 0
12✔
163
      rescue StandardError => e
164
        flash_message(:error, e.message)
6✔
165
        raise ActiveRecord::Rollback
6✔
166
      end
167
    end
168
    redirect_to action: 'index', assignment_id: assignment.id
24✔
169
  end
170

171
  private
1✔
172

173
  def flexible_criterion_params
1✔
174
    params.require(:flexible_criterion).permit(:name,
12✔
175
                                               :description,
176
                                               :position,
177
                                               :max_mark,
178
                                               :ta_visible,
179
                                               :peer_visible,
180
                                               :bonus,
181
                                               assignment_files: [])
182
  end
183

184
  def rubric_criterion_params
1✔
185
    params.require(:rubric_criterion).permit(:name,
18✔
186
                                             :assignment,
187
                                             :position,
188
                                             :ta_visible,
189
                                             :peer_visible,
190
                                             :max_mark,
191
                                             :bonus,
192
                                             levels_attributes: [:id, :name, :mark, :description, :_destroy],
193
                                             assignment_files: [])
194
  end
195

196
  def checkbox_criterion_params
1✔
197
    params.require(:checkbox_criterion).permit(:name,
4✔
198
                                               :description,
199
                                               :position,
200
                                               :max_mark,
201
                                               :ta_visible,
202
                                               :peer_visible,
203
                                               :bonus,
204
                                               assignment_files: [])
205
  end
206

207
  protected
1✔
208

209
  def implicit_authorization_target
1✔
210
    Criterion
263✔
211
  end
212
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc