mirror of
https://github.com/moebooru/moebooru
synced 2025-08-22 01:47:48 +00:00
182 lines
3.9 KiB
Ruby
182 lines
3.9 KiB
Ruby
class ForumPost < ApplicationRecord
|
|
LATEST_CACHE_KEY = 'forum_posts_latest_v4'
|
|
|
|
belongs_to :creator, class_name: "User", foreign_key: :creator_id
|
|
belongs_to :updater, class_name: "User", foreign_key: :last_updated_by
|
|
after_create :initialize_last_updated_by
|
|
after_create :clear_cache
|
|
before_validation :validate_title
|
|
validates_length_of :body, minimum: 1, message: "You need to enter a body"
|
|
|
|
module LockMethods
|
|
module ClassMethods
|
|
def lock!(id)
|
|
# Run raw SQL to skip the lock check
|
|
execute_sql("UPDATE forum_posts SET is_locked = TRUE WHERE id = ?", id)
|
|
end
|
|
|
|
def unlock!(id)
|
|
# Run raw SQL to skip the lock check
|
|
execute_sql("UPDATE forum_posts SET is_locked = FALSE WHERE id = ?", id)
|
|
end
|
|
end
|
|
|
|
def self.included(m)
|
|
m.extend(ClassMethods)
|
|
m.before_validation :validate_lock
|
|
end
|
|
|
|
def validate_lock
|
|
if root.is_locked?
|
|
errors.add(:base, "Thread is locked")
|
|
throw :abort
|
|
end
|
|
|
|
true
|
|
end
|
|
end
|
|
|
|
module StickyMethods
|
|
module ClassMethods
|
|
def stick!(id)
|
|
# Run raw SQL to skip the lock check
|
|
execute_sql("UPDATE forum_posts SET is_sticky = TRUE WHERE id = ?", id)
|
|
end
|
|
|
|
def unstick!(id)
|
|
# Run raw SQL to skip the lock check
|
|
execute_sql("UPDATE forum_posts SET is_sticky = FALSE WHERE id = ?", id)
|
|
end
|
|
end
|
|
|
|
def self.included(m)
|
|
m.extend(ClassMethods)
|
|
end
|
|
end
|
|
|
|
module ParentMethods
|
|
def self.included(m)
|
|
m.after_create :update_parent_on_create
|
|
m.before_destroy :update_parent_on_destroy
|
|
m.has_many :children, lambda { order "id" }, class_name: "ForumPost", foreign_key: :parent_id
|
|
m.belongs_to :parent, class_name: "ForumPost", foreign_key: :parent_id
|
|
end
|
|
|
|
def update_parent_on_destroy
|
|
unless is_parent?
|
|
p = parent
|
|
p.update(response_count: p.response_count - 1)
|
|
end
|
|
end
|
|
|
|
def update_parent_on_create
|
|
unless is_parent?
|
|
p = parent
|
|
p.update(updated_at: updated_at, response_count: p.response_count + 1, last_updated_by: creator_id)
|
|
end
|
|
end
|
|
|
|
def is_parent?
|
|
parent_id.nil?
|
|
end
|
|
|
|
def root
|
|
if is_parent?
|
|
self
|
|
else
|
|
parent
|
|
end
|
|
end
|
|
|
|
def root_id
|
|
if is_parent?
|
|
id
|
|
else
|
|
parent_id
|
|
end
|
|
end
|
|
end
|
|
|
|
module ApiMethods
|
|
def api_attributes
|
|
{
|
|
body: body,
|
|
creator: author,
|
|
creator_id: creator_id,
|
|
id: id,
|
|
parent_id: parent_id,
|
|
title: title,
|
|
updated_at: updated_at,
|
|
pages: pages
|
|
}
|
|
end
|
|
|
|
def as_json(*params)
|
|
api_attributes.as_json(*params)
|
|
end
|
|
|
|
def to_xml(options = {})
|
|
api_attributes.to_xml(options.reverse_merge(root: "forum_post"))
|
|
end
|
|
end
|
|
|
|
include LockMethods
|
|
include StickyMethods
|
|
include ParentMethods
|
|
include ApiMethods
|
|
|
|
def self.updated?(user)
|
|
conds = []
|
|
conds += [ "creator_id <> %d" % [ user.id ] ] unless user.is_anonymous?
|
|
|
|
newest_topic = ForumPost.where(conds).order(id: :desc).select(:created_at).take
|
|
return false if newest_topic.nil?
|
|
newest_topic.created_at > user.last_forum_topic_read_at
|
|
end
|
|
|
|
def validate_title
|
|
if is_parent?
|
|
if title.blank?
|
|
errors.add :title, "missing"
|
|
throw :abort
|
|
end
|
|
|
|
if title !~ /\S/
|
|
errors.add :title, "missing"
|
|
throw :abort
|
|
end
|
|
end
|
|
|
|
true
|
|
end
|
|
|
|
def initialize_last_updated_by
|
|
if is_parent?
|
|
update(last_updated_by: creator_id)
|
|
end
|
|
end
|
|
|
|
def clear_cache
|
|
Rails.cache.delete "forum_posts"
|
|
Rails.cache.delete LATEST_CACHE_KEY
|
|
end
|
|
|
|
def last_updater
|
|
updater.name
|
|
rescue
|
|
CONFIG["default_guest_name"]
|
|
end
|
|
|
|
def author
|
|
creator.name
|
|
end
|
|
|
|
def pages
|
|
((response_count == 0 ? 1 : response_count) / 30.0).ceil
|
|
end
|
|
|
|
def self.latest
|
|
where(parent_id: nil).reorder(updated_at: :desc).paginate(page: 1, per_page: 10)
|
|
end
|
|
end
|