remove acts_as_paranoid, use .trash! , .recover! and .with_deleted as needed

makes upgrading to rails 4 possible
This commit is contained in:
Sam 2013-05-07 14:39:01 +10:00
parent a71a15913c
commit e9fc272db7
21 changed files with 77 additions and 36 deletions

View File

@ -15,7 +15,6 @@ gem 'simple_handlebars_rails', path: 'vendor/gems/simple_handlebars_rails'
gem 'redcarpet', require: false gem 'redcarpet', require: false
gem 'activerecord-postgres-hstore' gem 'activerecord-postgres-hstore'
gem 'acts_as_paranoid'
gem 'active_attr' # until we get ActiveModel::Model with Rails 4 gem 'active_attr' # until we get ActiveModel::Model with Rails 4
gem 'airbrake', '3.1.2', require: false # errbit is broken with 3.1.3 for now gem 'airbrake', '3.1.2', require: false # errbit is broken with 3.1.3 for now
gem 'clockwork', require: false gem 'clockwork', require: false

View File

@ -120,8 +120,6 @@ GEM
activesupport (3.2.12) activesupport (3.2.12)
i18n (~> 0.6) i18n (~> 0.6)
multi_json (~> 1.0) multi_json (~> 1.0)
acts_as_paranoid (0.4.1)
activerecord (~> 3.2)
airbrake (3.1.2) airbrake (3.1.2)
activesupport activesupport
builder builder
@ -448,7 +446,6 @@ DEPENDENCIES
active_attr active_attr
active_model_serializers! active_model_serializers!
activerecord-postgres-hstore activerecord-postgres-hstore
acts_as_paranoid
airbrake (= 3.1.2) airbrake (= 3.1.2)
barber (= 0.3.0) barber (= 0.3.0)
better_errors better_errors

View File

@ -33,7 +33,7 @@ class InvitesController < ApplicationController
invite = Invite.where(invited_by_id: current_user.id, email: params[:email]).first invite = Invite.where(invited_by_id: current_user.id, email: params[:email]).first
raise Discourse::InvalidParameters.new(:email) if invite.blank? raise Discourse::InvalidParameters.new(:email) if invite.blank?
invite.destroy invite.trash!
render nothing: true render nothing: true
end end

View File

@ -128,7 +128,7 @@ class PostsController < ApplicationController
def recover def recover
post = find_post_from_params post = find_post_from_params
guardian.ensure_can_recover_post!(post) guardian.ensure_can_recover_post!(post)
post.recover post.recover!
render nothing: true render nothing: true
end end

View File

@ -100,7 +100,7 @@ class TopicsController < ApplicationController
def destroy def destroy
topic = Topic.where(id: params[:id]).first topic = Topic.where(id: params[:id]).first
guardian.ensure_can_delete!(topic) guardian.ensure_can_delete!(topic)
topic.destroy topic.trash!
render nothing: true render nothing: true
end end

View File

@ -1,4 +1,7 @@
require_dependency 'trashable'
class Invite < ActiveRecord::Base class Invite < ActiveRecord::Base
include Trashable
belongs_to :user belongs_to :user
belongs_to :topic belongs_to :topic
@ -9,8 +12,6 @@ class Invite < ActiveRecord::Base
validates_presence_of :email validates_presence_of :email
validates_presence_of :invited_by_id validates_presence_of :invited_by_id
acts_as_paranoid
before_create do before_create do
self.invite_key ||= SecureRandom.hex self.invite_key ||= SecureRandom.hex
end end

View File

@ -3,19 +3,19 @@ require_dependency 'pretty_text'
require_dependency 'rate_limiter' require_dependency 'rate_limiter'
require_dependency 'post_revisor' require_dependency 'post_revisor'
require_dependency 'enum' require_dependency 'enum'
require_dependency 'trashable'
require 'archetype' require 'archetype'
require 'digest/sha1' require 'digest/sha1'
class Post < ActiveRecord::Base class Post < ActiveRecord::Base
include RateLimiter::OnCreateRecord include RateLimiter::OnCreateRecord
include Trashable
versioned if: :raw_changed? versioned if: :raw_changed?
rate_limit rate_limit
acts_as_paranoid
after_recover :update_flagged_posts_count
belongs_to :user belongs_to :user
belongs_to :topic, counter_cache: :posts_count belongs_to :topic, counter_cache: :posts_count
@ -52,6 +52,11 @@ class Post < ActiveRecord::Base
@types ||= Enum.new(:regular, :moderator_action) @types ||= Enum.new(:regular, :moderator_action)
end end
def recover!
super
update_flagged_posts_count
end
def raw_quality def raw_quality
sentinel = TextSentinel.body_sentinel(raw) sentinel = TextSentinel.body_sentinel(raw)
errors.add(:raw, I18n.t(:is_invalid)) unless sentinel.valid? errors.add(:raw, I18n.t(:is_invalid)) unless sentinel.valid?

