Fix error, submission, hints and help views
This commit is contained in:
@ -14,9 +14,6 @@ class ApplicationController < ActionController::Base
|
|||||||
@current_user ||= ExternalUser.find_by(id: session[:external_user_id]) || login_from_session || login_from_other_sources
|
@current_user ||= ExternalUser.find_by(id: session[:external_user_id]) || login_from_session || login_from_other_sources
|
||||||
end
|
end
|
||||||
|
|
||||||
def help
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_not_authorized
|
def render_not_authorized
|
||||||
redirect_to(:root, alert: t('application.not_authorized'))
|
redirect_to(:root, alert: t('application.not_authorized'))
|
||||||
end
|
end
|
||||||
|
45
app/controllers/code_ocean/errors_controller.rb
Normal file
45
app/controllers/code_ocean/errors_controller.rb
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
module CodeOcean
|
||||||
|
class ErrorsController < ApplicationController
|
||||||
|
before_action :set_execution_environment
|
||||||
|
|
||||||
|
def authorize!
|
||||||
|
authorize(@error || @errors)
|
||||||
|
end
|
||||||
|
private :authorize!
|
||||||
|
|
||||||
|
def create
|
||||||
|
@error = CodeOcean::Error.new(error_params)
|
||||||
|
authorize!
|
||||||
|
hint = Whistleblower.new(execution_environment: @error.execution_environment).generate_hint(@error.message)
|
||||||
|
respond_to do |format|
|
||||||
|
format.json do
|
||||||
|
if hint
|
||||||
|
render(json: {hint: hint})
|
||||||
|
else
|
||||||
|
head (@error.save ? :created : :unprocessable_entity)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def error_params
|
||||||
|
params[:error].permit(:message, :submission_id).merge(execution_environment_id: @execution_environment.id) if params[:error].present?
|
||||||
|
end
|
||||||
|
private :error_params
|
||||||
|
|
||||||
|
def index
|
||||||
|
@errors = CodeOcean::Error.for_execution_environment(@execution_environment).grouped_by_message.paginate(page: params[:page])
|
||||||
|
authorize!
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_execution_environment
|
||||||
|
@execution_environment = ExecutionEnvironment.find(params[:execution_environment_id])
|
||||||
|
end
|
||||||
|
private :set_execution_environment
|
||||||
|
|
||||||
|
def show
|
||||||
|
@error = CodeOcean::Error.find(params[:id])
|
||||||
|
authorize!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,43 +0,0 @@
|
|||||||
class ErrorsController < ApplicationController
|
|
||||||
before_action :set_execution_environment
|
|
||||||
|
|
||||||
def authorize!
|
|
||||||
authorize(@error || @errors)
|
|
||||||
end
|
|
||||||
private :authorize!
|
|
||||||
|
|
||||||
def create
|
|
||||||
@error = Error.new(error_params)
|
|
||||||
authorize!
|
|
||||||
hint = Whistleblower.new(execution_environment: @error.execution_environment).generate_hint(@error.message)
|
|
||||||
respond_to do |format|
|
|
||||||
format.json do
|
|
||||||
if hint
|
|
||||||
render(json: {hint: hint})
|
|
||||||
else
|
|
||||||
head (@error.save ? :created : :unprocessable_entity)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def error_params
|
|
||||||
params[:error].permit(:message, :submission_id).merge(execution_environment_id: @execution_environment.id) if params[:error].present?
|
|
||||||
end
|
|
||||||
private :error_params
|
|
||||||
|
|
||||||
def index
|
|
||||||
@errors = Error.for_execution_environment(@execution_environment).grouped_by_message.paginate(page: params[:page])
|
|
||||||
authorize!
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_execution_environment
|
|
||||||
@execution_environment = ExecutionEnvironment.find(params[:execution_environment_id])
|
|
||||||
end
|
|
||||||
private :set_execution_environment
|
|
||||||
|
|
||||||
def show
|
|
||||||
@error = Error.find(params[:id])
|
|
||||||
authorize!
|
|
||||||
end
|
|
||||||
end
|
|
@ -366,7 +366,7 @@ class SubmissionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def store_error(stderr)
|
def store_error(stderr)
|
||||||
::Error.create(submission_id: @submission.id, execution_environment_id: @submission.execution_environment.id, message: stderr)
|
CodeOcean::Error.create(submission_id: @submission.id, execution_environment_id: @submission.execution_environment.id, message: stderr)
|
||||||
end
|
end
|
||||||
private :store_error
|
private :store_error
|
||||||
|
|
||||||
|
19
app/models/code_ocean/error.rb
Normal file
19
app/models/code_ocean/error.rb
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
module CodeOcean
|
||||||
|
class Error < ApplicationRecord
|
||||||
|
belongs_to :execution_environment
|
||||||
|
|
||||||
|
scope :for_execution_environment, ->(execution_environment) { where(execution_environment_id: execution_environment.id) }
|
||||||
|
scope :grouped_by_message, -> { select('MAX(created_at) AS created_at, MAX(id) AS id, message, COUNT(id) AS count').group(:message).order('count DESC') }
|
||||||
|
|
||||||
|
validates :execution_environment_id, presence: true
|
||||||
|
validates :message, presence: true
|
||||||
|
|
||||||
|
def self.nested_resource?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
id.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,13 +0,0 @@
|
|||||||
class Error < ApplicationRecord
|
|
||||||
belongs_to :execution_environment
|
|
||||||
|
|
||||||
scope :for_execution_environment, ->(execution_environment) { where(execution_environment_id: execution_environment.id) }
|
|
||||||
scope :grouped_by_message, -> { select('MAX(created_at) AS created_at, MAX(id) AS id, message, COUNT(id) AS count').group(:message).order('count DESC') }
|
|
||||||
|
|
||||||
validates :execution_environment_id, presence: true
|
|
||||||
validates :message, presence: true
|
|
||||||
|
|
||||||
def self.nested_resource?
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
|
7
app/policies/code_ocean/error_policy.rb
Normal file
7
app/policies/code_ocean/error_policy.rb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module CodeOcean
|
||||||
|
class ErrorPolicy < AdminOrAuthorPolicy
|
||||||
|
def author?
|
||||||
|
@user == @record.execution_environment.author
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,5 +0,0 @@
|
|||||||
class ErrorPolicy < AdminOrAuthorPolicy
|
|
||||||
def author?
|
|
||||||
@user == @record.execution_environment.author
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,6 +1,6 @@
|
|||||||
- if current_user.try(:internal_user?)
|
- if current_user.try(:internal_user?)
|
||||||
ul.breadcrumb
|
ul.breadcrumb
|
||||||
- if model = Kernel.const_get(controller_name.classify) rescue nil
|
- if model = Kernel.const_get(controller_path.classify) rescue nil
|
||||||
- object = model.find_by(id: params[:id])
|
- object = model.find_by(id: params[:id])
|
||||||
- if model.try(:nested_resource?)
|
- if model.try(:nested_resource?)
|
||||||
li = model.model_name.human(count: 2)
|
li = model.model_name.human(count: 2)
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
li = link_to(t('breadcrumbs.statistics.show'), statistics_path)
|
li = link_to(t('breadcrumbs.statistics.show'), statistics_path)
|
||||||
li.divider
|
li.divider
|
||||||
= render('navigation_submenu', title: t('activerecord.models.exercise.other'),
|
= render('navigation_submenu', title: t('activerecord.models.exercise.other'),
|
||||||
models: [Exercise, ExerciseCollection, ProxyExercise, Tag], link: exercises_path, cached: true)
|
models: [Exercise, ExerciseCollection, ProxyExercise, Tag, Submission], link: exercises_path, cached: true)
|
||||||
= render('navigation_submenu', title: t('navigation.sections.users'), models: [InternalUser, ExternalUser],
|
= render('navigation_submenu', title: t('navigation.sections.users'), models: [InternalUser, ExternalUser],
|
||||||
cached: true)
|
cached: true)
|
||||||
= render('navigation_collection_link', model: ExecutionEnvironment, cached: true)
|
= render('navigation_collection_link', model: ExecutionEnvironment, cached: true)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
h1 = ::Error.model_name.human(count: 2)
|
h1 = CodeOcean::Error.model_name.human(count: 2)
|
||||||
|
|
||||||
.table-responsive
|
.table-responsive
|
||||||
table.table
|
table.table
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
th = t('.count')
|
th = t('errors.index.count')
|
||||||
th = t('activerecord.attributes.error.message')
|
th = t('activerecord.attributes.error.message')
|
||||||
th = t('shared.created_at')
|
th = t('shared.created_at')
|
||||||
th = t('shared.actions')
|
th = t('shared.actions')
|
@ -1,4 +1,4 @@
|
|||||||
h1 = ::Error.model_name.human
|
h1 = CodeOcean::Error.model_name.human
|
||||||
|
|
||||||
= row(label: 'error.message', value: @error.message)
|
= row(label: 'error.message', value: @error.message)
|
||||||
= row(label: 'shared.created_at', value: l(@error.created_at, format: :short))
|
= row(label: 'shared.created_at', value: l(@error.created_at, format: :short))
|
@ -1 +1,3 @@
|
|||||||
= link_to(t('shared.edit'), local_assigns.fetch(:path, send(:"edit_#{object.class.name.underscore}_path", object)), class: 'btn btn-default pull-right')
|
// default value for fetch will always be evaluated even if it is not returned
|
||||||
|
- link_target = local_assigns.fetch(:path, false) || send(:"edit_#{object.class.name.underscore}_path", object)
|
||||||
|
= link_to(t('shared.edit'), link_target, class: 'btn btn-default pull-right')
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
- if policy(model).new?
|
- if policy(model).new?
|
||||||
a.btn.btn-success href=local_assigns.fetch(:path, send(:"new_#{model.model_name.singular}_path"))
|
// default value for fetch will always be evaluated even if it is not returned
|
||||||
|
- href_target = local_assigns.fetch(:path, false) || send(:"new_#{model.model_name.singular}_path")
|
||||||
|
a.btn.btn-success href=href_target
|
||||||
i.fa.fa-plus
|
i.fa.fa-plus
|
||||||
= t('shared.new_model', model: model.model_name.human)
|
= t('shared.new_model', model: model.model_name.human)
|
||||||
|
@ -28,7 +28,7 @@ Rails.application.routes.draw do
|
|||||||
delete '/comment_by_id', to: 'comments#destroy_by_id'
|
delete '/comment_by_id', to: 'comments#destroy_by_id'
|
||||||
put '/comments', to: 'comments#update'
|
put '/comments', to: 'comments#update'
|
||||||
|
|
||||||
resources :subscriptions do
|
resources :subscriptions, only: [:create, :destroy] do
|
||||||
member do
|
member do
|
||||||
get :unsubscribe, to: 'subscriptions#destroy'
|
get :unsubscribe, to: 'subscriptions#destroy'
|
||||||
end
|
end
|
||||||
@ -40,8 +40,6 @@ Rails.application.routes.draw do
|
|||||||
get 'dashboard', to: 'dashboard#show'
|
get 'dashboard', to: 'dashboard#show'
|
||||||
end
|
end
|
||||||
|
|
||||||
get '/help', to: 'application#help'
|
|
||||||
|
|
||||||
get 'statistics/', to: 'statistics#show'
|
get 'statistics/', to: 'statistics#show'
|
||||||
get 'statistics/graphs', to: 'statistics#graphs'
|
get 'statistics/graphs', to: 'statistics#graphs'
|
||||||
get 'statistics/graphs/user-activity', to: 'statistics#user_activity'
|
get 'statistics/graphs/user-activity', to: 'statistics#user_activity'
|
||||||
@ -65,7 +63,7 @@ Rails.application.routes.draw do
|
|||||||
get :statistics
|
get :statistics
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :errors, only: [:create, :index, :show]
|
resources :errors, only: [:create, :index, :show], controller: 'code_ocean/errors'
|
||||||
resources :hints
|
resources :hints
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ Rails.application.routes.default_url_options = Rails.application.config.action_m
|
|||||||
ExecutionEnvironment.create_factories
|
ExecutionEnvironment.create_factories
|
||||||
|
|
||||||
# errors
|
# errors
|
||||||
Error.create_factories
|
CodeOcean::Error.create_factories
|
||||||
|
|
||||||
# exercises
|
# exercises
|
||||||
@exercises = find_factories_by_class(Exercise).map(&:name).map { |factory_name| [factory_name, FactoryBot.create(factory_name)] }.to_h
|
@exercises = find_factories_by_class(Exercise).map(&:name).map { |factory_name| [factory_name, FactoryBot.create(factory_name)] }.to_h
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
FactoryBot.define do
|
FactoryBot.define do
|
||||||
factory :error, class: Error do
|
factory :error, class: CodeOcean::Error do
|
||||||
association :execution_environment, factory: :ruby
|
association :execution_environment, factory: :ruby
|
||||||
message { "exercise.rb:4:in `<main>': undefined local variable or method `foo' for main:Object (NameError)" }
|
message { "exercise.rb:4:in `<main>': undefined local variable or method `foo' for main:Object (NameError)" }
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
describe Error do
|
describe CodeOcean::Error do
|
||||||
let(:error) { described_class.create }
|
let(:error) { described_class.create }
|
||||||
|
|
||||||
it 'validates the presence of an execution environment' do
|
it 'validates the presence of an execution environment' do
|
||||||
|
Reference in New Issue
Block a user