journalduhacker/app/models/vote.rb
joshua stein e940601a2f start on automated story title and tagging suggestions
Rather than keep "poorly titled" and "poorly tagged" as reasons for
flagging, make the user do the work of suggesting new ones.

At some point, suggested taggings will flip to real taggings once
they reach a certain count (to be determined later).  This also has
to take into account tagging sets that don't contain current tags,
for when they need to be removed.

For titles, I'm not yet sure how to handle this in an automated
fashion except for the (probably rare) case of multiple users
submitting the same exact thing, but at least collect them for now.

Issue #207
2015-10-14 20:32:24 -05:00

137 lines
3.1 KiB
Ruby

class Vote < ActiveRecord::Base
belongs_to :user
belongs_to :story
belongs_to :comment
COMMENT_REASONS = {
"O" => "Off-topic",
"I" => "Incorrect",
"M" => "Me-too",
"T" => "Troll",
"S" => "Spam",
"" => "Cancel",
}
STORY_REASONS = {
"O" => "Off-topic",
"A" => "Already Posted",
"S" => "Spam",
"" => "Cancel",
}
OLD_STORY_REASONS = {
"Q" => "Low Quality",
}
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] = { :vote => v.vote, :reason => v.reason }
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
return
end
upvote = 0
downvote = 0
Vote.transaction do
# unvote
if vote == 0
# 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