Files
codeocean/app/models/request_for_comment.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

104 lines
3.3 KiB
Ruby

# frozen_string_literal: true
class RequestForComment < ApplicationRecord
include Creation
include ActionCableHelper
# SOLVED: The author explicitly marked the RfC as solved.
# SOFT_SOLVED: The author did not mark the RfC as solved but reached the maximum score in the corresponding exercise at any time.
# ONGOING: The author did not mark the RfC as solved and did not reach the maximum score in the corresponding exercise yet.
STATE = [SOLVED = :solved, SOFT_SOLVED = :soft_solved, ONGOING = :unsolved].freeze
belongs_to :submission
belongs_to :exercise
belongs_to :file, class_name: 'CodeOcean::File'
has_many :comments, through: :submission
has_many :subscriptions, dependent: :destroy
scope :unsolved, -> { where(solved: [false, nil]) }
scope :in_range, ->(from, to) { from == DateTime.new(0) && to > 5.seconds.ago ? all : where(created_at: from..to) }
scope :with_comments, -> { select {|rfc| rfc.comments.any? } }
# after_save :trigger_rfc_action_cable
def commenters
comments.map(&:user).uniq
end
def comments?
comments.any?
end
def to_s
"RFC-#{id}"
end
def current_state
state(solved, full_score_reached)
end
def old_state
state(solved_before_last_save, full_score_reached_before_last_save)
end
private
def state(solved, full_score_reached)
if solved
SOLVED
elsif full_score_reached
SOFT_SOLVED
else
ONGOING
end
end
class << self
def with_last_activity
joins('join "submissions" s on s.id = request_for_comments.submission_id ' \
'left outer join "files" f on f.context_id = s.id ' \
'left outer join "comments" c on c.file_id = f.id')
.group('request_for_comments.id')
.select('request_for_comments.*, max(c.updated_at) as last_comment')
end
def last_per_user(count = 5)
from(row_number_user_sql, :request_for_comments)
.where('row_number <= ?', count)
.group('request_for_comments.id, request_for_comments.user_id, request_for_comments.user_type, ' \
'request_for_comments.exercise_id, request_for_comments.file_id, request_for_comments.question, ' \
'request_for_comments.created_at, request_for_comments.updated_at, request_for_comments.solved, ' \
'request_for_comments.full_score_reached, request_for_comments.submission_id, request_for_comments.row_number')
# ugly, but necessary
end
def ransackable_associations(_auth_object = nil)
%w[exercise submission]
end
def ransackable_attributes(_auth_object = nil)
%w[solved]
end
private
def row_number_user_sql
select('
request_for_comments.id,
request_for_comments.user_id,
request_for_comments.user_type,
request_for_comments.exercise_id,
request_for_comments.file_id,
request_for_comments.question,
request_for_comments.created_at,
request_for_comments.updated_at,
request_for_comments.solved,
request_for_comments.full_score_reached,
request_for_comments.submission_id,
row_number() OVER (PARTITION BY request_for_comments.user_id, request_for_comments.user_type ORDER BY request_for_comments.created_at DESC) as row_number
')
end
end
end