Skip to content

Commit 083c98a

Browse files
authored
Merge branch 'core' into feat-after_restore_commit
2 parents 3be8277 + ba6dde7 commit 083c98a

File tree

4 files changed

+121
-22
lines changed

4 files changed

+121
-22
lines changed

Diff for: .github/workflows/build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
fail-fast: false
1717
matrix:
18-
rails: ["edge", "~> 7.2.0", "~> 7.1.0", "~> 7.0.0", "~> 6.1.0"]
18+
rails: ["~> 7.2.0", "~> 7.1.0", "~> 7.0.0", "~> 6.1.0"]
1919
ruby: ["3.3","3.2", "3.1", "3.0", "2.7"]
2020
exclude:
2121
- rails: "~> 7.2.0"

Diff for: README.md

+15
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,21 @@ end
361361
# => NoMethodError: undefined method `with_deleted' for #<Class:0x0123456>
362362
```
363363

364+
#### delete_all:
365+
366+
The gem supports `delete_all` method, however it is disabled by default, to enabled add this in your `environment` file
367+
368+
``` ruby
369+
Paranoia.delete_all_enabled = true
370+
```
371+
alternatively, you can enable/disable it for specific models as follow:
372+
373+
``` ruby
374+
class User < ActiveRecord::Base
375+
acts_as_paranoid(delete_all_enabled: true)
376+
end
377+
```
378+
364379
## Acts As Paranoid Migration
365380

366381
You can replace the older `acts_as_paranoid` methods as follows:

Diff for: lib/paranoia.rb

+37-19
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@
66
end
77

88
module Paranoia
9-
@@default_sentinel_value = nil
109

11-
# Change default_sentinel_value in a rails initializer
12-
def self.default_sentinel_value=(val)
13-
@@default_sentinel_value = val
14-
end
15-
16-
def self.default_sentinel_value
17-
@@default_sentinel_value
10+
class << self
11+
# Change default values in a rails initializer
12+
attr_accessor :default_sentinel_value,
13+
:delete_all_enabled
1814
end
1915

2016
def self.included(klazz)
@@ -58,6 +54,16 @@ def restore(id_or_ids, opts = {})
5854
end
5955
ids.map { |id| only_deleted.find(id).restore!(opts) }
6056
end
57+
58+
def paranoia_destroy_attributes
59+
{
60+
paranoia_column => current_time_from_proper_timezone
61+
}.merge(timestamp_attributes_with_current_time)
62+
end
63+
64+
def timestamp_attributes_with_current_time
65+
timestamp_attributes_for_update_in_model.each_with_object({}) { |attr,hash| hash[attr] = current_time_from_proper_timezone }
66+
end
6167
end
6268

6369
def paranoia_destroy
@@ -217,18 +223,10 @@ def each_counter_cached_associations
217223
def paranoia_restore_attributes
218224
{
219225
paranoia_column => paranoia_sentinel_value
220-
}.merge(timestamp_attributes_with_current_time)
226+
}.merge(self.class.timestamp_attributes_with_current_time)
221227
end
222228

223-
def paranoia_destroy_attributes
224-
{
225-
paranoia_column => current_time_from_proper_timezone
226-
}.merge(timestamp_attributes_with_current_time)
227-
end
228-
229-
def timestamp_attributes_with_current_time
230-
timestamp_attributes_for_update_in_model.each_with_object({}) { |attr,hash| hash[attr] = current_time_from_proper_timezone }
231-
end
229+
delegate :paranoia_destroy_attributes, to: 'self.class'
232230

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

297+
module Paranoia::Relation
298+
def paranoia_delete_all
299+
update_all(klass.paranoia_destroy_attributes)
300+
end
301+
302+
alias_method :delete_all, :paranoia_delete_all
303+
end
304+
299305
ActiveSupport.on_load(:active_record) do
300306
class ActiveRecord::Base
301307
def self.acts_as_paranoid(options={})
@@ -310,9 +316,11 @@ def self.acts_as_paranoid(options={})
310316
alias_method :really_destroyed?, :destroyed?
311317
alias_method :really_delete, :delete
312318
alias_method :destroy_without_paranoia, :destroy
319+
class << self; delegate :really_delete_all, to: :all end
313320

314321
include Paranoia
315-
class_attribute :paranoia_column, :paranoia_sentinel_value, :paranoia_after_restore_commit
322+
class_attribute :paranoia_column, :paranoia_sentinel_value, :paranoia_after_restore_commit,
323+
:delete_all_enabled
316324

317325
self.paranoia_column = (options[:column] || :deleted_at).to_s
318326
self.paranoia_sentinel_value = options.fetch(:sentinel_value) { Paranoia.default_sentinel_value }
@@ -336,6 +344,16 @@ class << self; alias_method :without_deleted, :paranoia_scope end
336344
if paranoia_after_restore_commit
337345
ActiveRecord::Transactions.send(:include, ActiveRecord::Transactions::RestoreSupport)
338346
end
347+
348+
self.delete_all_enabled = options[:delete_all_enabled] || Paranoia.delete_all_enabled
349+
350+
if self.delete_all_enabled
351+
"#{self}::ActiveRecord_Relation".constantize.class_eval do
352+
alias_method :really_delete_all, :delete_all
353+
354+
include Paranoia::Relation
355+
end
356+
end
339357
end
340358

341359
# Please do not use this method in production.

Diff for: test/paranoia_test.rb

+68-2
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,71 @@ def test_has_one_with_scope_not_restored
13531353
assert_equal 1, ParanoidHasOneWithScope.count # gamma deleted
13541354
end
13551355

1356+
def test_delete_all_disabled_by_default
1357+
assert_nil ParanoidModel.delete_all_enabled
1358+
1359+
(0...3).each{ ParanoidModel.create }
1360+
assert_equal 3, ParanoidModel.count
1361+
ParanoidModel.delete_all
1362+
assert_equal 0, ParanoidModel.count
1363+
assert_equal 0, ParanoidModel.unscoped.count
1364+
end
1365+
1366+
def test_delete_all_called_on_class
1367+
assert Employee.delete_all_enabled
1368+
1369+
(0...3).each{ Employee.create }
1370+
assert_equal 3, Employee.count
1371+
Employee.delete_all
1372+
assert_equal 0, Employee.count
1373+
assert_equal 3, Employee.unscoped.count
1374+
end
1375+
1376+
def test_delete_all_called_on_relation
1377+
assert Employee.delete_all_enabled
1378+
1379+
(0...3).each{ Employee.create }
1380+
assert_equal 3, Employee.count
1381+
Employee.where(id: 1).delete_all
1382+
assert_equal 2, Employee.count
1383+
assert_equal 3, Employee.unscoped.count
1384+
end
1385+
1386+
def test_really_delete_all_called_on_class
1387+
assert Employee.delete_all_enabled
1388+
1389+
(0...3).each{ Employee.create }
1390+
assert_equal 3, Employee.count
1391+
Employee.really_delete_all
1392+
assert_equal 0, Employee.count
1393+
assert_equal 0, Employee.unscoped.count
1394+
end
1395+
1396+
def test_delete_all_called_on_relation
1397+
assert Employee.delete_all_enabled
1398+
1399+
(0...3).each{ Employee.create }
1400+
assert_equal 3, Employee.count
1401+
Employee.where(id: 1).really_delete_all
1402+
assert_equal 2, Employee.count
1403+
assert_equal 2, Employee.unscoped.count
1404+
end
1405+
1406+
def test_update_has_many_through_relation_delete_associations
1407+
employer = Employer.create
1408+
employee1 = Employee.create
1409+
employee2 = Employee.create
1410+
job = Job.create :employer => employer, :employee => employee1
1411+
1412+
assert_equal 1, employer.jobs.count
1413+
assert_equal 1, employer.jobs.with_deleted.count
1414+
1415+
employer.update(employee_ids: [employee2.id])
1416+
1417+
assert_equal 1, employer.jobs.count
1418+
assert_equal 2, employer.jobs.with_deleted.count
1419+
end
1420+
13561421
private
13571422
def get_featureful_model
13581423
FeaturefulModel.new(:name => "not empty")
@@ -1557,16 +1622,17 @@ class Employer < ActiveRecord::Base
15571622
acts_as_paranoid
15581623
validates_uniqueness_of :name
15591624
has_many :jobs
1560-
has_many :employees, :through => :jobs
1625+
has_many :employees, :through => :jobs, dependent: :destroy
15611626
end
15621627

15631628
class Employee < ActiveRecord::Base
1564-
acts_as_paranoid
1629+
acts_as_paranoid(delete_all_enabled: true)
15651630
has_many :jobs
15661631
has_many :employers, :through => :jobs
15671632
end
15681633

15691634
class Job < ActiveRecord::Base
1635+
acts_as_paranoid(delete_all_enabled: true)
15701636
acts_as_paranoid
15711637
belongs_to :employer
15721638
belongs_to :employee

0 commit comments

Comments
 (0)