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:
parent
fe159cc3f7
commit
f9b309d342
|
@ -237,8 +237,7 @@ class StoriesController < ApplicationController
|
||||||
return render :text => "can't find story", :status => 400
|
return render :text => "can't find story", :status => 400
|
||||||
end
|
end
|
||||||
|
|
||||||
Vote.vote_thusly_on_story_or_comment_for_user_because(0, story.id,
|
HiddenStory.hide_story_for_user(story.id, @user.id)
|
||||||
nil, @user.id, "H")
|
|
||||||
|
|
||||||
render :text => "ok"
|
render :text => "ok"
|
||||||
end
|
end
|
||||||
|
@ -248,8 +247,7 @@ class StoriesController < ApplicationController
|
||||||
return render :text => "can't find story", :status => 400
|
return render :text => "can't find story", :status => 400
|
||||||
end
|
end
|
||||||
|
|
||||||
Vote.vote_thusly_on_story_or_comment_for_user_because(0, story.id,
|
HiddenStory.where(:user_id => @user.id, :story_id => story.id).delete_all
|
||||||
nil, @user.id, nil)
|
|
||||||
|
|
||||||
render :text => "ok"
|
render :text => "ok"
|
||||||
end
|
end
|
||||||
|
@ -299,9 +297,11 @@ private
|
||||||
if @user
|
if @user
|
||||||
if v = Vote.where(:user_id => @user.id, :story_id => @story.id,
|
if v = Vote.where(:user_id => @user.id, :story_id => @story.id,
|
||||||
:comment_id => nil).first
|
:comment_id => nil).first
|
||||||
@story.vote = v.vote
|
@story.vote = { :vote => v.vote, :reason => v.reason }
|
||||||
end
|
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)
|
@votes = Vote.comment_votes_by_user_for_story_hash(@user.id, @story.id)
|
||||||
@comments.each do |c|
|
@comments.each do |c|
|
||||||
if @votes[c.id]
|
if @votes[c.id]
|
||||||
|
|
11
app/models/hidden_story.rb
Normal file
11
app/models/hidden_story.rb
Normal 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
|
|
@ -26,10 +26,16 @@ private
|
||||||
if @user
|
if @user
|
||||||
votes = Vote.votes_by_user_for_stories_hash(@user.id, scope.map(&:id))
|
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|
|
scope.each do |s|
|
||||||
if votes[s.id]
|
if votes[s.id]
|
||||||
s.vote = votes[s.id]
|
s.vote = votes[s.id]
|
||||||
end
|
end
|
||||||
|
if hs.include?(s.id)
|
||||||
|
s.is_hidden_by_cur_user = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
scope
|
scope
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Story < ActiveRecord::Base
|
||||||
RECENT_DAYS = 30
|
RECENT_DAYS = 30
|
||||||
|
|
||||||
attr_accessor :vote, :already_posted_story, :fetched_content, :previewing,
|
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
|
attr_accessor :editor, :moderation_reason, :merge_story_short_id
|
||||||
|
|
||||||
before_validation :assign_short_id_and_upvote,
|
before_validation :assign_short_id_and_upvote,
|
||||||
|
@ -298,11 +298,11 @@ class Story < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def hider_count
|
def hider_count
|
||||||
@hider_count ||= Vote.where(:story_id => self.id, :comment_id => nil,
|
@hider_count ||= HiddenStory.where(:story_id => self.id).count
|
||||||
:vote => 0).count
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_downvotable?
|
def is_downvotable?
|
||||||
|
return true
|
||||||
if self.created_at
|
if self.created_at
|
||||||
Time.now - self.created_at <= DOWNVOTABLE_DAYS.days
|
Time.now - self.created_at <= DOWNVOTABLE_DAYS.days
|
||||||
else
|
else
|
||||||
|
@ -328,6 +328,10 @@ class Story < ActiveRecord::Base
|
||||||
is_expired?
|
is_expired?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def is_hidden_by_user?(user)
|
||||||
|
!!HiddenStory.where(:user_id => user.id, :story_id => self.id).first
|
||||||
|
end
|
||||||
|
|
||||||
def is_recent?
|
def is_recent?
|
||||||
self.created_at >= RECENT_DAYS.days.ago
|
self.created_at >= RECENT_DAYS.days.ago
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,7 @@ class StoryRepository
|
||||||
|
|
||||||
def hottest
|
def hottest
|
||||||
hottest = positive_ranked base_scope
|
hottest = positive_ranked base_scope
|
||||||
hottest = filter_downvoted_and_tags hottest
|
hottest = filter_hidden_and_tags hottest
|
||||||
hottest.order('hotness')
|
hottest.order('hotness')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ class StoryRepository
|
||||||
end
|
end
|
||||||
|
|
||||||
def newest
|
def newest
|
||||||
newest = filter_downvoted_and_tags base_scope
|
newest = filter_hidden_and_tags base_scope
|
||||||
newest.order("stories.id DESC")
|
newest.order("stories.id DESC")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -94,9 +94,9 @@ private
|
||||||
Story.unmerged.where(is_expired: false)
|
Story.unmerged.where(is_expired: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_downvoted_and_tags(scope)
|
def filter_hidden_and_tags(scope)
|
||||||
if @user
|
if @user
|
||||||
scope = filter_downvoted scope
|
scope = filter_hidden scope
|
||||||
end
|
end
|
||||||
if @params[:exclude_tags].try(:any?)
|
if @params[:exclude_tags].try(:any?)
|
||||||
scope = filter_tags scope, @params[:exclude_tags]
|
scope = filter_tags scope, @params[:exclude_tags]
|
||||||
|
@ -104,20 +104,16 @@ private
|
||||||
scope
|
scope
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_downvoted(scope)
|
def filter_hidden(scope)
|
||||||
scope.where(Story.arel_table[:id].not_in(hidden_arel))
|
scope.where(Story.arel_table[:id].not_in(hidden_arel))
|
||||||
end
|
end
|
||||||
|
|
||||||
def hidden_arel
|
def hidden_arel
|
||||||
if @user
|
if @user
|
||||||
hidden_arel = Vote.arel_table.where(
|
hidden_arel = HiddenStory.arel_table.where(
|
||||||
Vote.arel_table[:user_id].eq(@user.id)
|
HiddenStory.arel_table[:user_id].eq(@user.id)
|
||||||
).where(
|
|
||||||
Vote.arel_table[:vote].lteq(0)
|
|
||||||
).where(
|
|
||||||
Vote.arel_table[:comment_id].eq(nil)
|
|
||||||
).project(
|
).project(
|
||||||
Vote.arel_table[:story_id]
|
HiddenStory.arel_table[:story_id]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Vote < ActiveRecord::Base
|
||||||
|
|
||||||
Vote.where(:user_id => user, :story_id => stories,
|
Vote.where(:user_id => user, :story_id => stories,
|
||||||
:comment_id => nil).each do |v|
|
:comment_id => nil).each do |v|
|
||||||
votes[v.story_id] = v.vote
|
votes[v.story_id] = { :vote => v.vote, :reason => v.reason }
|
||||||
end
|
end
|
||||||
|
|
||||||
votes
|
votes
|
||||||
|
@ -84,7 +84,7 @@ class Vote < ActiveRecord::Base
|
||||||
v = Vote.where(:user_id => user_id, :story_id => story_id,
|
v = Vote.where(:user_id => user_id, :story_id => story_id,
|
||||||
:comment_id => comment_id).first_or_initialize
|
:comment_id => comment_id).first_or_initialize
|
||||||
|
|
||||||
if !v.new_record? && v.vote == vote && vote != 0
|
if !v.new_record? && v.vote == vote
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ class Vote < ActiveRecord::Base
|
||||||
|
|
||||||
Vote.transaction do
|
Vote.transaction do
|
||||||
# unvote
|
# unvote
|
||||||
if vote == 0 && reason == nil
|
if vote == 0
|
||||||
# neutralize previous vote
|
# neutralize previous vote
|
||||||
upvote = (v.vote == 1 ? -1 : 0)
|
upvote = (v.vote == 1 ? -1 : 0)
|
||||||
downvote = (v.vote == -1 ? -1 : 0)
|
downvote = (v.vote == -1 ? -1 : 0)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<li id="story_<%= story.short_id %>" data-shortid="<%= story.short_id %>"
|
<li id="story_<%= story.short_id %>" data-shortid="<%= story.short_id %>"
|
||||||
class="story <%= story.vote == 1 ? "upvoted" : "" %> <%= story.vote == -1 ?
|
class="story <%= story.vote && story.vote[:vote] == 1 ? "upvoted" : "" %>
|
||||||
"downvoted" : "" %> <%= story.vote == 0 ? "hidden" : "" %> <%= story.is_expired? ?
|
<%= story.vote && story.vote[:vote] == -1 ? "downvoted" : "" %>
|
||||||
"expired" : "" %>">
|
<%= story.is_hidden_by_cur_user ? "hidden" : "" %>
|
||||||
|
<%= story.is_expired? ? "expired" : "" %>">
|
||||||
<div class="story_liner">
|
<div class="story_liner">
|
||||||
<div class="voters">
|
<div class="voters">
|
||||||
<% if @user %>
|
<% if @user %>
|
||||||
|
@ -100,10 +101,13 @@ class="story <%= story.vote == 1 ? "upvoted" : "" %> <%= story.vote == -1 ?
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if !story.is_gone? && @user %>
|
<% 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>
|
| <a class="flagger">flag</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if story.vote == 0 %>
|
<% if story.is_hidden_by_cur_user %>
|
||||||
| <%= link_to "unhide", story_unhide_path(story.short_id),
|
| <%= link_to "unhide", story_unhide_path(story.short_id),
|
||||||
:class => "hider" %>
|
:class => "hider" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
|
|
@ -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
|
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# 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|
|
create_table "comments", force: true do |t|
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
|
@ -46,6 +46,13 @@ ActiveRecord::Schema.define(version: 20150127180326) do
|
||||||
t.string "link"
|
t.string "link"
|
||||||
end
|
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|
|
create_table "invitation_requests", force: true do |t|
|
||||||
t.string "code"
|
t.string "code"
|
||||||
t.boolean "is_verified", default: false
|
t.boolean "is_verified", default: false
|
||||||
|
|
Loading…
Reference in a new issue