Class: User

Constant Summary collapse

PLACEHOLDER_IMAGE_URL =
'user_shape.png'.freeze

Instance Method Summary collapse

Methods included from WithUserNavigation

#navigable_name, #navigation_end?

Methods included from WithReminders

#build_reminder, #remind!, #should_remind?, #try_remind_with_lock!

Methods included from Disabling

#disable!, #disabled?, #enabled?, #ensure_enabled!

Methods included from Mumuki::Domain::Helpers::User

#any_granted_organizations, #discusser_of?, #full_name, #has_immersive_main_organization?, #has_role?, #has_student_granted_organizations?, #main_organization, #merge_permissions!, #platform_class_name, #profile_completed?, #to_param

Methods included from Mumuki::Domain::Syncable

#platform_class_name, #sync_key

Methods inherited from ApplicationRecord

aggregate_of, all_except, defaults, #delete, #destroy!, numbered, organic_on, resource_fields, #save, #save_and_notify!, #save_and_notify_changes!, serialize_symbolized_hash_array, #update_and_notify!, update_or_create!, whitelist_attributes

Instance Method Details

#accept_invitation!(invitation) ⇒ Object



92
93
94
# File 'app/models/user.rb', line 92

def accept_invitation!(invitation)
  make_student_of! invitation.course_slug
end

#ageObject



233
234
235
236
237
# File 'app/models/user.rb', line 233

def age
  if birthdate.present?
    @age ||= Time.now.round_years_since(birthdate.to_time)
  end
end

#attach!(role, course) ⇒ Object



127
128
129
130
# File 'app/models/user.rb', line 127

def attach!(role, course)
  add_permission! role, course.slug
  save_and_notify!
end

#build_assignment(exercise, organization) ⇒ Object



205
206
207
# File 'app/models/user.rb', line 205

def build_assignment(exercise, organization)
  assignments.build(exercise: exercise, organization: organization)
end

#bury!Object



157
158
159
160
# File 'app/models/user.rb', line 157

def bury!
  # TODO change avatar
  update! self.class.buried_profile.merge(accepts_reminders: false, gender: nil, birthdate: nil)
end

#can_access_teacher_info_in?(organization) ⇒ Boolean

Returns:

  • (Boolean)


193
194
195
# File 'app/models/user.rb', line 193

def can_access_teacher_info_in?(organization)
  teacher_of?(organization) || organization.teacher_training?
end

#can_discuss_here?Boolean

Returns:

  • (Boolean)


189
190
191
# File 'app/models/user.rb', line 189

def can_discuss_here?
  can_discuss_in? Organization.current
end

#can_discuss_in?(organization) ⇒ Boolean

Tells if the given user can discuss in an organization

This is true only when this organization has the forum enabled and the user has the discusser pseudo-permission and the discusser is trusted

Returns:

  • (Boolean)


181
182
183
# File 'app/models/user.rb', line 181

def can_discuss_in?(organization)
  organization.forum_enabled? && discusser_of?(organization) && trusted_as_discusser_in?(organization)
end

#clear_progress!Object



85
86
87
88
89
90
# File 'app/models/user.rb', line 85

def clear_progress!
  transaction do
    update! last_submission_date: nil, last_exercise: nil
    assignments.destroy_all
  end
end

#completed_containers(sequence, organization) ⇒ Object

Takes a didactic - ordered - sequence of content containers and returns those that have been completed



164
165
166
# File 'app/models/user.rb', line 164

def completed_containers(sequence, organization)
  sequence.take_while { |it| it.content.completed_for?(self, organization) }
end

#completed_containers_with_lookahead(sequence, organization, lookahead: 1) ⇒ Object

