simplify flag reporting and correct it so it properly displays old flags

This commit is contained in:
Sam 2013-06-26 15:57:22 +10:00
parent 1323a717da
commit 65dc04c00e
2 changed files with 60 additions and 43 deletions

View file

@ -138,7 +138,10 @@ class PostAction < ActiveRecord::Base
end end
def self.remove_act(user, post, post_action_type_id) def self.remove_act(user, post, post_action_type_id)
if action = where(post_id: post.id, user_id: user.id, post_action_type_id: post_action_type_id).first if action = where(post_id: post.id,
user_id: user.id,
post_action_type_id:
post_action_type_id).first
action.trash! action.trash!
action.run_callbacks(:save) action.run_callbacks(:save)
end end
@ -297,32 +300,44 @@ class PostAction < ActiveRecord::Base
end end
def self.flagged_posts_report(filter) def self.flagged_posts_report(filter)
posts = flagged_posts(filter)
return nil if posts.blank? actions = flagged_post_actions(filter)
post_ids = actions.limit(300).pluck(:post_id).uniq
return nil if post_ids.blank?
posts = SqlBuilder.new("SELECT p.id, t.title, p.cooked, p.user_id,
p.topic_id, p.post_number, p.hidden, t.visible topic_visible
FROM posts p
JOIN topics t ON t.id = p.topic_id
WHERE p.id in (:post_ids)").map_exec(OpenStruct, post_ids: post_ids)
post_lookup = {} post_lookup = {}
users = Set.new users = Set.new
posts.each do |p| posts.each do |p|
users << p["user_id"] users << p.user_id
p["excerpt"] = Post.excerpt(p.delete("cooked")) p.excerpt = Post.excerpt(p.cooked)
p[:topic_slug] = Slug.for(p["title"]) p.topic_slug = Slug.for(p.title)
post_lookup[p["id"].to_i] = p post_lookup[p.id] = p
end end
post_actions = PostAction.includes({:related_post => :topic}) # maintain order
.where(post_action_type_id: PostActionType.notify_flag_type_ids) posts = post_ids.map{|id| post_lookup[id]}
.where(post_id: post_lookup.keys)
if filter == 'old' post_actions = actions.where(:post_id => post_ids)
post_actions = post_actions.with_deleted.where('deleted_at IS NOT NULL OR defer = true') .select('post_actions.id,
else post_actions.user_id,
post_actions = post_actions.where('defer IS NULL OR defer = false') post_action_type_id,
end post_actions.created_at,
post_actions.post_id,
post_actions.message')
.to_a
post_actions.each do |pa| post_actions.each do |pa|
post = post_lookup[pa.post_id] post = post_lookup[pa.post_id]
post[:post_actions] ||= [] post[:post_actions] ||= []
action = pa.attributes.slice('id', 'user_id', 'post_action_type_id', 'created_at', 'post_id', 'message') action = pa.attributes
if (pa.related_post && pa.related_post.topic) if (pa.related_post && pa.related_post.topic)
action.merge!(topic_id: pa.related_post.topic_id, action.merge!(topic_id: pa.related_post.topic_id,
slug: pa.related_post.topic.slug, slug: pa.related_post.topic.slug,
@ -332,42 +347,34 @@ class PostAction < ActiveRecord::Base
users << pa.user_id users << pa.user_id
end end
# TODO add serializer so we can skip this
posts.map!(&:to_h)
[posts, User.select([:id, :username, :email]).where(id: users.to_a).all] [posts, User.select([:id, :username, :email]).where(id: users.to_a).all]
end end
protected protected
def self.flagged_posts(filter) def self.flagged_post_actions(filter)
sql = SqlBuilder.new "select p.id, t.title, p.cooked, p.user_id, p.topic_id, p.post_number, p.hidden, t.visible topic_visible post_actions = PostAction
from posts p .includes({:related_post => :topic})
join topics t on t.id = topic_id .where(post_action_type_id: PostActionType.notify_flag_type_ids)
join ( .joins(:post => :topic)
select .order('post_actions.created_at DESC')
post_id,
count(*) as cnt,
max(created_at) max
from post_actions
/*where2*/
group by post_id
) as a on a.post_id = p.id
/*where*/
/*order_by*/
limit 100"
sql.where2 "post_action_type_id in (:flag_types)", flag_types: PostActionType.notify_flag_type_ids
# it may make sense to add a view that shows flags on deleted posts,
# we don't clear the flags on post deletion, just suppress counts
if filter == 'old' if filter == 'old'
sql.where2 "deleted_at is not null OR defer = true" post_actions
sql.order_by "max desc" .with_deleted
.where('post_actions.deleted_at IS NOT NULL OR
defer = true OR
topics.deleted_at IS NOT NULL OR
posts.deleted_at IS NOT NULL')
else else
sql.where "p.deleted_at is null and t.deleted_at is null" post_actions
sql.where2 "deleted_at is null and (defer IS NULL OR defer = false)" .where('defer IS NULL OR
sql.order_by "cnt desc, max asc" defer = false')
.where('posts.deleted_at IS NULL AND
topics.deleted_at IS NULL')
end end
sql.exec.to_a
end end
def self.target_moderators def self.target_moderators

View file

@ -12,6 +12,16 @@ describe PostAction do
let(:post) { Fabricate(:post) } let(:post) { Fabricate(:post) }
let(:bookmark) { PostAction.new(user_id: post.user_id, post_action_type_id: PostActionType.types[:bookmark] , post_id: post.id) } let(:bookmark) { PostAction.new(user_id: post.user_id, post_action_type_id: PostActionType.types[:bookmark] , post_id: post.id) }
describe "flagged_posts_report" do
it "operates correctly" do
PostAction.act(codinghorror, post, PostActionType.types[:spam])
posts, users = PostAction.flagged_posts_report("")
p posts
posts.count.should == 1
users.count.should == 2
end
end
describe "messaging" do describe "messaging" do
it "notify moderators integration test" do it "notify moderators integration test" do