Class: CourseExam
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- CourseExam
- Defined in:
- app/models/course_exam.rb
Overview
== Schema Information
Table name: course_exams
Database name: primary
id :bigint not null, primary key
attainable_maximum :integer
position :integer
score :integer
state :string
created_at :datetime not null
updated_at :datetime not null
course_enrollment_id :integer
topic_exam_id :integer
Indexes
index_course_exams_on_course_enrollment_id (course_enrollment_id)
Foreign Keys
fk_rails_... (course_enrollment_id => course_enrollments.id)
A learner's attempt at a course's final exam. Created when the learner
requests the exam (position = attempt number), it carries their answers as
CustomerTopic copies and is graded by Grader. Lifecycle:
new → in_progress → passed/failed (or cancelled by staff); passing
completes the parent CourseEnrollment and triggers the learner/staff
notifications, failing only notifies — retakes are unlimited.
Defined Under Namespace
Classes: Grader, InitializeTopics
Constant Summary
Constants included from Models::Schedulable
Models::Schedulable::SIMPLE_FORM_OPTIONS
Belongs to collapse
-
#course_enrollment ⇒ CourseEnrollment
The enrollment this attempt belongs to.
-
#topic_exam ⇒ TopicExam
The exam definition (questions + pass threshold) being attempted.
Has many collapse
-
#customer_topics ⇒ ActiveRecord::Relation<CustomerTopic>
The learner's per-question answer copies for this attempt.
Class Method Summary collapse
-
.active ⇒ ActiveRecord::Relation<CourseExam>
A relation of CourseExams that are active.
-
.passed ⇒ ActiveRecord::Relation<CourseExam>
A relation of CourseExams that are passed.
-
.sorted ⇒ ActiveRecord::Relation<CourseExam>
A relation of CourseExams that are sorted.
Instance Method Summary collapse
-
#cutoff_mark ⇒ Integer
The minimum score needed to pass, from the exam definition.
-
#failed? ⇒ Boolean
Whether the attempt was graded below the pass threshold.
-
#in_progress? ⇒ Boolean
Whether the attempt is open (started but not yet graded).
-
#passed? ⇒ Boolean
Whether the attempt was graded at or above the pass threshold.
-
#score_display ⇒ String?
Score alongside the attainable maximum, e.g.
Methods inherited from ApplicationRecord
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
Methods included from Models::Schedulable
Methods included from Models::AfterCommittable
Methods included from Models::EventPublishable
Class Method Details
.active ⇒ ActiveRecord::Relation<CourseExam>
A relation of CourseExams that are active. Active Record Scope
46 |
# File 'app/models/course_exam.rb', line 46 scope :active, -> { where(state: 'in_progress') } |
.passed ⇒ ActiveRecord::Relation<CourseExam>
A relation of CourseExams that are passed. Active Record Scope
45 |
# File 'app/models/course_exam.rb', line 45 scope :passed, -> { where(state: 'passed') } |
.sorted ⇒ ActiveRecord::Relation<CourseExam>
A relation of CourseExams that are sorted. Active Record Scope
47 |
# File 'app/models/course_exam.rb', line 47 scope :sorted, -> { order(:position) } |
Instance Method Details
#course_enrollment ⇒ CourseEnrollment
The enrollment this attempt belongs to.
34 |
# File 'app/models/course_exam.rb', line 34 belongs_to :course_enrollment, optional: true |
#customer_topics ⇒ ActiveRecord::Relation<CustomerTopic>
The learner's per-question answer copies for this attempt.
39 |
# File 'app/models/course_exam.rb', line 39 has_many :customer_topics, -> { order(:position) }, inverse_of: :course_exam |
#cutoff_mark ⇒ Integer
The minimum score needed to pass, from the exam definition.
104 105 106 |
# File 'app/models/course_exam.rb', line 104 def cutoff_mark topic_exam.min_score_to_pass.to_i end |
#failed? ⇒ Boolean
Whether the attempt was graded below the pass threshold.
90 91 92 |
# File 'app/models/course_exam.rb', line 90 def failed? state == 'failed' end |
#in_progress? ⇒ Boolean
Whether the attempt is open (started but not yet graded).
83 84 85 |
# File 'app/models/course_exam.rb', line 83 def in_progress? state == 'in_progress' end |
#passed? ⇒ Boolean
Whether the attempt was graded at or above the pass threshold.
97 98 99 |
# File 'app/models/course_exam.rb', line 97 def passed? state == 'passed' end |
#score_display ⇒ String?
Score alongside the attainable maximum, e.g. "12 of 15 (80%)" —
absolute points alone are meaningless once questions are added or
removed from the exam definition. Uses the maximum captured when the
attempt was created, ensuring it remains immutable even if the exam
definition changes.
115 116 117 118 119 120 121 122 |
# File 'app/models/course_exam.rb', line 115 def score_display return if score.nil? max = attainable_maximum.to_i return score.to_s unless max.positive? "#{score} of #{max} (#{score * 100 / max}%)" end |
#topic_exam ⇒ TopicExam
The exam definition (questions + pass threshold) being attempted.
36 |
# File 'app/models/course_exam.rb', line 36 belongs_to :topic_exam, optional: true |