View File

@ -1,10 +1,12 @@
require_dependency 'rate_limiter' require_dependency 'rate_limiter'
require_dependency 'system_message' require_dependency 'system_message'
require_dependency 'trashable'
class PostAction < ActiveRecord::Base class PostAction < ActiveRecord::Base
class AlreadyActed < StandardError; end class AlreadyActed < StandardError; end
include RateLimiter::OnCreateRecord include RateLimiter::OnCreateRecord
include Trashable
attr_accessible :post_action_type_id, :post_id, :user_id, :post, :user, :post_action_type, :message, :related_post_id attr_accessible :post_action_type_id, :post_id, :user_id, :post, :user, :post_action_type, :message, :related_post_id
@ -12,8 +14,6 @@ class PostAction < ActiveRecord::Base
belongs_to :user belongs_to :user
belongs_to :post_action_type belongs_to :post_action_type
acts_as_paranoid
rate_limit :post_action_rate_limiter rate_limit :post_action_rate_limiter
validate :message_quality validate :message_quality
@ -114,8 +114,7 @@ class PostAction < ActiveRecord::Base
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.destroy action.trash!
action.deleted_at = Time.zone.now
action.run_callbacks(:save) action.run_callbacks(:save)
end end
end end

View File

@ -4,10 +4,12 @@ require_dependency 'topic_view'
require_dependency 'rate_limiter' require_dependency 'rate_limiter'
require_dependency 'text_sentinel' require_dependency 'text_sentinel'
require_dependency 'text_cleaner' require_dependency 'text_cleaner'
require_dependency 'trashable'
class Topic < ActiveRecord::Base class Topic < ActiveRecord::Base
include ActionView::Helpers include ActionView::Helpers
include RateLimiter::OnCreateRecord include RateLimiter::OnCreateRecord
include Trashable
def self.max_sort_order def self.max_sort_order
2**31 - 1 2**31 - 1
@ -18,9 +20,17 @@ class Topic < ActiveRecord::Base
end end
versioned if: :new_version_required? versioned if: :new_version_required?
acts_as_paranoid
after_recover :update_flagged_posts_count
after_destroy :update_flagged_posts_count def trash!
super
update_flagged_posts_count
end
def recover!
super
update_flagged_posts_count
end
rate_limit :default_rate_limiter rate_limit :default_rate_limiter
rate_limit :limit_topics_per_day rate_limit :limit_topics_per_day

View File

@ -442,11 +442,11 @@ class User < ActiveRecord::Base
posts.order("post_number desc").each do |p| posts.order("post_number desc").each do |p|
if p.post_number == 1 if p.post_number == 1
p.topic.destroy p.topic.trash!
# TODO: But the post is not destroyed. Why? # TODO: But the post is not destroyed. Why?
else else
# TODO: This should be using the PostDestroyer! # TODO: This should be using the PostDestroyer!
p.destroy p.trash!
end end
end end
end end

View File

@ -14,7 +14,6 @@ The following Ruby Gems are used in Discourse:
* [rack-mini-profiler](https://rubygems.org/gems/rack-mini-profiler) * [rack-mini-profiler](https://rubygems.org/gems/rack-mini-profiler)
* [sass](https://rubygems.org/gems/sass) * [sass](https://rubygems.org/gems/sass)
* [rest-client](https://rubygems.org/gems/rest-client) * [rest-client](https://rubygems.org/gems/rest-client)
* [rails3_acts_as_paranoid](https://rubygems.org/gems/rails3_acts_as_paranoid)
* [activerecord-postgres-hstore](https://rubygems.org/gems/activerecord-postgres-hstore) * [activerecord-postgres-hstore](https://rubygems.org/gems/activerecord-postgres-hstore)
* [fastimage](https://rubygems.org/gems/fastimage) * [fastimage](https://rubygems.org/gems/fastimage)
* [seed-fu](https://rubygems.org/gems/seed-fu) * [seed-fu](https://rubygems.org/gems/seed-fu)

View File

@ -37,8 +37,7 @@ class PostDestroyer
# Feature users in the topic # Feature users in the topic
Jobs.enqueue(:feature_topic_users, topic_id: @post.topic_id, except_post_id: @post.id) Jobs.enqueue(:feature_topic_users, topic_id: @post.topic_id, except_post_id: @post.id)
# Actually soft-delete the post :) @post.trash!
@post.destroy
Topic.reset_highest(@post.topic_id) Topic.reset_highest(@post.topic_id)
@post.update_flagged_posts_count @post.update_flagged_posts_count

32
lib/trashable.rb Normal file
View File

@ -0,0 +1,32 @@
module Trashable
extend ActiveSupport::Concern
included do
default_scope where(with_deleted_scope_sql)
end
module ClassMethods
def with_deleted
# lifted from acts_as_paranoid, works around http://stackoverflow.com/questions/8734669/rails-3-1-3-unscoped-scope
scope = self.scoped.with_default_scope
scope.where_values.delete(with_deleted_scope_sql)
scope
end
def with_deleted_scope_sql
self.scoped.table[:deleted_at].eq(nil).to_sql
end
end
def trash!
self.update_column(:deleted_at, DateTime.now)
end
def recover!
# see: https://github.com/rails/rails/issues/8436
self.class.unscoped.update_all({deleted_at: nil}, id: self.id)
raw_write_attribute :deleted_at, nil
end
end

View File

@ -222,14 +222,14 @@ describe Guardian do
it 'correctly handles post visibility' do it 'correctly handles post visibility' do
Guardian.new(user).can_see?(post).should be_true Guardian.new(user).can_see?(post).should be_true
post.destroy post.trash!
post.reload post.reload
Guardian.new(user).can_see?(post).should be_false Guardian.new(user).can_see?(post).should be_false
Guardian.new(admin).can_see?(post).should be_true Guardian.new(admin).can_see?(post).should be_true
post.recover post.recover!
post.reload post.reload
topic.destroy topic.trash!
topic.reload topic.reload
Guardian.new(user).can_see?(post).should be_false Guardian.new(user).can_see?(post).should be_false
Guardian.new(admin).can_see?(post).should be_true Guardian.new(admin).can_see?(post).should be_true

View File

@ -196,7 +196,7 @@ describe TopicView do
describe "filter_posts_after" do describe "filter_posts_after" do
it "returns undeleted posts after a post" do it "returns undeleted posts after a post" do
topic_view.filter_posts_after(p1.post_number).should == [p2, p3, p5] topic_view.filter_posts_after(p1.post_number).map(&:id).should == [p2.id, p3.id, p5.id]
topic_view.should_not be_initial_load topic_view.should_not be_initial_load
topic_view.index_offset.should == 1 topic_view.index_offset.should == 1
topic_view.index_reverse.should be_false topic_view.index_reverse.should be_false

View File

@ -29,7 +29,7 @@ describe InvitesController do
end end
it "destroys the invite" do it "destroys the invite" do
Invite.any_instance.expects(:destroy) Invite.any_instance.expects(:trash!)
delete :destroy, email: invite.email delete :destroy, email: invite.email
end end

View File

@ -120,7 +120,7 @@ describe PostActionsController do
end end
it "works with a deleted post" do it "works with a deleted post" do
flagged_post.destroy flagged_post.trash!
xhr :post, :clear_flags, id: flagged_post.id, post_action_type_id: PostActionType.types[:spam] xhr :post, :clear_flags, id: flagged_post.id, post_action_type_id: PostActionType.types[:spam]
response.should be_success response.should be_success
end end

View File

@ -30,7 +30,7 @@ describe PostsController do
context "deleted post" do context "deleted post" do
before do before do
post.destroy post.trash!
end end
it "can't find deleted posts as an anonymous user" do it "can't find deleted posts as an anonymous user" do
@ -121,7 +121,7 @@ describe PostsController do
end end
it "calls recover" do it "calls recover" do
Post.any_instance.expects(:recover) Post.any_instance.expects(:recover!)
xhr :put, :recover, post_id: post.id xhr :put, :recover, post_id: post.id
end end

View File

@ -78,7 +78,7 @@ describe PostAction do
it "should reset counts when a topic is deleted" do it "should reset counts when a topic is deleted" do
PostAction.act(codinghorror, post, PostActionType.types[:off_topic]) PostAction.act(codinghorror, post, PostActionType.types[:off_topic])
post.topic.destroy post.topic.trash!
PostAction.flagged_posts_count.should == 0 PostAction.flagged_posts_count.should == 0
end end

View File

@ -50,7 +50,7 @@ describe Post do
let(:post) { Fabricate(:post, post_args) } let(:post) { Fabricate(:post, post_args) }
before do before do
post.destroy post.trash!
post.reload post.reload
end end
@ -60,7 +60,7 @@ describe Post do
describe "recovery" do describe "recovery" do
before do before do
post.recover post.recover!
post.reload post.reload
end end

View File

@ -58,7 +58,7 @@ describe UserAction do
other_stats.should == expecting other_stats.should == expecting
public_topic.destroy public_topic.trash!
stats_for_user.should == [] stats_for_user.should == []
stream_count.should == 0 stream_count.should == 0
@ -66,7 +66,7 @@ describe UserAction do
category = Fabricate(:category, secure: true) category = Fabricate(:category, secure: true)
public_topic.recover public_topic.recover!
public_topic.category = category public_topic.category = category
public_topic.save public_topic.save