Skip to content

Commit

Permalink
Merge branch 'core' into feat-after_restore_commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieujobin authored Oct 2, 2024
2 parents 3be8277 + ba6dde7 commit 083c98a
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
rails: ["edge", "~> 7.2.0", "~> 7.1.0", "~> 7.0.0", "~> 6.1.0"]
rails: ["~> 7.2.0", "~> 7.1.0", "~> 7.0.0", "~> 6.1.0"]
ruby: ["3.3","3.2", "3.1", "3.0", "2.7"]
exclude:
- rails: "~> 7.2.0"
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,21 @@ end
# => NoMethodError: undefined method `with_deleted' for #<Class:0x0123456>
```

#### delete_all:

The gem supports `delete_all` method, however it is disabled by default, to enabled add this in your `environment` file

``` ruby
Paranoia.delete_all_enabled = true
```
alternatively, you can enable/disable it for specific models as follow:

``` ruby
class User < ActiveRecord::Base
acts_as_paranoid(delete_all_enabled: true)
end
```

## Acts As Paranoid Migration

You can replace the older `acts_as_paranoid` methods as follows:
Expand Down
56 changes: 37 additions & 19 deletions lib/paranoia.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,11 @@
end

module Paranoia
@@default_sentinel_value = nil

# Change default_sentinel_value in a rails initializer
def self.default_sentinel_value=(val)
@@default_sentinel_value = val
end

def self.default_sentinel_value
@@default_sentinel_value
class << self
# Change default values in a rails initializer
attr_accessor :default_sentinel_value,
:delete_all_enabled
end

def self.included(klazz)
Expand Down Expand Up @@ -58,6 +54,16 @@ def restore(id_or_ids, opts = {})
end
ids.map { |id| only_deleted.find(id).restore!(opts) }
end

def paranoia_destroy_attributes
{
paranoia_column => current_time_from_proper_timezone
}.merge(timestamp_attributes_with_current_time)
end

def timestamp_attributes_with_current_time
timestamp_attributes_for_update_in_model.each_with_object({}) { |attr,hash| hash[attr] = current_time_from_proper_timezone }
end
end

def paranoia_destroy
Expand Down Expand Up @@ -217,18 +223,10 @@ def each_counter_cached_associations
def paranoia_restore_attributes
{
paranoia_column => paranoia_sentinel_value
}.merge(timestamp_attributes_with_current_time)
}.merge(self.class.timestamp_attributes_with_current_time)
end

def paranoia_destroy_attributes
{
paranoia_column => current_time_from_proper_timezone
}.merge(timestamp_attributes_with_current_time)
end

def timestamp_attributes_with_current_time
timestamp_attributes_for_update_in_model.each_with_object({}) { |attr,hash| hash[attr] = current_time_from_proper_timezone }
end
delegate :paranoia_destroy_attributes, to: 'self.class'

def paranoia_find_has_one_target(association)
association_foreign_key = association.options[:through].present? ? association.klass.primary_key : association.foreign_key
Expand Down Expand Up @@ -296,6 +294,14 @@ def after_restore_commit(*args, &block)
end
end

module Paranoia::Relation
def paranoia_delete_all
update_all(klass.paranoia_destroy_attributes)
end

alias_method :delete_all, :paranoia_delete_all
end

ActiveSupport.on_load(:active_record) do
class ActiveRecord::Base
def self.acts_as_paranoid(options={})
Expand All @@ -310,9 +316,11 @@ def self.acts_as_paranoid(options={})
alias_method :really_destroyed?, :destroyed?
alias_method :really_delete, :delete
alias_method :destroy_without_paranoia, :destroy
class << self; delegate :really_delete_all, to: :all end

include Paranoia
class_attribute :paranoia_column, :paranoia_sentinel_value, :paranoia_after_restore_commit
class_attribute :paranoia_column, :paranoia_sentinel_value, :paranoia_after_restore_commit,
:delete_all_enabled

self.paranoia_column = (options[:column] || :deleted_at).to_s
self.paranoia_sentinel_value = options.fetch(:sentinel_value) { Paranoia.default_sentinel_value }
Expand All @@ -336,6 +344,16 @@ class << self; alias_method :without_deleted, :paranoia_scope end
if paranoia_after_restore_commit
ActiveRecord::Transactions.send(:include, ActiveRecord::Transactions::RestoreSupport)
end

self.delete_all_enabled = options[:delete_all_enabled] || Paranoia.delete_all_enabled

if self.delete_all_enabled
"#{self}::ActiveRecord_Relation".constantize.class_eval do
alias_method :really_delete_all, :delete_all

include Paranoia::Relation
end
end
end

# Please do not use this method in production.
Expand Down
70 changes: 68 additions & 2 deletions test/paranoia_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,71 @@ def test_has_one_with_scope_not_restored
assert_equal 1, ParanoidHasOneWithScope.count # gamma deleted
end

def test_delete_all_disabled_by_default
assert_nil ParanoidModel.delete_all_enabled

(0...3).each{ ParanoidModel.create }
assert_equal 3, ParanoidModel.count
ParanoidModel.delete_all
assert_equal 0, ParanoidModel.count
assert_equal 0, ParanoidModel.unscoped.count
end

def test_delete_all_called_on_class
assert Employee.delete_all_enabled

(0...3).each{ Employee.create }
assert_equal 3, Employee.count
Employee.delete_all
assert_equal 0, Employee.count
assert_equal 3, Employee.unscoped.count
end

def test_delete_all_called_on_relation
assert Employee.delete_all_enabled

(0...3).each{ Employee.create }
assert_equal 3, Employee.count
Employee.where(id: 1).delete_all
assert_equal 2, Employee.count
assert_equal 3, Employee.unscoped.count
end

def test_really_delete_all_called_on_class
assert Employee.delete_all_enabled

(0...3).each{ Employee.create }
assert_equal 3, Employee.count
Employee.really_delete_all
assert_equal 0, Employee.count
assert_equal 0, Employee.unscoped.count
end

def test_delete_all_called_on_relation
assert Employee.delete_all_enabled

(0...3).each{ Employee.create }
assert_equal 3, Employee.count
Employee.where(id: 1).really_delete_all
assert_equal 2, Employee.count
assert_equal 2, Employee.unscoped.count
end

def test_update_has_many_through_relation_delete_associations
employer = Employer.create
employee1 = Employee.create
employee2 = Employee.create
job = Job.create :employer => employer, :employee => employee1

assert_equal 1, employer.jobs.count
assert_equal 1, employer.jobs.with_deleted.count

employer.update(employee_ids: [employee2.id])

assert_equal 1, employer.jobs.count
assert_equal 2, employer.jobs.with_deleted.count
end

private
def get_featureful_model
FeaturefulModel.new(:name => "not empty")
Expand Down Expand Up @@ -1557,16 +1622,17 @@ class Employer < ActiveRecord::Base
acts_as_paranoid
validates_uniqueness_of :name
has_many :jobs
has_many :employees, :through => :jobs
has_many :employees, :through => :jobs, dependent: :destroy
end

class Employee < ActiveRecord::Base
acts_as_paranoid
acts_as_paranoid(delete_all_enabled: true)
has_many :jobs
has_many :employers, :through => :jobs
end

class Job < ActiveRecord::Base
acts_as_paranoid(delete_all_enabled: true)
acts_as_paranoid
belongs_to :employer
belongs_to :employee
Expand Down

0 comments on commit 083c98a

Please sign in to comment.