otwarchive-symphonyarchive/app/models/kudo.rb
2026-03-11 22:22:11 +00:00

105 lines
2.9 KiB
Ruby

class Kudo < ApplicationRecord
include Responder
VALID_COMMENTABLE_TYPES = %w[Work].freeze
belongs_to :user
belongs_to :commentable, polymorphic: true
validates :commentable_type, inclusion: { in: VALID_COMMENTABLE_TYPES }
validates :commentable,
presence: true,
if: proc { |c| VALID_COMMENTABLE_TYPES.include?(c.commentable_type) }
validates :user, not_blocked: { by: :commentable, on: :create }
validate :cannot_be_author, on: :create
def cannot_be_author
return unless user&.is_author_of?(commentable)
errors.add(:commentable, :author_on_own_work)
end
validate :guest_cannot_kudos_restricted_work, on: :create
def guest_cannot_kudos_restricted_work
return unless user.blank? && commentable.is_a?(Work) && commentable.restricted?
errors.add(:commentable, :guest_on_restricted)
end
validate :cannot_be_suspended, on: :create
def cannot_be_suspended
return unless user&.banned || user&.suspended
if user.banned
errors.add(:commentable, :user_is_banned)
else
errors.add(:commentable, :user_is_suspended)
end
end
validates :ip_address,
uniqueness: { scope: [:commentable_id, :commentable_type] },
if: proc { |kudo| kudo.ip_address.present? }
validates :user_id,
uniqueness: { scope: [:commentable_id, :commentable_type] },
if: proc { |kudo| kudo.user.present? }
validate :cannot_be_official_user, on: :create
def cannot_be_official_user
return unless user&.official
errors.add(:user, :official)
end
validate :cannot_be_archivist_account, on: :create
def cannot_be_archivist_account
return unless user&.archivist
errors.add(:user, :archivist)
end
scope :with_user, -> { where("user_id IS NOT NULL") }
scope :by_guest, -> { where("user_id IS NULL") }
after_destroy :update_work_stats
after_create :after_create, :update_work_stats
def after_create
users = self.commentable.pseuds.map(&:user).uniq
users.each do |user|
if notify_user_by_email?(user)
RedisMailQueue.queue_kudo(user, self)
end
end
end
after_save :expire_caches
def expire_caches
if commentable_type == "Work"
# Expire the work's cached total kudos count.
Rails.cache.delete("works/#{commentable_id}/kudos_count-v2")
# If it's a guest kudo, also expire the work's cached guest kudos count.
Rails.cache.delete("works/#{commentable_id}/guest_kudos_count-v2") if user_id.nil?
end
# Expire the cached kudos section under the work.
ActionController::Base.new.expire_fragment("#{commentable.cache_key}/kudos-v4")
end
def notify_user_by_email?(user)
user.nil? ? false : ( user.is_a?(Admin) ? true :
!(user == User.orphan_account || user.preference.kudos_emails_off?) )
end
# Return either the name of the kudo-giver or "guest".
# Used in kudo notifications.
def name
if self.user
user.login
else
"guest"
end
end
end