Files
codeocean/app/models/user.rb
Sebastian Serth 0e387ffda2 Add association for Comments and RequestForComments
For the submission and comments, I mainly decided to use a `has_one` association. Based on the database schema, multiple request for comments could be allowed (i.e., for each file or submission), but this won't happen practically (since we always create new submissions and files). Hence, the `has_one` association is representing our relationship better.
2023-09-25 18:17:52 +02:00

120 lines
3.6 KiB
Ruby

# frozen_string_literal: true
class User < ApplicationRecord
self.abstract_class = true
attr_reader :current_study_group_id
belongs_to :consumer
has_many :anomaly_notifications, as: :contributor, dependent: :destroy
has_many :authentication_token, dependent: :destroy
has_many :comments, as: :user
has_many :study_group_memberships, as: :user
has_many :study_groups, through: :study_group_memberships, as: :user
has_many :programming_group_memberships, as: :user
has_many :programming_groups, through: :programming_group_memberships, as: :user
has_many :exercises, as: :user
has_many :file_types, as: :user
has_many :submissions, as: :contributor
has_many :participations, through: :submissions, source: :exercise, as: :user
has_many :user_proxy_exercise_exercises, as: :user
has_many :user_exercise_interventions, as: :user
has_many :testruns, as: :user
has_many :interventions, through: :user_exercise_interventions
has_many :remote_evaluation_mappings, as: :user
has_many :request_for_comments, as: :user
has_many :runners, as: :contributor
has_many :events
has_many :events_synchronized_editor, class_name: 'Event::SynchronizedEditor'
has_many :pair_programming_exercise_feedbacks
has_many :pair_programming_waiting_users
has_one :codeharbor_link, dependent: :destroy
accepts_nested_attributes_for :user_proxy_exercise_exercises
scope :with_submissions, -> { where('id IN (SELECT user_id FROM submissions)') }
scope :in_study_group_of, lambda {|user|
unless user.admin?
joins(:study_group_memberships)
.where(study_group_memberships: {
study_group_id: user.study_group_memberships
.where(study_group_memberships: {role: StudyGroupMembership.roles[:teacher]})
.select(:study_group_id),
})
end
}
validates :platform_admin, inclusion: [true, false]
def internal_user?
is_a?(InternalUser)
end
def external_user?
is_a?(ExternalUser)
end
def programming_group?
false
end
def learner?
return true if current_study_group_id.nil?
@learner ||= current_study_group_membership.exists?(role: :learner) && !platform_admin?
end
def teacher?
@teacher ||= current_study_group_membership.exists?(role: :teacher) && !platform_admin?
end
def admin?
@admin ||= platform_admin?
end
def id_with_type
self.class.name.downcase.first + id.to_s
end
def store_current_study_group_id(study_group_id)
@current_study_group_id = study_group_id
self
end
def current_study_group_membership
# We use `where(...).limit(1)` instead of `find_by(...)` to allow query chaining
study_group_memberships.where(study_group: current_study_group_id).limit(1)
end
def to_s
displayname
end
def to_page_context
{
id:,
type: self.class.name,
consumer: consumer.name,
displayname:,
}
end
def self.find_by_id_with_type(id_with_type)
if id_with_type[0].casecmp('e').zero?
ExternalUser.find(id_with_type[1..])
elsif id_with_type[0].casecmp('i').zero?
InternalUser.find(id_with_type[1..])
else
raise ActiveRecord::RecordNotFound
end
end
def self.ransackable_attributes(auth_object)
if auth_object.present? && auth_object.admin?
%w[name email external_id consumer_id platform_admin]
else
%w[name external_id]
end
end
end