Extended Exercises by worktime, difficulty and tags, added ProxyExercises as prework for recommendations

Tags can be added to exercises in the edit view. Tags can monitored under /tags.
Added the concept of ProxyExercises which are a collection of Exercises. They can be found under /proxy_exercises
Added Interventions as prework to show interventions later to the user.
Added exercise/[:id]/working_time to return the working time of the user in this exercise and the average working time of all users in this exercise
This commit is contained in:
Thomas Hille
2017-01-29 20:26:45 +01:00
parent 8f927d5ac9
commit 0db11884bc
40 changed files with 675 additions and 5 deletions

View File

@@ -8,6 +8,10 @@ module User
has_many :exercises, as: :user
has_many :file_types, as: :user
has_many :submissions, as: :user
has_many :user_proxy_exercise_exercises, as: :user
has_many :user_exercise_interventions, as: :user
has_many :interventions, through: :user_exercise_interventions
scope :with_submissions, -> { where('id IN (SELECT user_id FROM submissions)') }
end

View File

@@ -12,6 +12,15 @@ class Exercise < ActiveRecord::Base
belongs_to :execution_environment
has_many :submissions
has_and_belongs_to_many :proxy_exercises
has_many :user_proxy_exercise_exercises
has_and_belongs_to_many :exercise_collections
has_many :user_exercise_interventions
has_many :interventions, through: :user_exercise_interventions
has_many :exercise_tags
has_many :tags, through: :exercise_tags
accepts_nested_attributes_for :exercise_tags
has_many :external_users, source: :user, source_type: ExternalUser, through: :submissions
has_many :internal_users, source: :user, source_type: InternalUser, through: :submissions
alias_method :users, :external_users
@@ -105,6 +114,7 @@ class Exercise < ActiveRecord::Base
def duplicate(attributes = {})
exercise = dup
exercise.attributes = attributes
exercise_tags.each { |et| exercise.exercise_tags << et.dup }
files.each { |file| exercise.files << file.dup }
exercise
end

View File

@@ -0,0 +1,5 @@
class ExerciseCollection < ActiveRecord::Base
has_and_belongs_to_many :exercises
end

View File

@@ -0,0 +1,13 @@
class ExerciseTag < ActiveRecord::Base
belongs_to :tag
belongs_to :exercise
before_save :destroy_if_empty_exercise_or_tag
private
def destroy_if_empty_exercise_or_tag
destroy if exercise_id.blank? || tag_id.blank?
end
end

View File

@@ -0,0 +1,15 @@
class Intervention < ActiveRecord::Base
NAME = %w(overallSlower longSession syntaxErrors videoNotWatched)
has_many :user_exercise_interventions
has_many :users, through: :user_exercise_interventions, source_type: "ExternalUser"
#belongs_to :user, polymorphic: true
#belongs_to :external_users, source: :user, source_type: ExternalUser
#belongs_to :internal_users, source: :user, source_type: InternalUser, through: :user_interventions
# alias_method :users, :external_users
#has_many :exercises, through: :user_interventions
validates :name, inclusion: {in: NAME}
end

View File

@@ -0,0 +1,27 @@
class ProxyExercise < ActiveRecord::Base
after_initialize :generate_token
has_and_belongs_to_many :exercises
has_many :user_proxy_exercise_exercises
def count_files
exercises.count
end
def generate_token
self.token ||= SecureRandom.hex(4)
end
private :generate_token
def duplicate(attributes = {})
proxy_exercise = dup
proxy_exercise.attributes = attributes
proxy_exercise
end
def to_s
title
end
end

22
app/models/tag.rb Normal file
View File

@@ -0,0 +1,22 @@
class Tag < ActiveRecord::Base
has_many :exercise_tags
has_many :exercises, through: :exercise_tags
validates_uniqueness_of :name
def destroy
if (can_be_destroyed?)
super
end
end
def can_be_destroyed?
!exercises.any?
end
def to_s
name
end
end

View File

@@ -0,0 +1,8 @@
class UserExerciseFeedback < ActiveRecord::Base
belongs_to :user, polymorphic: true
belongs_to :exercise
validates :user_id, uniqueness: { scope: [:exercise_id, :user_type] }
end

View File

@@ -0,0 +1,11 @@
class UserExerciseIntervention < ActiveRecord::Base
belongs_to :user, polymorphic: true
belongs_to :intervention
belongs_to :exercise
validates :user, presence: true
validates :exercise, presence: true
validates :intervention, presence: true
end

View File

@@ -0,0 +1,14 @@
class UserProxyExerciseExercise < ActiveRecord::Base
belongs_to :user, polymorphic: true
belongs_to :exercise
belongs_to :proxy_exercise
validates :user_id, presence: true
validates :user_type, presence: true
validates :exercise_id, presence: true
validates :proxy_exercise_id, presence: true
validates :user_id, uniqueness: { scope: [:proxy_exercise_id, :user_type] }
end