mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-12-02 11:59:17 -05:00
PostDestroyer to replace callbacks for destroying
This commit is contained in:
parent
c1e40f5d19
commit
59fc3bfac4
9 changed files with 93 additions and 65 deletions
|
@ -1,4 +1,5 @@
|
||||||
require_dependency 'post_creator'
|
require_dependency 'post_creator'
|
||||||
|
require_dependency 'post_destroyer'
|
||||||
|
|
||||||
class PostsController < ApplicationController
|
class PostsController < ApplicationController
|
||||||
|
|
||||||
|
@ -83,7 +84,10 @@ class PostsController < ApplicationController
|
||||||
def destroy
|
def destroy
|
||||||
post = find_post_from_params
|
post = find_post_from_params
|
||||||
guardian.ensure_can_delete!(post)
|
guardian.ensure_can_delete!(post)
|
||||||
post.delete_by(current_user)
|
|
||||||
|
destroyer = PostDestroyer.new(current_user, post)
|
||||||
|
destroyer.destroy
|
||||||
|
|
||||||
render nothing: true
|
render nothing: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -143,25 +143,6 @@ class Post < ActiveRecord::Base
|
||||||
@raw_mentions = results.uniq.map { |un| un.first.downcase.gsub!(/^@/, '') }
|
@raw_mentions = results.uniq.map { |un| un.first.downcase.gsub!(/^@/, '') }
|
||||||
end
|
end
|
||||||
|
|
||||||
# The rules for deletion change depending on who is doing it.
|
|
||||||
def delete_by(deleted_by)
|
|
||||||
if deleted_by.moderator?
|
|
||||||
# As a moderator, delete the post.
|
|
||||||
Post.transaction do
|
|
||||||
self.destroy
|
|
||||||
Topic.reset_highest(topic_id)
|
|
||||||
update_flagged_posts_count
|
|
||||||
end
|
|
||||||
elsif deleted_by.id == user_id
|
|
||||||
# As the poster, make a revision that says deleted.
|
|
||||||
Post.transaction do
|
|
||||||
revise(deleted_by, I18n.t('js.post.deleted_by_author'), force_new_version: true)
|
|
||||||
update_column(:user_deleted, true)
|
|
||||||
update_flagged_posts_count
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def archetype
|
def archetype
|
||||||
topic.archetype
|
topic.archetype
|
||||||
end
|
end
|
||||||
|
@ -336,40 +317,6 @@ class Post < ActiveRecord::Base
|
||||||
self.cooked = cook(raw, topic_id: topic_id) unless new_record?
|
self.cooked = cook(raw, topic_id: topic_id) unless new_record?
|
||||||
end
|
end
|
||||||
|
|
||||||
before_destroy do
|
|
||||||
|
|
||||||
# Update the last post id to the previous post if it exists
|
|
||||||
last_post = Post.where("topic_id = ? and id <> ?", topic_id, id).order('created_at desc').limit(1).first
|
|
||||||
if last_post.present?
|
|
||||||
topic.update_attributes(last_posted_at: last_post.created_at,
|
|
||||||
last_post_user_id: last_post.user_id,
|
|
||||||
highest_post_number: last_post.post_number)
|
|
||||||
|
|
||||||
# If the poster doesn't have any other posts in the topic, clear their posted flag
|
|
||||||
unless Post.exists?(["topic_id = ? and user_id = ? and id <> ?", topic_id, user_id, id])
|
|
||||||
TopicUser.update_all 'posted = false', topic_id: topic_id, user_id: user_id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Feature users in the topic
|
|
||||||
Jobs.enqueue(:feature_topic_users, topic_id: topic_id, except_post_id: id)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
after_destroy do
|
|
||||||
# Remove any reply records that point to deleted posts
|
|
||||||
post_ids = PostReply.select(:post_id).where(reply_id: id).map(&:post_id)
|
|
||||||
PostReply.delete_all reply_id: id
|
|
||||||
|
|
||||||
if post_ids.present?
|
|
||||||
Post.where(id: post_ids).each { |p| p.update_column :reply_count, p.replies.count }
|
|
||||||
end
|
|
||||||
|
|
||||||
# Remove any notifications that point to this deleted post
|
|
||||||
Notification.delete_all topic_id: topic_id, post_number: post_number
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def advance_draft_sequence
|
def advance_draft_sequence
|
||||||
return if topic.blank? # could be deleted
|
return if topic.blank? # could be deleted
|
||||||
DraftSequence.next!(last_editor_id, topic.draft_key)
|
DraftSequence.next!(last_editor_id, topic.draft_key)
|
||||||
|
|
68
lib/post_destroyer.rb
Normal file
68
lib/post_destroyer.rb
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#
|
||||||
|
# How a post is deleted is affected by who is performing the action.
|
||||||
|
# this class contains the logic to delete it.
|
||||||
|
#
|
||||||
|
class PostDestroyer
|
||||||
|
|
||||||
|
def initialize(user, post)
|
||||||
|
@user, @post = user, post
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
if @user.moderator?
|
||||||
|
moderator_destroyed
|
||||||
|
elsif @user.id == @post.user_id
|
||||||
|
user_destroyed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# When a post is properly deleted. Well, it's still soft deleted, but it will no longer
|
||||||
|
# show up in the topic
|
||||||
|
def moderator_destroyed
|
||||||
|
Post.transaction do
|
||||||
|
|
||||||
|
# Update the last post id to the previous post if it exists
|
||||||
|
last_post = Post.where("topic_id = ? and id <> ?", @post.topic_id, @post.id).order('created_at desc').limit(1).first
|
||||||
|
if last_post.present?
|
||||||
|
@post.topic.update_attributes(last_posted_at: last_post.created_at,
|
||||||
|
last_post_user_id: last_post.user_id,
|
||||||
|
highest_post_number: last_post.post_number)
|
||||||
|
|
||||||
|
# If the poster doesn't have any other posts in the topic, clear their posted flag
|
||||||
|
unless Post.exists?(["topic_id = ? and user_id = ? and id <> ?", @post.topic_id, @post.user_id, @post.id])
|
||||||
|
TopicUser.update_all 'posted = false', topic_id: @post.topic_id, user_id: @post.user_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Feature users in the topic
|
||||||
|
Jobs.enqueue(:feature_topic_users, topic_id: @post.topic_id, except_post_id: @post.id)
|
||||||
|
|
||||||
|
# Actually soft-delete the post :)
|
||||||
|
@post.destroy
|
||||||
|
|
||||||
|
Topic.reset_highest(@post.topic_id)
|
||||||
|
@post.update_flagged_posts_count
|
||||||
|
|
||||||
|
# Remove any reply records that point to deleted posts
|
||||||
|
post_ids = PostReply.select(:post_id).where(reply_id: @post.id).map(&:post_id)
|
||||||
|
PostReply.delete_all reply_id: @post.id
|
||||||
|
|
||||||
|
if post_ids.present?
|
||||||
|
Post.where(id: post_ids).each { |p| p.update_column :reply_count, p.replies.count }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove any notifications that point to this deleted post
|
||||||
|
Notification.delete_all topic_id: @post.topic_id, post_number: @post.post_number
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# When a user 'deletes' their own post. We just change the text.
|
||||||
|
def user_destroyed
|
||||||
|
Post.transaction do
|
||||||
|
@post.revise(@user, I18n.t('js.post.deleted_by_author'), force_new_version: true)
|
||||||
|
@post.update_column(:user_deleted, true)
|
||||||
|
@post.update_flagged_posts_count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,5 +1,6 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
require 'guardian'
|
require 'guardian'
|
||||||
|
require_dependency 'post_destroyer'
|
||||||
|
|
||||||
describe Guardian do
|
describe Guardian do
|
||||||
|
|
||||||
|
@ -620,7 +621,7 @@ describe Guardian do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false when trying to delete your own post that has already been deleted" do
|
it "returns false when trying to delete your own post that has already been deleted" do
|
||||||
post.delete_by(user)
|
PostDestroyer.new(user, post).destroy
|
||||||
post.reload
|
post.reload
|
||||||
Guardian.new(user).can_delete?(post).should be_false
|
Guardian.new(user).can_delete?(post).should be_false
|
||||||
end
|
end
|
||||||
|
|
|
@ -85,8 +85,10 @@ describe PostsController do
|
||||||
response.should be_forbidden
|
response.should be_forbidden
|
||||||
end
|
end
|
||||||
|
|
||||||
it "calls delete_by" do
|
it "uses a PostDestroyer" do
|
||||||
Post.any_instance.expects(:delete_by).with(user)
|
destroyer = mock
|
||||||
|
PostDestroyer.expects(:new).with(user, post).returns(destroyer)
|
||||||
|
destroyer.expects(:destroy)
|
||||||
xhr :delete, :destroy, id: post.id
|
xhr :delete, :destroy, id: post.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
require_dependency 'post_destroyer'
|
||||||
|
|
||||||
describe PostAction do
|
describe PostAction do
|
||||||
|
|
||||||
|
@ -7,6 +8,7 @@ describe PostAction do
|
||||||
it { should belong_to :post_action_type }
|
it { should belong_to :post_action_type }
|
||||||
it { should rate_limit }
|
it { should rate_limit }
|
||||||
|
|
||||||
|
let(:moderator) { Fabricate(:moderator) }
|
||||||
let(:codinghorror) { Fabricate(:coding_horror) }
|
let(:codinghorror) { Fabricate(:coding_horror) }
|
||||||
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) }
|
||||||
|
@ -36,7 +38,7 @@ describe PostAction do
|
||||||
it "should reset counts when a post is deleted" do
|
it "should reset counts when a post is deleted" do
|
||||||
post2 = Fabricate(:post, topic_id: post.topic_id)
|
post2 = Fabricate(:post, topic_id: post.topic_id)
|
||||||
PostAction.act(codinghorror, post2, PostActionType.types[:off_topic])
|
PostAction.act(codinghorror, post2, PostActionType.types[:off_topic])
|
||||||
post2.destroy
|
PostDestroyer.new(moderator, post2).destroy
|
||||||
PostAction.flagged_posts_count.should == 0
|
PostAction.flagged_posts_count.should == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
require_dependency 'post_destroyer'
|
||||||
|
|
||||||
describe PostAlertObserver do
|
describe PostAlertObserver do
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ describe PostAlertObserver do
|
||||||
it 'removes notifications' do
|
it 'removes notifications' do
|
||||||
post = mention_post
|
post = mention_post
|
||||||
lambda {
|
lambda {
|
||||||
post.destroy
|
PostDestroyer.new(Fabricate(:moderator), post).destroy
|
||||||
}.should change(evil_trout.notifications, :count).by(-1)
|
}.should change(evil_trout.notifications, :count).by(-1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
require_dependency 'post_destroyer'
|
||||||
|
|
||||||
describe Post do
|
describe Post do
|
||||||
|
|
||||||
|
@ -486,7 +487,7 @@ describe Post do
|
||||||
context "as the creator of the post" do
|
context "as the creator of the post" do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
post.delete_by(post.user)
|
PostDestroyer.new(post.user, post).destroy
|
||||||
post.reload
|
post.reload
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -508,12 +509,12 @@ describe Post do
|
||||||
context "as a moderator" do
|
context "as a moderator" do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
post.delete_by(post.user)
|
PostDestroyer.new(moderator, post).destroy
|
||||||
post.reload
|
post.reload
|
||||||
end
|
end
|
||||||
|
|
||||||
it "deletes the post" do
|
it "deletes the post" do
|
||||||
post.deleted_at.should be_blank
|
post.deleted_at.should be_present
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -522,12 +523,13 @@ describe Post do
|
||||||
|
|
||||||
describe 'after delete' do
|
describe 'after delete' do
|
||||||
|
|
||||||
|
let(:moderator) { Fabricate(:moderator) }
|
||||||
let!(:coding_horror) { Fabricate(:coding_horror) }
|
let!(:coding_horror) { Fabricate(:coding_horror) }
|
||||||
let!(:post) { Fabricate(:post, post_args.merge(raw: "Hello @CodingHorror")) }
|
let!(:post) { Fabricate(:post, post_args.merge(raw: "Hello @CodingHorror")) }
|
||||||
|
|
||||||
it "should feature the users again (in case they've changed)" do
|
it "should feature the users again (in case they've changed)" do
|
||||||
Jobs.expects(:enqueue).with(:feature_topic_users, has_entries(topic_id: post.topic_id, except_post_id: post.id))
|
Jobs.expects(:enqueue).with(:feature_topic_users, has_entries(topic_id: post.topic_id, except_post_id: post.id))
|
||||||
post.destroy
|
PostDestroyer.new(moderator, post).destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'with a reply' do
|
describe 'with a reply' do
|
||||||
|
@ -545,7 +547,7 @@ describe Post do
|
||||||
|
|
||||||
it 'lowers the reply_count when the reply is deleted' do
|
it 'lowers the reply_count when the reply is deleted' do
|
||||||
lambda {
|
lambda {
|
||||||
reply.destroy
|
PostDestroyer.new(moderator, reply).destroy
|
||||||
post.reload
|
post.reload
|
||||||
}.should change(post.post_replies, :count).by(-1)
|
}.should change(post.post_replies, :count).by(-1)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
require_dependency 'post_destroyer'
|
||||||
|
|
||||||
describe Topic do
|
describe Topic do
|
||||||
|
|
||||||
|
@ -808,7 +809,7 @@ describe Topic do
|
||||||
context 'after deleting that post' do
|
context 'after deleting that post' do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@new_post.destroy
|
PostDestroyer.new(Fabricate(:moderator), @new_post).destroy
|
||||||
Topic.reset_highest(@topic.id)
|
Topic.reset_highest(@topic.id)
|
||||||
@topic.reload
|
@topic.reload
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue