Skip to content

Commit

Permalink
Merge pull request #417 from rhomeister/csv-export
Browse files Browse the repository at this point in the history
Add button to export submissions data as a CSV file
  • Loading branch information
carlosahs authored Jul 13, 2022
2 parents cd133c4 + f3a0abd commit 0a3f862
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 16 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ config/ansible*

# Ignore master key for decrypting credentials and more.
/config/master.key

# Ignore development dir
development/

# Ignore Redis dump file
dump.rdb
10 changes: 5 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ GEM
mini_portile2 (~> 2.6.1)
racc (~> 1.4)
oauth2 (1.4.1)
faraday (= 1.0.0)
faraday (>= 0.8, < 0.16.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
Expand Down Expand Up @@ -370,7 +370,7 @@ GEM
rspec-collection_matchers (1.2.0)
rspec-expectations (>= 2.99.0.beta1)
rspec-core (3.10.1)
rspec-support (~> 3.11.0)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.11.0)
Expand Down Expand Up @@ -422,15 +422,15 @@ GEM
ffi (~> 1.9)
rake
sawyer (0.8.1)
addressable (= 2.8.0)
faraday (= 1.0.0)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
sentry-raven (3.1.2)
faraday (>= 1.0)
sidekiq (5.2.10)
connection_pool (~> 2.2, >= 2.2.2)
rack (~> 2.0)
rack-protection (>= 1.5.0)
redis (~> 4.5, <= 4.6.0)
redis (~> 4.5, < 4.6.0)
simple_form (5.0.3)
actionpack (>= 5.0)
activemodel (>= 5.0)
Expand Down
12 changes: 10 additions & 2 deletions app/controllers/submissions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ def index
.accessible_by(current_ability)
.find_by(memberships: { user_id: current_user.id })
@active_team = @active_team.try(:decorate)

respond_to do |format|
format.html
format.csv { send_data @submissions.to_csv, filename: 'data.csv' }
end
end

def show
Expand All @@ -42,8 +47,11 @@ def create
end

def rerun_all
@submissions.each(&:rerun_tests)
flash[:success] = 'All submissions have been enqueued for rechecking'
unless @submissions.any?{ |s| !s.checks_completed? }
@submissions.each(&:rerun_tests)
flash[:success] = 'All submissions have been enqueued for rechecking'
end

redirect_to action: 'index'
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/ability.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def setup_test_rights
def setup_submission_rights
can :read, Submission, team: membership_params
can :read, Submission, assignment: { course_id: instructor_course_ids }
can :rerun_all, Submission, assignment: { course_id: instructor_course_ids }
can :rerun_all, Submission if user.instructor? || user.admin?
can %i[new create], Submission, assignment: { course: membership_params }
end

Expand Down
27 changes: 27 additions & 0 deletions app/models/submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ class Submission < ApplicationRecord
self.status ||= :queued
end

def self.to_csv
attributes = %w[id assignment_id assignment_by_name
uploaded_by_id uploaded_by_name created_at
updated_at test_results_count successful_test_results_count
language status]

CSV.generate(headers: true) do |csv|
csv << attributes

all.each do |submission|
csv << attributes.map { |a| submission.send(a) }
end
end
end

after_commit on: :create do
SubmissionCheckWorker.perform_async(id)
end
Expand All @@ -22,12 +37,23 @@ class Submission < ApplicationRecord
next unless checks_completed?

notify_users
successful_test_results_count # store successful tests count in db column
end

def uploaded_by_name
uploaded_by&.name
end

def assignment_by_name
assignment&.name
end

def successful_test_results_count
value = self[:successful_test_results_count]
return value if value

return unless test_results.any?

self.successful_test_results_count = test_results.where(status: %w[success skipped]).count
save
successful_test_results_count
Expand Down Expand Up @@ -72,6 +98,7 @@ def tempdir
end

def rerun_tests
update(successful_test_results_count: nil)
SubmissionCheckWorker.perform_async(id)
end

Expand Down
13 changes: 10 additions & 3 deletions app/views/submissions/index.haml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@

= panel title: Submission.model_name.human.pl, context: :primary do
.panel-body
- if can?(:rerun_all, @submissions)
%p= link_to 'Rerun Submissions',
rerun_all_assignment_submissions_path(@assignment),
- if can?(:rerun_all, Submission)
-# Disable button until all submissions finish rerunning
- if @submissions.any?{ |s| !s.checks_completed? }
%span{:class => "btn btn-default"}= 'Rerun Submissions'
- else
= link_to 'Rerun Submissions',
rerun_all_assignment_submissions_path(@assignment),
class: 'btn btn-primary'
= link_to 'Export Data',
assignment_submissions_path(format: :csv),
class: 'btn btn-primary'
%table.table.table-striped
%thead
Expand Down
1 change: 1 addition & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require_relative 'boot'

require 'csv'
require 'rails/all'

# Require the gems listed in Gemfile, including any gems
Expand Down
10 changes: 5 additions & 5 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.

Expand Down
20 changes: 20 additions & 0 deletions spec/models/submission_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,24 @@
expect(result.submission).to eq submission
end
end

it 'can be exported to csv' do
travel_to Time.zone.local(2022, 1, 1) # '2022-01-01'
assignment = create(:assignment)
assignment.tests << create(:expected_output_test)

user = create(:user, name: 'Ruben')
submission = build(:file_submission, assignment: assignment, uploaded_by: user)
submission.file = File.new('spec/fixtures/dummy_submissions/correct.zip')
submission.save!

expect(submission.reload.status).to eq 'success'

expected_csv = <<~EXPECTED
id,assignment_id,assignment_by_name,uploaded_by_id,uploaded_by_name,created_at,updated_at,test_results_count,successful_test_results_count,language,status
#{submission.id},#{assignment.id},#{assignment.name},#{user.id},Ruben,2022-01-01 00:00:00 UTC,2022-01-01 00:00:00 UTC,1,1,,success
EXPECTED

expect(Submission.to_csv).to eq expected_csv
end
end
3 changes: 3 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'devise'
require 'rails_helper'
# This file was generated by the `rails generate rspec:install` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause
Expand Down Expand Up @@ -34,6 +35,8 @@
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end

config.include ActiveSupport::Testing::TimeHelpers

# rspec-mocks config goes here. You can use an alternate test double
# library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
Expand Down

0 comments on commit 0a3f862

Please sign in to comment.