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

MarkUsProject / Markus / 20143075828

11 Dec 2025 06:18PM UTC coverage: 91.513%. Remained the same
20143075828

Pull #7763

github

web-flow
Merge 9f55e660a into 3421ef3b2
Pull Request #7763: Release 2.9.0

914 of 1805 branches covered (50.64%)

Branch coverage included in aggregate %.

1584 of 1666 new or added lines in 108 files covered. (95.08%)

573 existing lines in 35 files now uncovered.

43650 of 46892 relevant lines covered (93.09%)

121.63 hits per line

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

66.32
/app/controllers/api/grade_entry_forms_controller.rb
1
module Api
1✔
2
  class GradeEntryFormsController < MainApiController
1✔
3
    DEFAULT_FIELDS = [:id, :short_identifier, :description, :due_date, :is_hidden, :visible_on, :visible_until,
1✔
4
                      :show_total].freeze
5

6
    # Sends the contents of the specified grade entry form
7
    # Requires: id
8
    def show
1✔
9
      grade_entry_form = record
1✔
10
      send_data grade_entry_form.export_as_csv(current_role),
1✔
11
                type: 'text/csv',
12
                filename: "#{grade_entry_form.short_identifier}_grades_report.csv",
13
                disposition: 'inline'
14
    rescue ActiveRecord::RecordNotFound => e
15
      # could not find grade entry form
UNCOV
16
      render 'shared/http_status', locals: { code: '404', message: e }, status: :not_found
×
17
    end
18

19
    def index
1✔
20
      grade_entry_forms = get_collection(current_course.grade_entry_forms) || return
18✔
21

22
      include_args = { only: DEFAULT_FIELDS, include: { grade_entry_items: { only: [:id, :name, :out_of] } } }
18✔
23

24
      respond_to do |format|
18✔
25
        format.xml do
18✔
26
          xml = grade_entry_forms.to_xml(**include_args, root: 'grade_entry_forms', skip_types: 'true')
9✔
27
          render xml: xml
9✔
28
        end
29
        format.json { render json: grade_entry_forms.to_json(include_args) }
27✔
30
      end
31
    end
32

33
    # create a new grade entry form
34
    # Requires:
35
    #   :short_identifier, :description
36
    # Optional:
37
    #   :description, :due_date, :is_hidden
38
    #   grade_entry_items:
39
    #     :name, :out_of, :bonus
40
    def create
1✔
41
      if has_missing_params?([:short_identifier])
10✔
42
        # incomplete/invalid HTTP params
43
        render 'shared/http_status', locals: { code: '422', message:
2✔
44
          HttpStatusHelper::ERROR_CODE['message']['422'] }, status: :unprocessable_content
45
        return
2✔
46
      end
47

48
      # check if there is an existing assignment
49
      form = current_course.grade_entry_forms.find_by(short_identifier: params[:short_identifier])
8✔
50
      unless form.nil?
8✔
51
        render 'shared/http_status', locals: { code: '409', message:
1✔
52
          'Grade Entry Form already exists' }, status: :conflict
53
        return
1✔
54
      end
55

56
      ApplicationRecord.transaction do
7✔
57
        create_params = params.permit(*DEFAULT_FIELDS)
7✔
58
        create_params[:is_hidden] ||= false
7✔
59
        create_params[:description] ||= ''
7✔
60
        create_params[:course_id] = params[:course_id]
7✔
61
        new_form = GradeEntryForm.new(create_params)
7✔
62
        unless new_form.save
7✔
63
          render 'shared/http_status', locals: { code: '422', message:
3✔
64
            new_form.errors.full_messages.first }, status: :unprocessable_content
65
          raise ActiveRecord::Rollback
3✔
66
        end
67

68
        params[:grade_entry_items]&.each&.with_index do |column_params, i|
4✔
UNCOV
69
          column_params = column_params.permit(:name, :out_of, :bonus).to_h.symbolize_keys
×
70
          grade_item = new_form.grade_entry_items.build(**column_params, position: i + 1)
×
71
          unless grade_item.save
×
72
            render 'shared/http_status', locals: { code: '422', message:
×
73
              grade_item.errors.full_messages.first }, status: :unprocessable_content
UNCOV
74
            raise ActiveRecord::Rollback
×
75
          end
76
        end
77
        render 'shared/http_status', locals: { code: '201', message:
4✔
78
          HttpStatusHelper::ERROR_CODE['message']['201'] }, status: :created
79
      end
80
    end
81

82
    # create a new grade entry form
83
    # params:
84
    #   :short_identifier, :description, :date, :is_hidden
85
    #   grade_entry_items:
86
    #     :id, :name, :out_of, :bonus
87
    #
88
    # if the grade_entry_items id param is set, an existing item will be
89
    # updated, otherwise a new grade_entry_item will be created
90
    def update
1✔
91
      # check if there is an existing assignment
92
      form = record
2✔
93
      if form.nil?
2✔
UNCOV
94
        render 'shared/http_status', locals: { code: '404', message:
×
95
          'Grade Entry Form not found' }, status: :not_found
UNCOV
96
        return
×
97
      end
98

