journalduhacker/app/models/vote.rb
joshua stein 9535b05490 remove story downvoting, add story hiding
stories should either be reported for spam (coming later), upvoted,
or left alone rather than being downvoted for being uninteresting.
since users don't like leaving uninteresting things alone, they can
now hide stories from their view without affecting the story's
score.

hiding is implemented as a Vote with its vote set to 0 and the
reason set to "H"

add a /hidden url which shows all of a user's hidden stories

while i'm here, simplify Vote guts and add some tests to make sure
all the flip-flopping stuff works right
2014-03-03 17:20:21 -06:00

126 lines
3 KiB
Ruby

class Vote < ActiveRecord::Base
belongs_to :user
belongs_to :story
COMMENT_REASONS = {
"O" => "Off-topic",
"I" => "Incorrect",
"M" => "Me-too",
"T" => "Troll",
"S" => "Spam",
"" => "Cancel",
}
def self.votes_by_user_for_stories_hash(user, stories)
votes = {}
Vote.where(:user_id => user, :story_id => stories,
:comment_id => nil).each do |v|
votes[v.story_id] = v.vote
end
votes
end
def self.comment_votes_by_user_for_story_hash(user_id, story_id)
votes = {}
Vote.where(
:user_id => user_id, :story_id => story_id
).where(
"comment_id IS NOT NULL"
).each do |v|
votes[v.comment_id] = { :vote => v.vote, :reason => v.reason }
end
votes
end
def self.story_votes_by_user_for_story_ids_hash(user_id, story_ids)
if story_ids.empty?
{}
else
votes = self.where(
:user_id => user_id,
:comment_id => nil,
:story_id => story_ids,
)
votes.inject({}) do |memo, v|
memo[v.story_id] = { :vote => v.vote, :reason => v.reason }
memo
end
end
end
def self.comment_votes_by_user_for_comment_ids_hash(user_id, comment_ids)
if comment_ids.empty?
{}
else
votes = self.where(
:user_id => user_id,
:comment_id => comment_ids,
)
votes.inject({}) do |memo, v|
memo[v.comment_id] = { :vote => v.vote, :reason => v.reason }
memo
end
end
end
def self.vote_thusly_on_story_or_comment_for_user_because(vote, story_id,
comment_id, user_id, reason, update_counters = true)
v = Vote.where(:user_id => user_id, :story_id => story_id,
:comment_id => comment_id).first_or_initialize
if !v.new_record? && v.vote == vote && vote != 0
return
end
upvote = 0
downvote = 0
Vote.transaction do
# unvote
if vote == 0 && reason == nil
# neutralize previous vote
upvote = (v.vote == 1 ? -1 : 0)
downvote = (v.vote == -1 ? -1 : 0)
v.destroy!
# new vote or change vote
else
if !v.new_record?
upvote = (v.vote == 1 ? -1 : 0)
downvote = (v.vote == -1 ? -1 : 0)
end
upvote += (vote == 1 ? 1 : 0)
downvote += (vote == -1 ? 1 : 0)
v.vote = vote
v.reason = reason
v.save!
end
if update_counters && (downvote != 0 || upvote != 0)
if v.comment_id
c = Comment.find(v.comment_id)
if c.user_id != user_id
User.update_counters c.user_id, :karma => upvote - downvote
end
c.give_upvote_or_downvote_and_recalculate_confidence!(upvote,
downvote)
else
s = Story.find(v.story_id)
if s.user_id != user_id
User.update_counters s.user_id, :karma => upvote - downvote
end
s.give_upvote_or_downvote_and_recalculate_hotness!(upvote, downvote)
end
end
end
end
end