94 lines
2.5 KiB
Ruby
94 lines
2.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class PostVote < ApplicationRecord
|
|
attr_accessor :updater
|
|
|
|
belongs_to :post
|
|
belongs_to :user
|
|
|
|
validates :score, inclusion: { in: [1, -1], message: "must be 1 or -1" }
|
|
|
|
before_save { post.lock! }
|
|
before_save :update_score_on_delete, if: -> { !new_record? && is_deleted_changed?(from: false, to: true) }
|
|
before_save :update_score_on_undelete, if: -> { !new_record? && is_deleted_changed?(from: true, to: false) }
|
|
before_save :create_mod_action_on_delete_or_undelete
|
|
before_create :update_score_on_create
|
|
before_create :remove_conflicting_votes
|
|
|
|
scope :positive, -> { where("post_votes.score > 0") }
|
|
scope :negative, -> { where("post_votes.score < 0") }
|
|
scope :public_votes, -> { active.positive.where(user: User.has_public_favorites) }
|
|
|
|
deletable
|
|
|
|
def self.visible(user)
|
|
if user.is_admin?
|
|
all
|
|
elsif user.is_anonymous?
|
|
public_votes
|
|
else
|
|
active.where(user: user).or(public_votes)
|
|
end
|
|
end
|
|
|
|
def self.search(params)
|
|
q = search_attributes(params, :id, :created_at, :updated_at, :score, :is_deleted, :user, :post)
|
|
|
|
q.apply_default_order(params)
|
|
end
|
|
|
|
def is_positive?
|
|
score > 0
|
|
end
|
|
|
|
def is_negative?
|
|
score < 0
|
|
end
|
|
|
|
def remove_conflicting_votes
|
|
PostVote.active.where.not(id: id).where(post: post, user: user).each do |vote|
|
|
vote.soft_delete!(updater: updater)
|
|
end
|
|
end
|
|
|
|
def validate_vote_is_unique
|
|
if !is_deleted? && PostVote.active.where.not(id: id).exists?(post: post, user: user)
|
|
errors.add(:user, "have already voted for this post")
|
|
end
|
|
end
|
|
|
|
def update_score_on_create
|
|
if is_positive?
|
|
Post.update_counters(post_id, { score: score, up_score: score })
|
|
else
|
|
Post.update_counters(post_id, { score: score, down_score: score })
|
|
end
|
|
end
|
|
|
|
def update_score_on_delete
|
|
if is_positive?
|
|
Post.update_counters(post_id, { score: -score, up_score: -score })
|
|
else
|
|
Post.update_counters(post_id, { score: -score, down_score: -score })
|
|
end
|
|
end
|
|
|
|
def update_score_on_undelete
|
|
update_score_on_create
|
|
end
|
|
|
|
def create_mod_action_on_delete_or_undelete
|
|
return if new_record? || updater.nil? || updater == user
|
|
|
|
if is_deleted_changed?(from: false, to: true)
|
|
ModAction.log("#{updater.name} deleted post vote ##{id} on post ##{post_id}", :post_vote_delete, updater)
|
|
elsif is_deleted_changed?(from: true, to: false)
|
|
ModAction.log("#{updater.name} undeleted post vote ##{id} on post ##{post_id}", :post_vote_undelete, updater)
|
|
end
|
|
end
|
|
|
|
def self.available_includes
|
|
[:user, :post]
|
|
end
|
|
end
|