99
      ApplicationRecord.transaction do
2✔
100
        update_params = params.permit(*DEFAULT_FIELDS)
2✔
101
        unless form.update(update_params)
2✔
102
          render 'shared/http_status', locals: { code: '500', message:
1✔
103
            form.errors.full_messages.first }, status: :internal_server_error
104
          raise ActiveRecord::Rollback
1✔
105
        end
106

107
        position = form.grade_entry_items.count
1✔
108
        params[:grade_entry_items]&.each do |column_params|
1✔
UNCOV
109
          if column_params[:id].nil?
×
110
            column_params = column_params.permit(:name, :out_of, :bonus).to_h.symbolize_keys
×
111
            grade_item = form.grade_entry_items.build(**column_params, position: position += 1)
×
112
            unless grade_item.save
×
113
              render 'shared/http_status', locals: { code: '500', message:
×
114
                grade_item.errors.full_messages.first }, status: :internal_server_error
UNCOV
115
              raise ActiveRecord::Rollback
×
116
            end
117
          else
UNCOV
118
            column_params = column_params.permit(:id, :name, :out_of, :bonus).to_h.symbolize_keys
×
119
            grade_item = form.grade_entry_items.where(id: column_params[:id]).first
×
120
            if grade_item.nil?
×
121
              render 'shared/http_status', locals: { code: '404', message:
×
122
                "Grade Entry Item with id=#{column_params[:id]} not found" }, status: :not_found
UNCOV
123
              raise ActiveRecord::Rollback
×
124
            end
UNCOV
125
            unless grade_item.update(column_params)
×
126
              render 'shared/http_status', locals: { code: '500', message:
×
127
                grade_item.errors.full_messages.first }, status: :internal_server_error
UNCOV
128
              raise ActiveRecord::Rollback
×
129
            end
130
          end
131
        end
132
        render 'shared/http_status', locals: { code: '200', message:
1✔
133
          HttpStatusHelper::ERROR_CODE['message']['200'] }, status: :ok
134
      end
135
    end
136

137
    def update_grades
1✔
138
      if has_missing_params?([:user_name, :grade_entry_items])
3✔
139
        # incomplete/invalid HTTP params
UNCOV
140
        render 'shared/http_status', locals: { code: '422', message:
×
141
          HttpStatusHelper::ERROR_CODE['message']['422'] }, status: :unprocessable_content
UNCOV
142
        return
×
143
      end
144

145
      grade_entry_form = record
3✔
146

147
      grade_entry_student = grade_entry_form.grade_entry_students
3✔
148
                                            .joins(:user)
149
                                            .where('users.user_name': params[:user_name])
150
                                            .first
151

152
      if grade_entry_student.nil?
3✔
153
        # There is no student with that user_name
UNCOV
154
        render 'shared/http_status', locals: { code: '422', message:
×
155
          'There is no student with that user_name' }, status: :unprocessable_content
UNCOV
156
        return
×
157
      end
158

159
      Grade.transaction do
3✔
160
        params[:grade_entry_items].each do |item, score|
3✔
161
          grade_entry_item = GradeEntryItem.find_by(name: item, assessment_id: params[:id])
3✔
162

163
          if grade_entry_item.nil?
3✔
164
            # There is no such grade entry item
UNCOV
165
            render 'shared/http_status', locals: { code: '422', message:
×
166
              "There is no grade entry item named #{item}" }, status: :unprocessable_content
UNCOV
167
            raise ActiveRecord::Rollback
×
168
          end
169
          grade = grade_entry_student.grades.find_or_create_by(grade_entry_item_id: grade_entry_item.id)
3✔
170
          grade.update(grade: score)
3✔
171
        end
172
        if grade_entry_student.save
3✔
173
          render 'shared/http_status', locals: { code: '200', message:
3✔
174
            HttpStatusHelper::ERROR_CODE['message']['200'] }, status: :ok
175
        else
176
          # Some error occurred (including invalid mark)
UNCOV
177
          render 'shared/http_status', locals: { code: '500', message:
×
178
            grade_entry_student.errors.full_messages.first }, status: :internal_server_error
UNCOV
179
          raise ActiveRecord::Rollback
×
180
        end
181
      end
182
    end
183

184
    def destroy
1✔
185
      # check if the grade entry form exists
186
      grade_entry_form = record
2✔
187
      if grade_entry_form.nil?
2✔
UNCOV
188
        render 'shared/http_status', locals: { code: '404', message:
×
189
          'Grade Entry Form not found' }, status: :not_found
UNCOV
190
        return
×
191
      end
192
      # delete the grade entry form
193
      begin
194
        grade_entry_form.destroy!
2✔
195
        render 'shared/http_status',
1✔
196
               locals: { code: '200',
197
                         message: 'Grade Entry Form successfully deleted' }, status: :ok
198
      rescue ActiveRecord::RecordNotDestroyed
199
        render 'shared/http_status',
1✔
200
               locals: { code: :conflict,
201
                         message: 'Grade Entry Form contains non-nil grades' }, status: :conflict
202
      end
203
    end
204
  end
205
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

© 2026 Coveralls, Inc