separate story hiding from voting

A story downvote is considered a flag, just meaning the story has
problems and not necessarily that the user wants to ignore it.  By
moving hiding out of Vote and into a new HiddenStory model, a user
can now both downvote/flag and hide separately, or just one or the
other.
This commit is contained in:
joshua stein 2015-02-11 11:37:03 -06:00
parent fe159cc3f7
commit f9b309d342
9 changed files with 76 additions and 29 deletions

View file

@ -237,8 +237,7 @@ class StoriesController < ApplicationController
return render :text => "can't find story", :status => 400
end
Vote.vote_thusly_on_story_or_comment_for_user_because(0, story.id,
nil, @user.id, "H")
HiddenStory.hide_story_for_user(story.id, @user.id)
render :text => "ok"
end
@ -248,8 +247,7 @@ class StoriesController < ApplicationController
return render :text => "can't find story", :status => 400
end
Vote.vote_thusly_on_story_or_comment_for_user_because(0, story.id,
nil, @user.id, nil)
HiddenStory.where(:user_id => @user.id, :story_id => story.id).delete_all
render :text => "ok"
end
@ -299,9 +297,11 @@ private
if @user
if v = Vote.where(:user_id => @user.id, :story_id => @story.id,
:comment_id => nil).first
@story.vote = v.vote
@story.vote = { :vote => v.vote, :reason => v.reason }
end
@story.is_hidden_by_cur_user = @story.is_hidden_by_user?(@user)
@votes = Vote.comment_votes_by_user_for_story_hash(@user.id, @story.id)
@comments.each do |c|
if @votes[c.id]

View file

@ -0,0 +1,11 @@
class HiddenStory < ActiveRecord::Base
belongs_to :user
belongs_to :story
validates_presence_of :user_id, :story_id
def self.hide_story_for_user(story_id, user_id)
HiddenStory.where(:user_id => user_id, :story_id =>
story_id).first_or_initialize.save!
end
end

View file

@ -26,10 +26,16 @@ private
if @user
votes = Vote.votes_by_user_for_stories_hash(@user.id, scope.map(&:id))
hs = HiddenStory.where(:user_id => @user.id, :story_id =>
scope.map(&:id)).map(&:story_id)
scope.each do |s|
if votes[s.id]
s.vote = votes[s.id]
end
if hs.include?(s.id)
s.is_hidden_by_cur_user = true
end
end
end
scope

View file

@ -31,7 +31,7 @@ class Story < ActiveRecord::Base
RECENT_DAYS = 30
attr_accessor :vote, :already_posted_story, :fetched_content, :previewing,
:seen_previous
:seen_previous, :is_hidden_by_cur_user
attr_accessor :editor, :moderation_reason, :merge_story_short_id
before_validation :assign_short_id_and_upvote,
@ -298,11 +298,11 @@ class Story < ActiveRecord::Base
end
def hider_count
@hider_count ||= Vote.where(:story_id => self.id, :comment_id => nil,
:vote => 0).count
@hider_count ||= HiddenStory.where(:story_id => self.id).count
end
def is_downvotable?
return true
if self.created_at
Time.now - self.created_at <= DOWNVOTABLE_DAYS.days
else
@ -328,6 +328,10 @@ class Story < ActiveRecord::Base
is_expired?
end
def is_hidden_by_user?(user)
!!HiddenStory.where(:user_id => user.id, :story_id => self.id).first
end
def is_recent?
self.created_at >= RECENT_DAYS.days.ago
end

View file