Like ‘completed_containers`, returns a slice of the completed containers in the sequence, but adding a configurable number of trailing, non-completed contaienrs



170
171
172
173
174
175
# File 'app/models/user.rb', line 170

def completed_containers_with_lookahead(sequence, organization, lookahead: 1)
  raise 'invalid lookahead' if lookahead < 1

  count = completed_containers(sequence, organization).size
  sequence[0..count + lookahead - 1]
end

#current_audienceObject



225
226
227
# File 'app/models/user.rb', line 225

def current_audience
  current_organic_context&.target_audience
end

#currently_in_exam?Boolean

Returns:

  • (Boolean)


145
146
147
# File 'app/models/user.rb', line 145

def currently_in_exam?
  exams.any? { |e| e.in_progress_for? self }
end

#custom_profile_pictureObject



149
150
151
# File 'app/models/user.rb', line 149

def custom_profile_picture
  avatar&.image_url || image_url
end

#detach!(role, course) ⇒ Object



132
133
134
135
# File 'app/models/user.rb', line 132

def detach!(role, course)
  remove_permission! role, course.slug
  save_and_notify!
end

#import_from_resource_h!(json) ⇒ Object



108
109
110
# File 'app/models/user.rb', line 108

def import_from_resource_h!(json)
  update! self.class.slice_resource_h json
end

#incognito?Boolean

Returns:

  • (Boolean)


221
222
223
# File 'app/models/user.rb', line 221

def incognito?
  false
end

#interpolationsObject



137
138
139
140
141
142
143
# File 'app/models/user.rb', line 137

def interpolations
  {
    'user_email' => email,
    'user_first_name' => first_name,
    'user_last_name' => last_name
  }
end

#last_lessonObject



45
46
47
# File 'app/models/user.rb', line 45

def last_lesson
  last_guide.try(:lesson)
end

#name_initialsObject



197
198
199
# File 'app/models/user.rb', line 197

def name_initials
  name.split.map(&:first).map(&:capitalize).join(' ')
end

#never_submitted?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'app/models/user.rb', line 81

def 
  last_submission_date.nil?
end

#next_exercise_at(guide) ⇒ Object



213
214
215
# File 'app/models/user.rb', line 213

def next_exercise_at(guide)
  guide.pending_exercises(self).order('public.exercises.number asc').first
end

#passed_assignmentsObject



65
66
67
# File 'app/models/user.rb', line 65

def passed_assignments
  assignments.where(status: Mumuki::Domain::Status::Submission::Passed.to_i)
end

#passed_submissions_countObject



53
54
55
# File 'app/models/user.rb', line 53

def passed_submissions_count
  passed_assignments.count
end

#pending_siblings_at(content) ⇒ Object



209
210
211
# File 'app/models/user.rb', line 209

def pending_siblings_at(content)
  content.pending_siblings_for(self)
end

#placeholder_image_urlObject



229
230
231
# File 'app/models/user.rb', line 229

def placeholder_image_url
  PLACEHOLDER_IMAGE_URL
end

#profile_pictureObject



153
154
155
# File 'app/models/user.rb', line 153

def profile_picture
  custom_profile_picture || placeholder_image_url
end

#progress_at(content, organization) ⇒ Object



201
202
203
# File 'app/models/user.rb', line 201

def progress_at(content, organization)
  Indicator.find_or_initialize_by(user: self, organization: organization, content: content)
end

#run_submission!(submission, assignment, evaluation) ⇒ Object



217
218
219
# File 'app/models/user.rb', line 217

def run_submission!(submission, assignment, evaluation)
  submission.run! assignment, evaluation
end

#solved_exercises_countObject



61
62
63
# File 'app/models/user.rb', line 61

def solved_exercises_count
  solved_exercises.count
end

#submissions_countObject



49
50
51
# File 'app/models/user.rb', line 49

def submissions_count
  assignments.pluck(:submissions_count).sum
end

#submitted_exercises_countObject



57
58
59
# File 'app/models/user.rb', line 57

def 
  .count
end

#to_resource_hObject



112
113
114
# File 'app/models/user.rb', line 112

def to_resource_h
  super.merge(image_url: profile_picture)
end

#to_sObject



77
78
79
# File 'app/models/user.rb', line 77

def to_s
  "#{id}:#{name}:#{uid}"
end

#transfer_progress_to!(another) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
# File 'app/models/user.rb', line 96

def transfer_progress_to!(another)
  transaction do
    assignments.update_all(submitter_id: another.id)
    if another. || last_submission_date.try { |it| it > another.last_submission_date }
      another.update! last_submission_date: last_submission_date,
                      last_exercise: last_exercise,
                      last_organization: last_organization
    end
  end
  reload
end

#trusted_as_discusser_in?(organization) ⇒ Boolean

Returns:

  • (Boolean)


185
186
187
# File 'app/models/user.rb', line 185

def trusted_as_discusser_in?(organization)
  trusted_for_forum? || !organization.forum_only_for_trusted?
end

#unread_messagesObject



69
70
71
# File 'app/models/user.rb', line 69

def unread_messages
  messages.where read: false
end

#unsubscribe_from_reminders!Object



122
123
124
# File 'app/models/user.rb', line 122

def unsubscribe_from_reminders!
  update! accepts_reminders: false
end

#verify_name!Object



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

def verify_name!
  self.verified_first_name ||= first_name
  self.verified_last_name ||= last_name
  save!
end

#visit!(organization) ⇒ Object



73
74
75
# File 'app/models/user.rb', line 73

def visit!(organization)
  update!(last_organization: organization) if organization != last_organization
end