From c98ad454fbbb8a56004cb4f495a47af53090239e Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Wed, 1 Nov 2017 15:53:59 -0700 Subject: [PATCH 1/4] Use define_model_callbacks --- lib/paranoia.rb | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/lib/paranoia.rb b/lib/paranoia.rb index a2298953..374970be 100644 --- a/lib/paranoia.rb +++ b/lib/paranoia.rb @@ -14,7 +14,6 @@ def self.default_sentinel_value def self.included(klazz) klazz.extend Query - klazz.extend Callbacks end module Query @@ -53,26 +52,6 @@ def restore(id_or_ids, opts = {}) end end - module Callbacks - def self.extended(klazz) - [:restore, :real_destroy].each do |callback_name| - klazz.define_callbacks callback_name - - klazz.define_singleton_method("before_#{callback_name}") do |*args, &block| - set_callback(callback_name, :before, *args, &block) - end - - klazz.define_singleton_method("around_#{callback_name}") do |*args, &block| - set_callback(callback_name, :around, *args, &block) - end - - klazz.define_singleton_method("after_#{callback_name}") do |*args, &block| - set_callback(callback_name, :after, *args, &block) - end - end - end - end - def destroy transaction do run_callbacks(:destroy) do @@ -241,6 +220,8 @@ def restore_associated_records(recovery_window_range = nil) ActiveSupport.on_load(:active_record) do class ActiveRecord::Base def self.acts_as_paranoid(options={}) + define_model_callbacks :restore, :real_destroy + alias_method :really_destroyed?, :destroyed? alias_method :really_delete, :delete alias_method :destroy_without_paranoia, :destroy From f6448c4a5c7d42c4cb223a8fc9c124c239e3d0c2 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Wed, 1 Nov 2017 16:06:53 -0700 Subject: [PATCH 2/4] Add paranoia_{delete,destroy} aliases This should help users be more explicit about what action they want to perform. My hope is that this will also make it easier to migrate off of paranoia. --- lib/paranoia.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/paranoia.rb b/lib/paranoia.rb index 374970be..9b0ff2c5 100644 --- a/lib/paranoia.rb +++ b/lib/paranoia.rb @@ -52,7 +52,7 @@ def restore(id_or_ids, opts = {}) end end - def destroy + def paranoia_destroy transaction do run_callbacks(:destroy) do @_disable_counter_cache = deleted? @@ -69,8 +69,9 @@ def destroy end end end + alias_method :destroy, :paranoia_destroy - def delete + def paranoia_delete raise ActiveRecord::ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly? if persisted? # if a transaction exists, add the record so that after_commit @@ -82,6 +83,7 @@ def delete end self end + alias_method :delete, :paranoia_delete def restore!(opts = {}) self.class.transaction do From 87f8a0c1c461b524f30803229509c46360b9deff Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Thu, 2 Nov 2017 14:37:05 -0700 Subject: [PATCH 3/4] Use paranoia_ aliases internally This makes paranoia's code itself more explicit. --- lib/paranoia.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/paranoia.rb b/lib/paranoia.rb index 9b0ff2c5..95a5d274 100644 --- a/lib/paranoia.rb +++ b/lib/paranoia.rb @@ -56,7 +56,7 @@ def paranoia_destroy transaction do run_callbacks(:destroy) do @_disable_counter_cache = deleted? - result = delete + result = paranoia_delete next result unless result && ActiveRecord::VERSION::STRING >= '4.2' each_counter_cached_associations do |association| foreign_key = association.reflection.foreign_key.to_sym @@ -93,7 +93,7 @@ def restore!(opts = {}) # This only happened on Rails versions earlier than 4.1. noop_if_frozen = ActiveRecord.version < Gem::Version.new("4.1") if within_recovery_window?(recovery_window_range) && ((noop_if_frozen && !@attributes.frozen?) || !noop_if_frozen) - @_disable_counter_cache = !deleted? + @_disable_counter_cache = !paranoia_destroyed? write_attribute paranoia_column, paranoia_sentinel_value update_columns(paranoia_restore_attributes) each_counter_cached_associations do |association| @@ -130,7 +130,7 @@ def paranoia_destroyed? def really_destroy! transaction do run_callbacks(:real_destroy) do - @_disable_counter_cache = deleted? + @_disable_counter_cache = paranoia_destroyed? dependent_reflections = self.class.reflections.select do |name, reflection| reflection.options[:dependent] == :destroy end @@ -300,7 +300,7 @@ class UniquenessValidator < ActiveModel::EachValidator class AssociationNotSoftDestroyedValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) # if association is soft destroyed, add an error - if value.present? && value.deleted? + if value.present? && value.paranoia_destroyed? record.errors[attribute] << 'has been soft-deleted' end end From 0f25822c283a00b36fd3bdccb9d29a4de7726afd Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Wed, 1 Nov 2017 19:10:11 -0700 Subject: [PATCH 4/4] Add paranoia_destroy! --- lib/paranoia.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/paranoia.rb b/lib/paranoia.rb index 95a5d274..58ecbcad 100644 --- a/lib/paranoia.rb +++ b/lib/paranoia.rb @@ -71,6 +71,11 @@ def paranoia_destroy end alias_method :destroy, :paranoia_destroy + def paranoia_destroy! + paranoia_destroy || + raise(ActiveRecord::RecordNotDestroyed.new("Failed to destroy the record", self)) + end + def paranoia_delete raise ActiveRecord::ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly? if persisted?