18
app/assets/javascripts/error_templates.js
Normal file
18
app/assets/javascripts/error_templates.js
Normal file
@ -0,0 +1,18 @@
|
||||
$(function() {
|
||||
if ($.isController('error_templates')) {
|
||||
$('#add-attribute').find('button').on('click', function () {
|
||||
$.ajax(location + '/attribute.json', {
|
||||
method: 'POST',
|
||||
data: {
|
||||
_method: 'PUT',
|
||||
dataType: 'json',
|
||||
error_template_attribute_id: $('#add-attribute').find('select').val()
|
||||
}
|
||||
}).success(function () {
|
||||
location.reload();
|
||||
}).error(function (error) {
|
||||
$.flash.danger({text: error.statusText});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
9
app/assets/stylesheets/error_templates.scss
Normal file
9
app/assets/stylesheets/error_templates.scss
Normal file
@ -0,0 +1,9 @@
|
||||
#add-attribute {
|
||||
display: flex;
|
||||
max-width: 400px;
|
||||
margin-top: 30px;
|
||||
|
||||
button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
@ -9,6 +9,14 @@ module SubmissionScoring
|
||||
assessment = assessor.assess(output)
|
||||
passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score] > 0))
|
||||
testrun_output = passed ? nil : 'message: ' + output[:message].to_s + "\n stdout: " + output[:stdout].to_s + "\n stderr: " + output[:stderr].to_s
|
||||
if !testrun_output.blank?
|
||||
submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(testrun_output)
|
||||
StructuredError.create_from_template(template, testrun_output)
|
||||
end
|
||||
end
|
||||
end
|
||||
Testrun.new(submission: submission, cause: 'assess', file: file, passed: passed, output: testrun_output).save
|
||||
output.merge!(assessment)
|
||||
output.merge!(filename: file.name_with_extension, message: feedback_message(file, output[:score]), weight: file.weight)
|
||||
|
86
app/controllers/error_template_attributes_controller.rb
Normal file
86
app/controllers/error_template_attributes_controller.rb
Normal file
@ -0,0 +1,86 @@
|
||||
class ErrorTemplateAttributesController < ApplicationController
|
||||
before_action :set_error_template_attribute, only: [:show, :edit, :update, :destroy]
|
||||
|
||||
def authorize!
|
||||
authorize(@error_template_attributes || @error_template_attribute)
|
||||
end
|
||||
private :authorize!
|
||||
|
||||
# GET /error_template_attributes
|
||||
# GET /error_template_attributes.json
|
||||
def index
|
||||
@error_template_attributes = ErrorTemplateAttribute.all.order('important DESC', :key, :id).paginate(page: params[:page])
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_template_attributes/1
|
||||
# GET /error_template_attributes/1.json
|
||||
def show
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_template_attributes/new
|
||||
def new
|
||||
@error_template_attribute = ErrorTemplateAttribute.new
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_template_attributes/1/edit
|
||||
def edit
|
||||
authorize!
|
||||
end
|
||||
|
||||
# POST /error_template_attributes
|
||||
# POST /error_template_attributes.json
|
||||
def create
|
||||
@error_template_attribute = ErrorTemplateAttribute.new(error_template_attribute_params)
|
||||
authorize!
|
||||
|
||||
respond_to do |format|
|
||||
if @error_template_attribute.save
|
||||
format.html { redirect_to @error_template_attribute, notice: 'Error template attribute was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @error_template_attribute }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @error_template_attribute.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /error_template_attributes/1
|
||||
# PATCH/PUT /error_template_attributes/1.json
|
||||
def update
|
||||
authorize!
|
||||
respond_to do |format|
|
||||
if @error_template_attribute.update(error_template_attribute_params)
|
||||
format.html { redirect_to @error_template_attribute, notice: 'Error template attribute was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @error_template_attribute }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @error_template_attribute.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /error_template_attributes/1
|
||||
# DELETE /error_template_attributes/1.json
|
||||
def destroy
|
||||
authorize!
|
||||
@error_template_attribute.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to error_template_attributes_url, notice: 'Error template attribute was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_error_template_attribute
|
||||
@error_template_attribute = ErrorTemplateAttribute.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def error_template_attribute_params
|
||||
params[:error_template_attribute].permit(:key, :description, :regex, :important)
|
||||
end
|
||||
end
|
104
app/controllers/error_templates_controller.rb
Normal file
104
app/controllers/error_templates_controller.rb
Normal file
@ -0,0 +1,104 @@
|
||||
class ErrorTemplatesController < ApplicationController
|
||||
before_action :set_error_template, only: [:show, :edit, :update, :destroy, :add_attribute, :remove_attribute]
|
||||
|
||||
def authorize!
|
||||
authorize(@error_templates || @error_template)
|
||||
end
|
||||
private :authorize!
|
||||
|
||||
# GET /error_templates
|
||||
# GET /error_templates.json
|
||||
def index
|
||||
@error_templates = ErrorTemplate.all.order(:execution_environment_id, :name).paginate(page: params[:page])
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_templates/1
|
||||
# GET /error_templates/1.json
|
||||
def show
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_templates/new
|
||||
def new
|
||||
@error_template = ErrorTemplate.new
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /error_templates/1/edit
|
||||
def edit
|
||||
authorize!
|
||||
end
|
||||
|
||||
# POST /error_templates
|
||||
# POST /error_templates.json
|
||||
def create
|
||||
@error_template = ErrorTemplate.new(error_template_params)
|
||||
authorize!
|
||||
|
||||
respond_to do |format|
|
||||
if @error_template.save
|
||||
format.html { redirect_to @error_template, notice: 'Error template was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @error_template }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @error_template.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /error_templates/1
|
||||
# PATCH/PUT /error_templates/1.json
|
||||
def update
|
||||
authorize!
|
||||
respond_to do |format|
|
||||
if @error_template.update(error_template_params)
|
||||
format.html { redirect_to @error_template, notice: 'Error template was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @error_template }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @error_template.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /error_templates/1
|
||||
# DELETE /error_templates/1.json
|
||||
def destroy
|
||||
authorize!
|
||||
@error_template.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to error_templates_url, notice: 'Error template was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
def add_attribute
|
||||
authorize!
|
||||
@error_template.error_template_attributes << ErrorTemplateAttribute.find(params['error_template_attribute_id'])
|
||||
respond_to do |format|
|
||||
format.html { redirect_to @error_template }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
def remove_attribute
|
||||
authorize!
|
||||
@error_template.error_template_attributes.delete(ErrorTemplateAttribute.find(params['error_template_attribute_id']))
|
||||
respond_to do |format|
|
||||
format.html { redirect_to @error_template }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_error_template
|
||||
@error_template = ErrorTemplate.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def error_template_params
|
||||
params[:error_template].permit(:name, :execution_environment_id, :signature, :description, :hint)
|
||||
end
|
||||
end
|
@ -6,7 +6,7 @@ class SubmissionsController < ApplicationController
|
||||
include SubmissionScoring
|
||||
include Tubesock::Hijack
|
||||
|
||||
before_action :set_submission, only: [:download, :download_file, :render_file, :run, :score, :show, :statistics, :stop, :test]
|
||||
before_action :set_submission, only: [:download, :download_file, :render_file, :run, :score, :extract_errors, :show, :statistics, :stop, :test]
|
||||
before_action :set_docker_client, only: [:run, :test]
|
||||
before_action :set_files, only: [:download, :download_file, :render_file, :show]
|
||||
before_action :set_file, only: [:download_file, :render_file]
|
||||
@ -191,6 +191,9 @@ class SubmissionsController < ApplicationController
|
||||
end
|
||||
|
||||
def kill_socket(tubesock)
|
||||
# search for errors and save them as StructuredError (for scoring runs see submission_scoring.rb)
|
||||
extract_errors
|
||||
|
||||
# save the output of this "run" as a "testrun" (scoring runs are saved in submission_scoring.rb)
|
||||
save_run_output
|
||||
|
||||
@ -199,6 +202,17 @@ class SubmissionsController < ApplicationController
|
||||
tubesock.close
|
||||
end
|
||||
|
||||
def extract_errors
|
||||
if !@message_buffer.blank?
|
||||
@submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(@message_buffer)
|
||||
StructuredError.create_from_template(template, @message_buffer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def handle_message(message, tubesock, container)
|
||||
@run_output ||= ""
|
||||
# Handle special commands first
|
||||
|
2
app/helpers/error_template_attributes_helper.rb
Normal file
2
app/helpers/error_template_attributes_helper.rb
Normal file
@ -0,0 +1,2 @@
|
||||
module ErrorTemplateAttributesHelper
|
||||
end
|
2
app/helpers/error_templates_helper.rb
Normal file
2
app/helpers/error_templates_helper.rb
Normal file
@ -0,0 +1,2 @@
|
||||
module ErrorTemplatesHelper
|
||||
end
|
8
app/models/error_template.rb
Normal file
8
app/models/error_template.rb
Normal file
@ -0,0 +1,8 @@
|
||||
class ErrorTemplate < ActiveRecord::Base
|
||||
belongs_to :execution_environment
|
||||
has_and_belongs_to_many :error_template_attributes
|
||||
|
||||
def to_s
|
||||
"#{id} [#{name}]"
|
||||
end
|
||||
end
|
7
app/models/error_template_attribute.rb
Normal file
7
app/models/error_template_attribute.rb
Normal file
@ -0,0 +1,7 @@
|
||||
class ErrorTemplateAttribute < ActiveRecord::Base
|
||||
has_and_belongs_to_many :error_template
|
||||
|
||||
def to_s
|
||||
"#{id} [#{key}]"
|
||||
end
|
||||
end
|
@ -11,6 +11,7 @@ class ExecutionEnvironment < ActiveRecord::Base
|
||||
has_many :exercises
|
||||
belongs_to :file_type
|
||||
has_many :hints
|
||||
has_many :error_templates
|
||||
|
||||
scope :with_exercises, -> { where('id IN (SELECT execution_environment_id FROM exercises)') }
|
||||
|
||||
|
12
app/models/structured_error.rb
Normal file
12
app/models/structured_error.rb
Normal file
@ -0,0 +1,12 @@
|
||||
class StructuredError < ActiveRecord::Base
|
||||
belongs_to :error_template
|
||||
belongs_to :file, class_name: 'CodeOcean::File'
|
||||
|
||||
def self.create_from_template(template, message_buffer)
|
||||
instance = self.create(error_template: template)
|
||||
template.error_template_attributes.each do |attribute|
|
||||
StructuredErrorAttribute.create_from_template(attribute, instance, message_buffer)
|
||||
end
|
||||
instance
|
||||
end
|
||||
end
|
17
app/models/structured_error_attribute.rb
Normal file
17
app/models/structured_error_attribute.rb
Normal file
@ -0,0 +1,17 @@
|
||||
class StructuredErrorAttribute < ActiveRecord::Base
|
||||
belongs_to :structured_error
|
||||
belongs_to :error_template_attribute
|
||||
|
||||
def self.create_from_template(attribute, structured_error, message_buffer)
|
||||
match = false
|
||||
value = nil
|
||||
result = message_buffer.match(attribute.regex)
|
||||
if result != nil
|
||||
match = true
|
||||
if result.captures.size > 0
|
||||
value = result.captures[0]
|
||||
end
|
||||
end
|
||||
self.create(structured_error: structured_error, error_template_attribute: attribute, value: value, match: match)
|
||||
end
|
||||
end
|
3
app/policies/error_template_attribute_policy.rb
Normal file
3
app/policies/error_template_attribute_policy.rb
Normal file
@ -0,0 +1,3 @@
|
||||
class ErrorTemplateAttributePolicy < AdminOnlyPolicy
|
||||
|
||||
end
|
9
app/policies/error_template_policy.rb
Normal file
9
app/policies/error_template_policy.rb
Normal file
@ -0,0 +1,9 @@
|
||||
class ErrorTemplatePolicy < AdminOnlyPolicy
|
||||
def add_attribute?
|
||||
admin?
|
||||
end
|
||||
|
||||
def remove_attribute?
|
||||
admin?
|
||||
end
|
||||
end
|
@ -8,7 +8,8 @@
|
||||
- if current_user.admin?
|
||||
li = link_to(t('breadcrumbs.dashboard.show'), admin_dashboard_path)
|
||||
li.divider
|
||||
- models = [ExecutionEnvironment, Exercise, ExerciseCollection, ProxyExercise, Tag, Consumer, CodeHarborLink, ExternalUser, FileType, FileTemplate, InternalUser].sort_by { |model| model.model_name.human(count: 2) }
|
||||
- models = [ExecutionEnvironment, Exercise, ExerciseCollection, ProxyExercise, Tag, Consumer, CodeHarborLink,
|
||||
ErrorTemplate, ErrorTemplateAttribute, ExternalUser, FileType, FileTemplate, InternalUser].sort_by {|model| model.model_name.human(count: 2) }
|
||||
- models.each do |model|
|
||||
- if policy(model).index?
|
||||
li = link_to(model.model_name.human(count: 2), send(:"#{model.model_name.collection}_path"))
|
||||
|
16
app/views/error_template_attributes/_form.html.slim
Normal file
16
app/views/error_template_attributes/_form.html.slim
Normal file
@ -0,0 +1,16 @@
|
||||
= form_for(@error_template_attribute) do |f|
|
||||
= render('shared/form_errors', object: @error_template_attribute)
|
||||
.form-group
|
||||
= f.label(:key)
|
||||
= f.text_field(:key, class: 'form-control', required: true)
|
||||
.form-group
|
||||
= f.label(:description)
|
||||
= f.text_field(:description, class: 'form-control')
|
||||
.form-group
|
||||
= f.label(:regex)
|
||||
= f.text_field(:regex, class: 'form-control', required: true)
|
||||
.help-block == t('error_templates.hints.signature')
|
||||
.form-group
|
||||
= f.check_box(:important)
|
||||
= t('activerecord.attributes.error_template_attribute.important')
|
||||
.actions = render('shared/submit_button', f: f, object: @error_template_attribute)
|
3
app/views/error_template_attributes/edit.html.slim
Normal file
3
app/views/error_template_attributes/edit.html.slim
Normal file
@ -0,0 +1,3 @@
|
||||
h1 = @error_template_attribute
|
||||
|
||||
= render('form')
|
28
app/views/error_template_attributes/index.html.slim
Normal file
28
app/views/error_template_attributes/index.html.slim
Normal file
@ -0,0 +1,28 @@
|
||||
h1 = ErrorTemplateAttribute.model_name.human(count: 2)
|
||||
|
||||
.table-responsive
|
||||
table.sortable.table
|
||||
thead
|
||||
tr
|
||||
th
|
||||
th = t('activerecord.attributes.error_template_attribute.key')
|
||||
th = t('activerecord.attributes.error_template_attribute.description')
|
||||
th = t('activerecord.attributes.error_template_attribute.regex')
|
||||
th colspan=5 = t('shared.actions')
|
||||
tbody
|
||||
- @error_template_attributes.each do |error_template_attribute|
|
||||
tr
|
||||
td
|
||||
- if error_template_attribute.important
|
||||
span class="fa fa-star" aria-hidden="true"
|
||||
- else
|
||||
span class="fa fa-star-o" aria-hidden="true"
|
||||
td = error_template_attribute.key
|
||||
td = error_template_attribute.description
|
||||
td = error_template_attribute.regex
|
||||
td = link_to(t('shared.show'), error_template_attribute)
|
||||
td = link_to(t('shared.edit'), edit_error_template_attribute_path(error_template_attribute))
|
||||
td = link_to(t('shared.destroy'), error_template_attribute, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
|
||||
= render('shared/pagination', collection: @error_template_attributes)
|
||||
p = render('shared/new_button', model: ErrorTemplateAttribute)
|
3
app/views/error_template_attributes/new.html.slim
Normal file
3
app/views/error_template_attributes/new.html.slim
Normal file
@ -0,0 +1,3 @@
|
||||
h1 = t('shared.new_model', model: ErrorTemplateAttribute.model_name.human)
|
||||
|
||||
= render('form')
|
8
app/views/error_template_attributes/show.html.slim
Normal file
8
app/views/error_template_attributes/show.html.slim
Normal file
@ -0,0 +1,8 @@
|
||||
h1
|
||||
= @error_template_attribute
|
||||
= render('shared/edit_button', object: @error_template_attribute)
|
||||
|
||||
- [:key, :description, :regex, :important].each do |attribute|
|
||||
= row(label: "error_template_attribute.#{attribute}", value: @error_template_attribute.send(attribute))
|
||||
|
||||
// todo: used by
|
19
app/views/error_templates/_form.html.slim
Normal file
19
app/views/error_templates/_form.html.slim
Normal file
@ -0,0 +1,19 @@
|
||||
= form_for(@error_template) do |f|
|
||||
= render('shared/form_errors', object: @error_template)
|
||||
.form-group
|
||||
= f.label(:name)
|
||||
= f.text_field(:name, class: 'form-control', required: true)
|
||||
.form-group
|
||||
= f.label(:execution_environment_id)
|
||||
= f.collection_select(:execution_environment_id, ExecutionEnvironment.all.order(:name), :id, :name, {include_blank: false}, class: 'form-control')
|
||||
.form-group
|
||||
= f.label(:signature)
|
||||
= f.text_field(:signature, class: 'form-control')
|
||||
.help-block == t('error_templates.hints.signature')
|
||||
.form-group
|
||||
= f.label(:description)
|
||||
= f.text_field(:description, class: 'form-control')
|
||||
.form-group
|
||||
= f.label(:hint)
|
||||
= f.text_field(:hint, class: 'form-control')
|
||||
.actions = render('shared/submit_button', f: f, object: @error_template)
|
3
app/views/error_templates/edit.html.slim
Normal file
3
app/views/error_templates/edit.html.slim
Normal file
@ -0,0 +1,3 @@
|
||||
h1 = @error_template
|
||||
|
||||
= render('form')
|
22
app/views/error_templates/index.html.slim
Normal file
22
app/views/error_templates/index.html.slim
Normal file
@ -0,0 +1,22 @@
|
||||
h1 = ErrorTemplate.model_name.human(count: 2)
|
||||
|
||||
.table-responsive
|
||||
table.sortable.table
|
||||
thead
|
||||
tr
|
||||
th = t('activerecord.attributes.error_template.name')
|
||||
th = t('activerecord.attributes.error_template.description')
|
||||
th = t('activerecord.attributes.exercise.execution_environment')
|
||||
th colspan=3 = t('shared.actions')
|
||||
tbody
|
||||
- @error_templates.each do |error_template|
|
||||
tr
|
||||
td = error_template.name
|
||||
td = error_template.description
|
||||
td = link_to(error_template.execution_environment)
|
||||
td = link_to(t('shared.show'), error_template)
|
||||
td = link_to(t('shared.edit'), edit_error_template_path(error_template))
|
||||
td = link_to(t('shared.destroy'), error_template, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
|
||||
|
||||
= render('shared/pagination', collection: @error_templates)
|
||||
p = render('shared/new_button', model: ErrorTemplate)
|
3
app/views/error_templates/new.html.slim
Normal file
3
app/views/error_templates/new.html.slim
Normal file
@ -0,0 +1,3 @@
|
||||
h1 = t('shared.new_model', model: ErrorTemplate.model_name.human)
|
||||
|
||||
= render('form')
|
40
app/views/error_templates/show.html.slim
Normal file
40
app/views/error_templates/show.html.slim
Normal file
@ -0,0 +1,40 @@
|
||||
h1
|
||||
= @error_template
|
||||
= render('shared/edit_button', object: @error_template)
|
||||
|
||||
= row(label: 'error_template.name', value: @error_template.name)
|
||||
= row(label: 'exercise.execution_environment', value: link_to(@error_template.execution_environment))
|
||||
- [:signature, :description, :hint].each do |attribute|
|
||||
= row(label: "error_template.#{attribute}", value: @error_template.send(attribute))
|
||||
|
||||
h3
|
||||
= t 'error_templates.attributes'
|
||||
|
||||
.table-responsive
|
||||
table.sortable.table
|
||||
thead
|
||||
tr
|
||||
th
|
||||
th = t('activerecord.attributes.error_template_attribute.key')
|
||||
th = t('activerecord.attributes.error_template_attribute.description')
|
||||
th = t('activerecord.attributes.error_template_attribute.regex')
|
||||
th colspan=3 = t('shared.actions')
|
||||
tbody
|
||||
- @error_template.error_template_attributes.order('important DESC', :key).each do |attribute|
|
||||
tr
|
||||
td
|
||||
- if attribute.important
|
||||
span class="fa fa-star" aria-hidden="true"
|
||||
- else
|
||||
span class="fa fa-star-o" aria-hidden="true"
|
||||
td = attribute.key
|
||||
td = attribute.description
|
||||
td = attribute.regex
|
||||
td = link_to(t('shared.show'), attribute)
|
||||
td = link_to(t('shared.destroy'), attribute_error_template_url(:error_template_attribute_id => attribute.id), :method => :delete)
|
||||
|
||||
#add-attribute
|
||||
= collection_select({}, :error_template_attribute_id,
|
||||
ErrorTemplateAttribute.where.not(id: @error_template.error_template_attributes.select(:id).to_a).order('important DESC', :key),
|
||||
:id, :key, {include_blank: false}, class: '')
|
||||
button.btn.btn-default = t('error_templates.add_attribute')
|
@ -111,6 +111,16 @@ de:
|
||||
name: "Name"
|
||||
file_type: "Dateityp"
|
||||
content: "Code"
|
||||
error_template:
|
||||
name: Name
|
||||
signature: Regulärer Ausdruck
|
||||
description: Beschreibung
|
||||
hint: Hinweis
|
||||
error_template_attribute:
|
||||
important: "Wichtig"
|
||||
key: "Name"
|
||||
description: "Beschreibung"
|
||||
regex: "Regulärer Ausdruck"
|
||||
exercise_collections:
|
||||
id: "ID"
|
||||
name: "Name"
|
||||
@ -126,6 +136,12 @@ de:
|
||||
error:
|
||||
one: Fehler
|
||||
other: Fehler
|
||||
error_template:
|
||||
one: Fehlertemplate
|
||||
other: Fehlertemplates
|
||||
error_template_attribute:
|
||||
one: Fehlertemplatettribut
|
||||
other: Fehlertemplatettribute
|
||||
execution_environment:
|
||||
one: Ausführungsumgebung
|
||||
other: Ausführungsumgebungen
|
||||
@ -642,10 +658,14 @@ de:
|
||||
estimated_time_20_to_30: "zwischen 20 und 30 Minuten"
|
||||
estimated_time_more_30: "mehr als 30 Minuten"
|
||||
working_time: "Geschätze Bearbeitungszeit für diese Aufgabe:"
|
||||
error_templates:
|
||||
hints:
|
||||
signature: "Ein regulärer Ausdruck in Ruby-Syntax und ohne führende und schließende \"/\""
|
||||
attributes: "Attribute"
|
||||
add_attribute: "Attribut hinzufügen"
|
||||
comments:
|
||||
deleted: "Gelöscht"
|
||||
save_update: "Speichern"
|
||||
subscriptions:
|
||||
successfully_unsubscribed: "Ihr Abonnement für weitere Kommentare auf dieser Kommentaranfrage wurde erfolgreich beendet."
|
||||
subscription_not_existent: "Das Abonnement, von dem Sie sich abmelden wollen, existiert nicht."
|
||||
|
||||
|
@ -111,6 +111,16 @@ en:
|
||||
name: "Name"
|
||||
file_type: "File Type"
|
||||
content: "Content"
|
||||
error_template:
|
||||
name: Name
|
||||
signature: Signature Regular Expression
|
||||
description: Description
|
||||
hint: Hint
|
||||
error_template_attribute:
|
||||
important: "Important"
|
||||
key: "Identifier"
|
||||
description: "Description"
|
||||
regex: "Regular Expression"
|
||||
exercise_collections:
|
||||
id: "ID"
|
||||
name: "Name"
|
||||
@ -126,6 +136,12 @@ en:
|
||||
error:
|
||||
one: Error
|
||||
other: Errors
|
||||
error_template:
|
||||
one: Error Template
|
||||
other: Error Templates
|
||||
error_template_attribute:
|
||||
one: Error Template Attribute
|
||||
other: Error Template Attributes
|
||||
execution_environment:
|
||||
one: Execution Environment
|
||||
other: Execution Environments
|
||||
@ -642,6 +658,11 @@ en:
|
||||
estimated_time_20_to_30: "between 20 and 30 minutes"
|
||||
estimated_time_more_30: "more than 30 minutes"
|
||||
working_time: "Estimated time working on this exercise:"
|
||||
error_templates:
|
||||
hints:
|
||||
signature: "A regular expression in Ruby syntax without leading and trailing \"/\""
|
||||
attributes: "Attributes"
|
||||
add_attribute: "Add attribute"
|
||||
comments:
|
||||
deleted: "Deleted"
|
||||
save_update: "Save"
|
||||
|
@ -1,6 +1,13 @@
|
||||
FILENAME_REGEXP = /[\w\.]+/ unless Kernel.const_defined?(:FILENAME_REGEXP)
|
||||
|
||||
Rails.application.routes.draw do
|
||||
resources :error_template_attributes
|
||||
resources :error_templates do
|
||||
member do
|
||||
put 'attribute', to: 'error_templates#add_attribute'
|
||||
delete 'attribute', to: 'error_templates#remove_attribute'
|
||||
end
|
||||
end
|
||||
resources :file_templates do
|
||||
collection do
|
||||
get 'by_file_type/:file_type_id', as: :by_file_type, action: :by_file_type
|
||||
|
11
db/migrate/20170703075832_create_error_templates.rb
Normal file
11
db/migrate/20170703075832_create_error_templates.rb
Normal file
@ -0,0 +1,11 @@
|
||||
class CreateErrorTemplates < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :error_templates do |t|
|
||||
t.belongs_to :execution_environment
|
||||
t.string :name
|
||||
t.string :signature
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,11 @@
|
||||
class CreateErrorTemplateAttributes < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :error_template_attributes do |t|
|
||||
t.belongs_to :error_template
|
||||
t.string :key
|
||||
t.string :regex
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
10
db/migrate/20170703080205_create_structured_errors.rb
Normal file
10
db/migrate/20170703080205_create_structured_errors.rb
Normal file
@ -0,0 +1,10 @@
|
||||
class CreateStructuredErrors < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :structured_errors do |t|
|
||||
t.references :error_template
|
||||
t.belongs_to :file
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,11 @@
|
||||
class CreateStructuredErrorAttributes < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :structured_error_attributes do |t|
|
||||
t.belongs_to :structured_error
|
||||
t.references :error_template_attribute
|
||||
t.string :value
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,9 @@
|
||||
class AddDescriptionAndHintToErrorTemplate < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :error_templates, :description, :text
|
||||
add_column :error_templates, :hint, :text
|
||||
|
||||
add_column :error_template_attributes, :description, :text
|
||||
add_column :error_template_attributes, :important, :boolean
|
||||
end
|
||||
end
|
@ -0,0 +1,6 @@
|
||||
class ChangeErrorTemplateAttributeRelationshipToNToM < ActiveRecord::Migration
|
||||
def change
|
||||
remove_belongs_to :error_template_attributes, :error_template
|
||||
create_join_table :error_templates, :error_template_attributes
|
||||
end
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
class AddMatchToStructuredErrorAttribute < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :structured_error_attributes, :match, :boolean
|
||||
end
|
||||
end
|
40
db/schema.rb
40
db/schema.rb
@ -47,6 +47,30 @@ ActiveRecord::Schema.define(version: 20170920145852) do
|
||||
t.string "oauth_secret", limit: 255
|
||||
end
|
||||
|
||||
create_table "error_template_attributes", force: :cascade do |t|
|
||||
t.string "key"
|
||||
t.string "regex"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "description"
|
||||
t.boolean "important"
|
||||
end
|
||||
|
||||
create_table "error_template_attributes_templates", id: false, force: :cascade do |t|
|
||||
t.integer "error_template_id", null: false
|
||||
t.integer "error_template_attribute_id", null: false
|
||||
end
|
||||
|
||||
create_table "error_templates", force: :cascade do |t|
|
||||
t.integer "execution_environment_id"
|
||||
t.string "name"
|
||||
t.string "signature"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "description"
|
||||
t.text "hint"
|
||||
end
|
||||
|
||||
create_table "errors", force: :cascade do |t|
|
||||
t.integer "execution_environment_id"
|
||||
t.text "message"
|
||||
@ -268,6 +292,22 @@ ActiveRecord::Schema.define(version: 20170920145852) do
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "structured_error_attributes", force: :cascade do |t|
|
||||
t.integer "structured_error_id"
|
||||
t.integer "error_template_attribute_id"
|
||||
t.string "value"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.boolean "match"
|
||||
end
|
||||
|
||||
create_table "structured_errors", force: :cascade do |t|
|
||||
t.integer "error_template_id"
|
||||
t.integer "file_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "submissions", force: :cascade do |t|
|
||||
t.integer "exercise_id"
|
||||
t.float "score"
|
||||
|
@ -0,0 +1,49 @@
|
||||
require 'test_helper'
|
||||
|
||||
class ErrorTemplateAttributesControllerTest < ActionController::TestCase
|
||||
setup do
|
||||
@error_template_attribute = error_template_attributes(:one)
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:error_template_attributes)
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get :new
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should create error_template_attribute" do
|
||||
assert_difference('ErrorTemplateAttribute.count') do
|
||||
post :create, error_template_attribute: { }
|
||||
end
|
||||
|
||||
assert_redirected_to error_template_attribute_path(assigns(:error_template_attribute))
|
||||
end
|
||||
|
||||
test "should show error_template_attribute" do
|
||||
get :show, id: @error_template_attribute
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
get :edit, id: @error_template_attribute
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should update error_template_attribute" do
|
||||
patch :update, id: @error_template_attribute, error_template_attribute: { }
|
||||
assert_redirected_to error_template_attribute_path(assigns(:error_template_attribute))
|
||||
end
|
||||
|
||||
test "should destroy error_template_attribute" do
|
||||
assert_difference('ErrorTemplateAttribute.count', -1) do
|
||||
delete :destroy, id: @error_template_attribute
|
||||
end
|
||||
|
||||
assert_redirected_to error_template_attributes_path
|
||||
end
|
||||
end
|
49
test/controllers/error_templates_controller_test.rb
Normal file
49
test/controllers/error_templates_controller_test.rb
Normal file
@ -0,0 +1,49 @@
|
||||
require 'test_helper'
|
||||
|
||||
class ErrorTemplatesControllerTest < ActionController::TestCase
|
||||
setup do
|
||||
@error_template = error_templates(:one)
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get :index
|
||||
assert_response :success
|
||||
assert_not_nil assigns(:error_templates)
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get :new
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should create error_template" do
|
||||
assert_difference('ErrorTemplate.count') do
|
||||
post :create, error_template: { }
|
||||
end
|
||||
|
||||
assert_redirected_to error_template_path(assigns(:error_template))
|
||||
end
|
||||
|
||||
test "should show error_template" do
|
||||
get :show, id: @error_template
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
get :edit, id: @error_template
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should update error_template" do
|
||||
patch :update, id: @error_template, error_template: { }
|
||||
assert_redirected_to error_template_path(assigns(:error_template))
|
||||
end
|
||||
|
||||
test "should destroy error_template" do
|
||||
assert_difference('ErrorTemplate.count', -1) do
|
||||
delete :destroy, id: @error_template
|
||||
end
|
||||
|
||||
assert_redirected_to error_templates_path
|
||||
end
|
||||
end
|
7
test/factories/error_template_attributes.rb
Normal file
7
test/factories/error_template_attributes.rb
Normal file
@ -0,0 +1,7 @@
|
||||
FactoryGirl.define do
|
||||
factory :error_template_attribute do
|
||||
error_template nil
|
||||
key "MyString"
|
||||
regex "MyString"
|
||||
end
|
||||
end
|
7
test/factories/error_templates.rb
Normal file
7
test/factories/error_templates.rb
Normal file
@ -0,0 +1,7 @@
|
||||
FactoryGirl.define do
|
||||
factory :error_template do
|
||||
execution_environment nil
|
||||
name "MyString"
|
||||
signature "MyString"
|
||||
end
|
||||
end
|
7
test/factories/structured_error_attributes.rb
Normal file
7
test/factories/structured_error_attributes.rb
Normal file
@ -0,0 +1,7 @@
|
||||
FactoryGirl.define do
|
||||
factory :structured_error_attribute do
|
||||
structured_error nil
|
||||
error_template_attribute nil
|
||||
value "MyString"
|
||||
end
|
||||
end
|
6
test/factories/structured_errors.rb
Normal file
6
test/factories/structured_errors.rb
Normal file
@ -0,0 +1,6 @@
|
||||
FactoryGirl.define do
|
||||
factory :structured_error do
|
||||
error_template nil
|
||||
file nil
|
||||
end
|
||||
end
|
7
test/models/error_template_attribute_test.rb
Normal file
7
test/models/error_template_attribute_test.rb
Normal file
@ -0,0 +1,7 @@
|
||||
require 'test_helper'
|
||||
|
||||
class ErrorTemplateAttributeTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
7
test/models/error_template_test.rb
Normal file
7
test/models/error_template_test.rb
Normal file
@ -0,0 +1,7 @@
|
||||
require 'test_helper'
|
||||
|
||||
class ErrorTemplateTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
7
test/models/structured_error_attribute_test.rb
Normal file
7
test/models/structured_error_attribute_test.rb
Normal file
@ -0,0 +1,7 @@
|
||||
require 'test_helper'
|
||||
|
||||
class StructuredErrorAttributeTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
7
test/models/structured_error_test.rb
Normal file
7
test/models/structured_error_test.rb
Normal file
@ -0,0 +1,7 @@
|
||||
require 'test_helper'
|
||||
|
||||
class StructuredErrorTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
Reference in New Issue
Block a user