@ -11,7 +11,7 @@ class StoryRepository
def hottest
hottest = positive_ranked base_scope
hottest = filter_downvoted_and_tags hottest
hottest = filter_hidden_and_tags hottest
hottest.order('hotness')
end
@ -27,7 +27,7 @@ class StoryRepository
end
def newest
newest = filter_downvoted_and_tags base_scope
newest = filter_hidden_and_tags base_scope
newest.order("stories.id DESC")
end
@ -94,9 +94,9 @@ private
Story.unmerged.where(is_expired: false)
end
def filter_downvoted_and_tags(scope)
def filter_hidden_and_tags(scope)
if @user
scope = filter_downvoted scope
scope = filter_hidden scope
end
if @params[:exclude_tags].try(:any?)
scope = filter_tags scope, @params[:exclude_tags]
@ -104,20 +104,16 @@ private
scope
end
def filter_downvoted(scope)
def filter_hidden(scope)
scope.where(Story.arel_table[:id].not_in(hidden_arel))
end
def hidden_arel
if @user
hidden_arel = Vote.arel_table.where(
Vote.arel_table[:user_id].eq(@user.id)
).where(
Vote.arel_table[:vote].lteq(0)
).where(
Vote.arel_table[:comment_id].eq(nil)
hidden_arel = HiddenStory.arel_table.where(
HiddenStory.arel_table[:user_id].eq(@user.id)
).project(
Vote.arel_table[:story_id]
HiddenStory.arel_table[:story_id]
)
end
end

View file

@ -28,7 +28,7 @@ class Vote < ActiveRecord::Base
Vote.where(:user_id => user, :story_id => stories,
:comment_id => nil).each do |v|
votes[v.story_id] = v.vote
votes[v.story_id] = { :vote => v.vote, :reason => v.reason }
end
votes
@ -84,7 +84,7 @@ class Vote < ActiveRecord::Base
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
if !v.new_record? && v.vote == vote
return
end
@ -93,7 +93,7 @@ class Vote < ActiveRecord::Base
Vote.transaction do
# unvote
if vote == 0 && reason == nil
if vote == 0
# neutralize previous vote
upvote = (v.vote == 1 ? -1 : 0)
downvote = (v.vote == -1 ? -1 : 0)

View file

@ -1,7 +1,8 @@
<li id="story_<%= story.short_id %>" data-shortid="<%= story.short_id %>"
class="story <%= story.vote == 1 ? "upvoted" : "" %> <%= story.vote == -1 ?
"downvoted" : "" %> <%= story.vote == 0 ? "hidden" : "" %> <%= story.is_expired? ?
"expired" : "" %>">
class="story <%= story.vote && story.vote[:vote] == 1 ? "upvoted" : "" %>
<%= story.vote && story.vote[:vote] == -1 ? "downvoted" : "" %>
<%= story.is_hidden_by_cur_user ? "hidden" : "" %>
<%= story.is_expired? ? "expired" : "" %>">
<div class="story_liner">
<div class="voters">
<% if @user %>
@ -100,10 +101,13 @@ class="story <%= story.vote == 1 ? "upvoted" : "" %> <%= story.vote == -1 ?
<% end %>
<% end %>
<% if !story.is_gone? && @user %>
<% if @user && @user.can_downvote?(story) %>
<% if @user && story.vote && story.vote[:vote] == -1 %>
| <a class="flagger">unflag (<%=
Vote::STORY_REASONS[story.vote[:reason]].to_s.downcase %>)</a>
<% elsif @user && @user.can_downvote?(story) %>
| <a class="flagger">flag</a>
<% end %>
<% if story.vote == 0 %>
<% if story.is_hidden_by_cur_user %>
| <%= link_to "unhide", story_unhide_path(story.short_id),
:class => "hider" %>
<% else %>

View file

@ -0,0 +1,19 @@
class MoveHiddenVotesToHiddenStory < ActiveRecord::Migration
def up
create_table :hidden_stories do |t|
t.integer :user_id
t.integer :story_id
end
add_index "hidden_stories", ["user_id", "story_id"], :unique => true
Vote.where(:vote => 0).each do |v|
hs = HiddenStory.new
hs.user_id = v.user_id
hs.story_id = v.story_id
hs.save!
end
Vote.where(:vote => 0).delete_all
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150127180326) do
ActiveRecord::Schema.define(version: 20150211170052) do
create_table "comments", force: true do |t|
t.datetime "created_at", null: false
@ -46,6 +46,13 @@ ActiveRecord::Schema.define(version: 20150127180326) do
t.string "link"
end
create_table "hidden_stories", force: true do |t|
t.integer "user_id"
t.integer "story_id"
end
add_index "hidden_stories", ["user_id", "story_id"], name: "index_hidden_stories_on_user_id_and_story_id", unique: true, using: :btree
create_table "invitation_requests", force: true do |t|
t.string "code"
t.boolean "is_verified", default: false