Class: Assignment

Inherits:
ApplicationRecord show all
Includes:
Contextualization, WithMessages
Defined in:
app/models/assignment.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from WithMessages

#build_message, #has_messages?, #pending_messages?, #receive_answer!, #send_question!

Methods included from Contextualization

#expectation_results_visible?, #failed_expectation_results, #feedback_html, #humanized_expectation_results, #queries_with_results, #result_html, #result_preview, #results_visible?, #single_visual_result?, #single_visual_result_html, #visible_expectation_results

Methods inherited from ApplicationRecord

aggregate_of, all_except, defaults, numbered, #save, #save_and_notify!, #save_and_notify_changes!, serialize_symbolized_hash_array, #update_and_notify!, update_or_create!, whitelist_attributes

Class Method Details

.evaluate_manually!(teacher_evaluation) ⇒ Object



62
63
64
# File 'app/models/assignment.rb', line 62

def self.evaluate_manually!(teacher_evaluation)
  Assignment.find_by(submission_id: teacher_evaluation[:submission_id])&.evaluate_manually! teacher_evaluation
end

Instance Method Details

#attempts_leftObject



155
156
157
# File 'app/models/assignment.rb', line 155

def attempts_left
  navigable_parent.attempts_left_for(self)
end

#attempts_left?Boolean

Tells wether the submitter of this assignment can keep on sending submissions which is true for non limited or for assignments that have not reached their submissions limit

Returns:

  • (Boolean)


163
164
165
# File 'app/models/assignment.rb', line 163

def attempts_left?
  !limited? || attempts_left > 0
end

#content=(content) ⇒ Object



66
67
68
69
70
# File 'app/models/assignment.rb', line 66

def content=(content)
  if content.present?
    self.solution = exercise.single_choice? ? exercise.choices.index(content) : content
  end
end

#current_contentObject



167
168
169
# File 'app/models/assignment.rb', line 167

def current_content
  solution || default_content
end

#current_content_at(index) ⇒ Object



171
172
173
# File 'app/models/assignment.rb', line 171

def current_content_at(index)
  exercise.sibling_at(index).assignment_for(submitter).current_content
end

#default_contentObject



175
176
177
# File 'app/models/assignment.rb', line 175

def default_content
  @default_content ||= language.interpolate_references_for(self, exercise.default_content)
end

#errored!(message) ⇒ Object



106
107
108
# File 'app/models/assignment.rb', line 106

def errored!(message)
  update! result: message, submission_status: :errored
end

#evaluate_manually!(teacher_evaluation) ⇒ Object



34
35
36
# File 'app/models/assignment.rb', line 34

def evaluate_manually!(teacher_evaluation)
  update! status: teacher_evaluation[:status], manual_evaluation_comment: teacher_evaluation[:manual_evaluation]
end

#extensionObject



47
48
49
# File 'app/models/assignment.rb', line 47

def extension
  exercise.language.extension
end

#extraObject



76
77
78
# File 'app/models/assignment.rb', line 76

def extra
  exercise.extra && language.interpolate_references_for(self, exercise.extra)
end

#extra_previewObject



80
81
82
# File 'app/models/assignment.rb', line 80

def extra_preview
  Mumukit::ContentType::Markdown.highlighted_code(language.name, extra)
end

#filesObject



179
180
181
182
183
184
# File 'app/models/assignment.rb', line 179

def files
  language
    .directives_sections
    .split_sections(current_content)
    .map { |name, content| Mumuki::Domain::File.new name, content }
end

#increment_attempts!Object



151
152
153
# File 'app/models/assignment.rb', line 151

def increment_attempts!
  self.attempts_count += 1 if should_retry?
end

#notify!Object



51
52
53
# File 'app/models/assignment.rb', line 51

def notify!
  Mumukit::Nuntius.notify! 'submissions', to_resource_h unless Organization.current.silent?
end

#notify_to_accessible_organizations!Object



55
56
57
58
59
60
# File 'app/models/assignment.rb', line 55

def notify_to_accessible_organizations!
  submitter.accessible_organizations.each do |organization|
    organization.switch!
    notify!
  end
end

#passed!Object



94
95
96
# File 'app/models/assignment.rb', line 94

def passed!
  update! submission_status: :passed
end

#persist_submission!(submission) ⇒ Object



38
39
40
41
42
43
44
45
# File 'app/models/assignment.rb', line 38

def persist_submission!(submission)
  transaction do
    messages.destroy_all if submission_id.present?
    update! submission_id: submission.id
    update_submissions_count!
    update_last_submission!
  end
end

#run_tests!(params) ⇒ Object



115
116
117
# File 'app/models/assignment.rb', line 115

def run_tests!(params)
  exercise.run_tests! params.merge(extra: extra, test: test)
end

#run_update!Object



84
85
86
87
88
89
90
91
92
# File 'app/models/assignment.rb', line 84

def run_update!
  running!
  begin
    update! yield
  rescue => e
    errored! e.message
    raise e
  end
end

#running!Object



98
99
100
101
102
103
104
# File 'app/models/assignment.rb', line 98

def running!
  update! submission_status: :running,
          result: nil,
          test_results: nil,
          expectation_results: [],
          manual_evaluation_comment: nil
end

#testObject



72
73
74
# File 'app/models/assignment.rb', line 72

def test
  exercise.test && language.interpolate_references_for(self, exercise.test)
end

#tipsObject



147
148
149
# File 'app/models/assignment.rb', line 147

def tips
  @tips ||= exercise.assist_with(self)
end

#to_resource_hObject



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'app/models/assignment.rb', line 119

def to_resource_h
  as_json(except: [:exercise_id, :submission_id, :id, :submitter_id, :solution, :created_at, :updated_at, :submission_status],
            include: {
              guide: {
                only: [:slug, :name],
                include: {
                  lesson: {only: [:number]},
                  language: {only: [:name]}},
              },
              exercise: {only: [:name, :number]},
              submitter: {only: [:email, :image_url, :social_id, :uid], methods: [:name]}}).
    deep_merge(
      'organization' => Organization.current.name,
      'sid' => submission_id,
      'created_at' => updated_at,
      'content' => solution,
      'status' => submission_status,
      'exercise' => {
        'eid' => exercise.bibliotheca_id
      },
      'guide' => {'parent' => {
        'type' => navigable_parent.class.to_s,
        'name' => navigable_parent.name,
        'position' => navigable_parent.try(:number),
        'chapter' => guide.chapter.as_json(only: [:id], methods: [:name])
      }})
end