Class: Exam

Inherits:
ApplicationRecord show all
Includes:
FriendlyName, GuideContainer, TerminalNavigation
Defined in:
app/models/exam.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TerminalNavigation

#friendly, #navigable_name, #navigation_end?

Methods included from FriendlyName

#friendly_name, #to_param

Methods included from GuideContainer

#friendly, #index_usage!

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

.adapt_json_values(exam) ⇒ Object



115
116
117
118
119
120
# File 'app/models/exam.rb', line 115

def self.adapt_json_values(exam)
  exam[:guide_id] = Guide.find_by(slug: exam[:slug]).id
  exam[:organization_id] = Organization.current.id
  exam[:users] = exam[:uids].map { |uid| User.find_by(uid: uid) }.compact
  [:start_time, :end_time].each { |param| exam[param] = exam[param].to_time }
end

.import_from_resource_h!(json) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
# File 'app/models/exam.rb', line 103

def self.import_from_resource_h!(json)
  exam_data = json.with_indifferent_access
  organization = Organization.find_by!(name: exam_data[:organization])
  organization.switch!
  adapt_json_values exam_data
  remove_previous_version exam_data[:eid], exam_data[:guide_id]
  exam = where(classroom_id: exam_data[:eid]).update_or_create!(whitelist_attributes(exam_data))
  exam.process_users exam_data[:users]
  exam.index_usage! organization
  exam
end

.remove_previous_version(eid, guide_id) ⇒ Object



122
123
124
125
126
127
128
# File 'app/models/exam.rb', line 122

def self.remove_previous_version(eid, guide_id)
  Rails.logger.info "Looking for"
  where("guide_id=? and organization_id=? and classroom_id!=?", guide_id, Organization.current.id, eid).tap do |exams|
    Rails.logger.info "Deleting exams with ORG_ID:#{Organization.current.id} - GUIDE_ID:#{guide_id} - CLASSROOM_ID:#{eid}"
    exams.destroy_all
  end
end

Instance Method Details

#accessible_for?(user) ⇒ Boolean

Returns:

  • (Boolean)


46
47
48
# File 'app/models/exam.rb', line 46

def accessible_for?(user)
  authorized?(user) && enabled_for?(user)
end

#attempts_left_for(assignment) ⇒ Object



130
131
132
# File 'app/models/exam.rb', line 130

def attempts_left_for(assignment)
  max_attempts_for(assignment.exercise) - (assignment.attempts_count || 0)
end

#authorization_for(user) ⇒ Object



66
67
68
# File 'app/models/exam.rb', line 66

def authorization_for(user)
  authorizations.find_by(user_id: user.id)
end

#authorizations_for(users) ⇒ Object



70
71
72
# File 'app/models/exam.rb', line 70

def authorizations_for(users)
  authorizations.where(user_id: users.map(&:id))
end

#authorize!(user) ⇒ Object



54
55
56
# File 'app/models/exam.rb', line 54

def authorize!(user)
  users << user unless authorized?(user)
end

#authorized?(user) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
# File 'app/models/exam.rb', line 58

def authorized?(user)
  users.include? user
end

#clean_authorizations(users) ⇒ Object



99
100
101
# File 'app/models/exam.rb', line 99

def clean_authorizations(users)
  authorizations.all_except(authorizations_for(users)).destroy_all
end

#enabled?Boolean

Returns:

  • (Boolean)


21
22
23
# File 'app/models/exam.rb', line 21

def enabled?
  enabled_range.cover? DateTime.now
end

#enabled_for?(user) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
# File 'app/models/exam.rb', line 29

def enabled_for?(user)
  enabled_range_for(user).cover? DateTime.now
end

#enabled_rangeObject



25
26
27
# File 'app/models/exam.rb', line 25

def enabled_range
  start_time..end_time
end

#enabled_range_for(user) ⇒ Object



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

def enabled_range_for(user)
  start_time..real_end_time(user)
end

#in_progress_for?(user) ⇒ Boolean

Returns:

  • (Boolean)


33
34
35
# File 'app/models/exam.rb', line 33

def in_progress_for?(user)
  accessible_for?(user) && started?(user)
end

#limited_for?(exercise) ⇒ Boolean

Returns:

  • (Boolean)


134
135
136
# File 'app/models/exam.rb', line 134

def limited_for?(exercise)
  max_attempts_for(exercise).present?
end

#process_users(users) ⇒ Object



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

def process_users(users)
  users.map { |user| authorize! user }
  clean_authorizations users
end

#real_end_time(user) ⇒ Object



82
83
84
85
86
87
88
# File 'app/models/exam.rb', line 82

def real_end_time(user)
  if duration.present? && started?(user)
    [started_at(user) + duration.minutes, end_time].min
  else
    end_time
  end
end

#resettable?Boolean

Returns:

  • (Boolean)


138
139
140
# File 'app/models/exam.rb', line 138

def resettable?
  false
end

#start!(user) ⇒ Object



74
75
76
# File 'app/models/exam.rb', line 74

def start!(user)
  authorization_for(user).start! unless user.teacher_here?
end

#started?(user) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'app/models/exam.rb', line 78

def started?(user)
  authorization_for(user).try(:started?)
end

#started_at(user) ⇒ Object



90
91
92
# File 'app/models/exam.rb', line 90

def started_at(user)
  authorization_for(user).started_at
end

#timed?Boolean

Returns:

  • (Boolean)


50
51
52
# File 'app/models/exam.rb', line 50

def timed?
  duration.present?
end

#used_in?(organization) ⇒ Boolean

Returns:

  • (Boolean)


17
18
19
# File 'app/models/exam.rb', line 17

def used_in?(organization)
  organization == self.organization
end

#validate_accessible_for!(user) ⇒ Object



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

def validate_accessible_for!(user)
  if user.present?
    raise Mumuki::Domain::ForbiddenError unless authorized?(user)
    raise Mumuki::Domain::GoneError unless enabled_for?(user)
  else
    raise Mumuki::Domain::UnauthorizedError
  end
end