acts_as_paranoid 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsParanoid
2
4
  module Relation
3
5
  def self.included(base)
@@ -1,4 +1,6 @@
1
- require 'active_support/core_ext/array/wrap'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array/wrap"
2
4
 
3
5
  module ActsAsParanoid
4
6
  module Validations
@@ -6,76 +8,17 @@ module ActsAsParanoid
6
8
  base.extend ClassMethods
7
9
  end
8
10
 
9
- class UniquenessWithoutDeletedValidator
10
- def self.[](version)
11
- version = version.to_s
12
- name = "V#{version.tr('.', '_')}"
13
- unless constants.include? name.to_sym
14
- raise "Unknown validator version #{version.inspect}; expected one of #{constants.sort.join(', ')}"
15
- end
16
- const_get name
17
- end
18
-
19
- class V5 < ActiveRecord::Validations::UniquenessValidator
20
- def validate_each(record, attribute, value)
21
- finder_class = find_finder_class_for(record)
22
- table = finder_class.arel_table
23
-
24
- coder = record.class.attribute_types[attribute.to_s]
25
- value = coder.type_cast_for_schema value if value && coder
26
-
27
- relation = build_relation(finder_class, table, attribute, value)
28
- [Array(finder_class.primary_key), Array(record.send(:id))].transpose.each do |pk_key, pk_value|
29
- relation = relation.where(table[pk_key.to_sym].not_eq(pk_value))
30
- end if record.persisted?
31
-
32
- Array.wrap(options[:scope]).each do |scope_item|
33
- relation = relation.where(table[scope_item].eq(record.public_send(scope_item)))
34
- end
35
-
36
- if relation.where(finder_class.paranoid_default_scope).where(relation).exists?
37
- record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
38
- end
39
- end
40
- end
41
-
42
- class V4 < ActiveRecord::Validations::UniquenessValidator
43
- def validate_each(record, attribute, value)
44
- finder_class = find_finder_class_for(record)
45
- table = finder_class.arel_table
46
-
47
- # TODO: Use record.class.column_types[attribute.to_s].coder ?
48
- coder = record.class.column_types[attribute.to_s]
49
-
50
- if value && coder
51
- value = if coder.respond_to? :type_cast_for_database
52
- coder.type_cast_for_database value
53
- else
54
- coder.type_cast_for_write value
55
- end
56
- end
57
-
58
- relation = build_relation(finder_class, table, attribute, value)
59
- [Array(finder_class.primary_key), Array(record.send(:id))].transpose.each do |pk_key, pk_value|
60
- relation = relation.and(table[pk_key.to_sym].not_eq(pk_value))
61
- end if record.persisted?
62
-
63
- Array.wrap(options[:scope]).each do |scope_item|
64
- scope_value = record.send(scope_item)
65
- relation = relation.and(table[scope_item].eq(scope_value))
66
- end
11
+ class UniquenessWithoutDeletedValidator < ActiveRecord::Validations::UniquenessValidator
12
+ private
67
13
 
68
- # Re-add ActsAsParanoid default scope conditions manually.
69
- if finder_class.unscoped.where(finder_class.paranoid_default_scope).where(relation).exists?
70
- record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
71
- end
72
- end
14
+ def build_relation(klass, attribute, value)
15
+ super.where(klass.paranoid_default_scope)
73
16
  end
74
17
  end
75
18
 
76
19
  module ClassMethods
77
20
  def validates_uniqueness_of_without_deleted(*attr_names)
78
- validates_with UniquenessWithoutDeletedValidator[ActiveRecord::VERSION::MAJOR], _merge_attributes(attr_names)
21
+ validates_with UniquenessWithoutDeletedValidator, _merge_attributes(attr_names)
79
22
  end
80
23
  end
81
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActsAsParanoid
2
- VERSION = "0.5.0"
4
+ VERSION = "0.7.0"
3
5
  end
@@ -1,27 +1,34 @@
1
- require 'test_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
2
4
 
3
5
  class AssociationsTest < ParanoidBaseTest
4
- def test_removal_with_associations
5
- paranoid_company_1 = ParanoidDestroyCompany.create! :name => "ParanoidDestroyCompany #1"
6
- paranoid_company_2 = ParanoidDeleteCompany.create! :name => "ParanoidDestroyCompany #1"
7
- paranoid_company_1.paranoid_products.create! :name => "ParanoidProduct #1"
8
- paranoid_company_2.paranoid_products.create! :name => "ParanoidProduct #2"
6
+ def test_removal_with_destroy_associations
7
+ paranoid_company = ParanoidDestroyCompany.create! name: "ParanoidDestroyCompany #1"
8
+ paranoid_company.paranoid_products.create! name: "ParanoidProduct #1"
9
9
 
10
10
  assert_equal 1, ParanoidDestroyCompany.count
11
- assert_equal 1, ParanoidDeleteCompany.count
12
- assert_equal 2, ParanoidProduct.count
11
+ assert_equal 1, ParanoidProduct.count
13
12
 
14
13
  ParanoidDestroyCompany.first.destroy
15
14
  assert_equal 0, ParanoidDestroyCompany.count
16
- assert_equal 1, ParanoidProduct.count
15
+ assert_equal 0, ParanoidProduct.count
17
16
  assert_equal 1, ParanoidDestroyCompany.with_deleted.count
18
- assert_equal 2, ParanoidProduct.with_deleted.count
17
+ assert_equal 1, ParanoidProduct.with_deleted.count
19
18
 
20
19
  ParanoidDestroyCompany.with_deleted.first.destroy
21
20
  assert_equal 0, ParanoidDestroyCompany.count
22
- assert_equal 1, ParanoidProduct.count
21
+ assert_equal 0, ParanoidProduct.count
23
22
  assert_equal 0, ParanoidDestroyCompany.with_deleted.count
24
- assert_equal 1, ParanoidProduct.with_deleted.count
23
+ assert_equal 0, ParanoidProduct.with_deleted.count
24
+ end
25
+
26
+ def test_removal_with_delete_all_associations
27
+ paranoid_company = ParanoidDeleteCompany.create! name: "ParanoidDestroyCompany #1"
28
+ paranoid_company.paranoid_products.create! name: "ParanoidProduct #2"
29
+
30
+ assert_equal 1, ParanoidDeleteCompany.count
31
+ assert_equal 1, ParanoidProduct.count
25
32
 
26
33
  ParanoidDeleteCompany.first.destroy
27
34
  assert_equal 0, ParanoidDeleteCompany.count
@@ -38,64 +45,122 @@ class AssociationsTest < ParanoidBaseTest
38
45
 
39
46
  def test_belongs_to_with_scope_option
40
47
  paranoid_has_many_dependant = ParanoidHasManyDependant.new
48
+
49
+ expected_includes_values = ParanoidTime.includes(:not_paranoid).includes_values
50
+ includes_values = paranoid_has_many_dependant
51
+ .association(:paranoid_time_with_scope).scope.includes_values
52
+
53
+ assert_equal expected_includes_values, includes_values
54
+
55
+ paranoid_time = ParanoidTime.create(name: "not-hello")
56
+ paranoid_has_many_dependant.paranoid_time = paranoid_time
57
+ paranoid_has_many_dependant.save!
58
+
59
+ assert_nil paranoid_has_many_dependant.paranoid_time_with_scope
60
+
61
+ paranoid_time.update(name: "hello")
62
+
63
+ paranoid_has_many_dependant.reload
64
+
65
+ assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_scope
66
+
67
+ paranoid_time.destroy
68
+
69
+ paranoid_has_many_dependant.reload
70
+
71
+ assert_nil paranoid_has_many_dependant.paranoid_time_with_scope
72
+ end
73
+
74
+ def test_belongs_to_with_scope_and_deleted_option
75
+ paranoid_has_many_dependant = ParanoidHasManyDependant.new
41
76
  includes_values = ParanoidTime.includes(:not_paranoid).includes_values
42
77
 
43
- assert_equal includes_values, paranoid_has_many_dependant.association(:paranoid_time_with_scope).scope.includes_values
78
+ assert_equal includes_values, paranoid_has_many_dependant
79
+ .association(:paranoid_time_with_scope_with_deleted).scope.includes_values
80
+
81
+ paranoid_time = ParanoidTime.create(name: "not-hello")
82
+ paranoid_has_many_dependant.paranoid_time = paranoid_time
83
+ paranoid_has_many_dependant.save!
84
+
85
+ assert_nil paranoid_has_many_dependant.paranoid_time_with_scope_with_deleted
86
+
87
+ paranoid_time.update(name: "hello")
88
+ paranoid_has_many_dependant.reload
89
+
90
+ assert_equal paranoid_time, paranoid_has_many_dependant
91
+ .paranoid_time_with_scope_with_deleted
92
+
93
+ paranoid_time.destroy
94
+ paranoid_has_many_dependant.reload
95
+
96
+ assert_equal paranoid_time, paranoid_has_many_dependant
97
+ .paranoid_time_with_scope_with_deleted
44
98
  end
45
99
 
46
100
  def test_belongs_to_with_deleted
47
101
  paranoid_time = ParanoidTime.first
48
- paranoid_has_many_dependant = paranoid_time.paranoid_has_many_dependants.create(:name => 'dependant!')
102
+ paranoid_has_many_dependant = paranoid_time.paranoid_has_many_dependants
103
+ .create(name: "dependant!")
49
104
 
50
105
  assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time
51
106
  assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted
52
107
 
53
108
  paranoid_time.destroy
109
+ paranoid_has_many_dependant.reload
54
110
 
55
- assert_nil paranoid_has_many_dependant.paranoid_time(true)
56
- assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted(true)
111
+ assert_nil paranoid_has_many_dependant.paranoid_time
112
+ assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted
57
113
  end
58
114
 
59
115
  def test_belongs_to_polymorphic_with_deleted
60
116
  paranoid_time = ParanoidTime.first
61
- paranoid_has_many_dependant = ParanoidHasManyDependant.create!(:name => 'dependant!', :paranoid_time_polymorphic_with_deleted => paranoid_time)
117
+ paranoid_has_many_dependant = ParanoidHasManyDependant
118
+ .create!(name: "dependant!", paranoid_time_polymorphic_with_deleted: paranoid_time)
62
119
 
63
120
  assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time
64
- assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted
121
+ assert_equal paranoid_time, paranoid_has_many_dependant
122
+ .paranoid_time_polymorphic_with_deleted
65
123
 
66
124
  paranoid_time.destroy
67
125
 
68
- assert_nil paranoid_has_many_dependant.paranoid_time(true)
69
- assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted(true)
126
+ assert_nil paranoid_has_many_dependant.reload.paranoid_time
127
+ assert_equal paranoid_time, paranoid_has_many_dependant
128
+ .reload.paranoid_time_polymorphic_with_deleted
70
129
  end
71
130
 
72
131
  def test_belongs_to_nil_polymorphic_with_deleted
73
132
  paranoid_time = ParanoidTime.first
74
- paranoid_has_many_dependant = ParanoidHasManyDependant.create!(:name => 'dependant!', :paranoid_time_polymorphic_with_deleted => nil)
133
+ paranoid_has_many_dependant =
134
+ ParanoidHasManyDependant.create!(name: "dependant!",
135
+ paranoid_time_polymorphic_with_deleted: nil)
75
136
 
76
137
  assert_nil paranoid_has_many_dependant.paranoid_time
77
138
  assert_nil paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted
78
139
 
79
140
  paranoid_time.destroy
80
141
 
81
- assert_nil paranoid_has_many_dependant.paranoid_time(true)
82
- assert_nil paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted(true)
142
+ assert_nil paranoid_has_many_dependant.reload.paranoid_time
143
+ assert_nil paranoid_has_many_dependant.reload.paranoid_time_polymorphic_with_deleted
83
144
  end
84
145
 
85
146
  def test_belongs_to_options
86
- paranoid_time = ParanoidHasManyDependant.reflections.with_indifferent_access[:paranoid_time]
147
+ paranoid_time = ParanoidHasManyDependant.reflections
148
+ .with_indifferent_access[:paranoid_time]
87
149
  assert_equal :belongs_to, paranoid_time.macro
88
150
  assert_nil paranoid_time.options[:with_deleted]
89
151
  end
90
152
 
91
153
  def test_belongs_to_with_deleted_options
92
- paranoid_time_with_deleted = ParanoidHasManyDependant.reflections.with_indifferent_access[:paranoid_time_with_deleted]
154
+ paranoid_time_with_deleted =
155
+ ParanoidHasManyDependant.reflections
156
+ .with_indifferent_access[:paranoid_time_with_deleted]
93
157
  assert_equal :belongs_to, paranoid_time_with_deleted.macro
94
158
  assert paranoid_time_with_deleted.options[:with_deleted]
95
159
  end
96
160
 
97
161
  def test_belongs_to_polymorphic_with_deleted_options
98
- paranoid_time_polymorphic_with_deleted = ParanoidHasManyDependant.reflections.with_indifferent_access[:paranoid_time_polymorphic_with_deleted]
162
+ paranoid_time_polymorphic_with_deleted = ParanoidHasManyDependant.reflections
163
+ .with_indifferent_access[:paranoid_time_polymorphic_with_deleted]
99
164
  assert_equal :belongs_to, paranoid_time_polymorphic_with_deleted.macro
100
165
  assert paranoid_time_polymorphic_with_deleted.options[:with_deleted]
101
166
  end
@@ -118,6 +183,50 @@ class AssociationsTest < ParanoidBaseTest
118
183
  assert_equal [child], parent.paranoid_has_many_dependants.with_deleted.to_a
119
184
  end
120
185
 
186
+ def test_join_with_model_with_deleted
187
+ obj = ParanoidHasManyDependant.create(paranoid_time: ParanoidTime.create)
188
+ assert_not_nil obj.paranoid_time
189
+ assert_not_nil obj.paranoid_time_with_deleted
190
+
191
+ obj.paranoid_time.destroy
192
+ obj.reload
193
+
194
+ assert_nil obj.paranoid_time
195
+ assert_not_nil obj.paranoid_time_with_deleted
196
+
197
+ # Note that obj is destroyed because of dependent: :destroy in ParanoidTime
198
+ assert obj.destroyed?
199
+
200
+ assert_empty ParanoidHasManyDependant.with_deleted.joins(:paranoid_time)
201
+ assert_equal [obj],
202
+ ParanoidHasManyDependant.with_deleted.joins(:paranoid_time_with_deleted)
203
+ end
204
+
205
+ def test_includes_with_deleted
206
+ paranoid_time = ParanoidTime.first
207
+ paranoid_time.paranoid_has_many_dependants.create(name: "dependant!")
208
+
209
+ paranoid_time.destroy
210
+
211
+ ParanoidHasManyDependant.with_deleted
212
+ .includes(:paranoid_time_with_deleted).each do |hasmany|
213
+ assert_not_nil hasmany.paranoid_time_with_deleted
214
+ end
215
+ end
216
+
217
+ def test_includes_with_deleted_with_polymorphic_parent
218
+ not_paranoid_parent = NotParanoidHasManyAsParent.create(name: "not paranoid parent")
219
+ paranoid_parent = ParanoidHasManyAsParent.create(name: "paranoid parent")
220
+ ParanoidBelongsToPolymorphic.create(name: "belongs_to", parent: not_paranoid_parent)
221
+ ParanoidBelongsToPolymorphic.create(name: "belongs_to", parent: paranoid_parent)
222
+
223
+ paranoid_parent.destroy
224
+
225
+ ParanoidBelongsToPolymorphic.with_deleted.includes(:parent).each do |hasmany|
226
+ assert_not_nil hasmany.parent
227
+ end
228
+ end
229
+
121
230
  def test_cannot_find_a_paranoid_deleted_many_many_association
122
231
  left = ParanoidManyManyParentLeft.create
123
232
  right = ParanoidManyManyParentRight.create
@@ -128,8 +237,10 @@ class AssociationsTest < ParanoidBaseTest
128
237
  left.reload
129
238
 
130
239
  assert_equal [], left.paranoid_many_many_children, "Linking objects not deleted"
131
- assert_equal [], left.paranoid_many_many_parent_rights, "Associated objects not unlinked"
132
- assert_equal right, ParanoidManyManyParentRight.find(right.id), "Associated object deleted"
240
+ assert_equal [], left.paranoid_many_many_parent_rights,
241
+ "Associated objects not unlinked"
242
+ assert_equal right, ParanoidManyManyParentRight.find(right.id),
243
+ "Associated object deleted"
133
244
  end
134
245
 
135
246
  def test_cannot_find_a_paranoid_destroyed_many_many_association
@@ -142,11 +253,13 @@ class AssociationsTest < ParanoidBaseTest
142
253
  left.reload
143
254
 
144
255
  assert_equal [], left.paranoid_many_many_children, "Linking objects not deleted"
145
- assert_equal [], left.paranoid_many_many_parent_rights, "Associated objects not unlinked"
146
- assert_equal right, ParanoidManyManyParentRight.find(right.id), "Associated object deleted"
256
+ assert_equal [], left.paranoid_many_many_parent_rights,
257
+ "Associated objects not unlinked"
258
+ assert_equal right, ParanoidManyManyParentRight.find(right.id),
259
+ "Associated object deleted"
147
260
  end
148
261
 
149
- def test_cannot_find_a_has_many_through_object_when_its_linking_object_is_paranoid_destroyed
262
+ def test_cannot_find_a_has_many_through_object_when_its_linking_object_is_soft_destroyed
150
263
  left = ParanoidManyManyParentLeft.create
151
264
  right = ParanoidManyManyParentRight.create
152
265
  left.paranoid_many_many_parent_rights << right
@@ -175,8 +288,10 @@ class AssociationsTest < ParanoidBaseTest
175
288
  left.paranoid_many_many_parent_rights << right
176
289
 
177
290
  child = left.paranoid_many_many_children.first
178
- assert_equal left, child.paranoid_many_many_parent_left, "Child's left parent is incorrect"
179
- assert_equal right, child.paranoid_many_many_parent_right, "Child's right parent is incorrect"
291
+ assert_equal left, child.paranoid_many_many_parent_left,
292
+ "Child's left parent is incorrect"
293
+ assert_equal right, child.paranoid_many_many_parent_right,
294
+ "Child's right parent is incorrect"
180
295
 
181
296
  left.paranoid_many_many_parent_rights.clear
182
297
 
@@ -189,8 +304,10 @@ class AssociationsTest < ParanoidBaseTest
189
304
  left.paranoid_many_many_parent_rights << right
190
305
 
191
306
  child = left.paranoid_many_many_children.first
192
- assert_equal left, child.paranoid_many_many_parent_left, "Child's left parent is incorrect"
193
- assert_equal right, child.paranoid_many_many_parent_right, "Child's right parent is incorrect"
307
+ assert_equal left, child.paranoid_many_many_parent_left,
308
+ "Child's left parent is incorrect"
309
+ assert_equal right, child.paranoid_many_many_parent_right,
310
+ "Child's right parent is incorrect"
194
311
 
195
312
  left.paranoid_many_many_parent_rights.destroy(right)
196
313
 
@@ -203,8 +320,10 @@ class AssociationsTest < ParanoidBaseTest
203
320
  left.paranoid_many_many_parent_rights << right
204
321
 
205
322
  child = left.paranoid_many_many_children.first
206
- assert_equal left, child.paranoid_many_many_parent_left, "Child's left parent is incorrect"
207
- assert_equal right, child.paranoid_many_many_parent_right, "Child's right parent is incorrect"
323
+ assert_equal left, child.paranoid_many_many_parent_left,
324
+ "Child's left parent is incorrect"
325
+ assert_equal right, child.paranoid_many_many_parent_right,
326
+ "Child's right parent is incorrect"
208
327
 
209
328
  left.paranoid_many_many_parent_rights.delete(right)
210
329
 
@@ -228,9 +347,12 @@ class AssociationsTest < ParanoidBaseTest
228
347
  end
229
348
 
230
349
  def test_mass_assignment_of_paranoid_column_enabled
350
+ if Gem.loaded_specs["activerecord"].version >= Gem::Version.new("5.2.0")
351
+ skip "Creation as deleted is not supported with Rails >= 5.2"
352
+ end
231
353
  now = Time.now
232
- record = ParanoidTime.create! :name => 'Foo', :deleted_at => now
233
- assert_equal 'Foo', record.name
354
+ record = ParanoidTime.create! name: "Foo", deleted_at: now
355
+ assert_equal "Foo", record.name
234
356
  assert_equal now, record.deleted_at
235
357
  end
236
358
  end
@@ -1,4 +1,6 @@
1
- require 'test_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
2
4
 
3
5
  class ParanoidTest < ParanoidBaseTest
4
6
  def test_paranoid?
@@ -69,6 +71,13 @@ class ParanoidTest < ParanoidBaseTest
69
71
  assert_not_nil pt.paranoid_value
70
72
  end
71
73
 
74
+ def test_non_persisted_delete
75
+ pt = ParanoidTime.new
76
+ assert_nil pt.paranoid_value
77
+ pt.delete
78
+ assert_not_nil pt.paranoid_value
79
+ end
80
+
72
81
  def test_non_persisted_destroy!
73
82
  pt = ParanoidTime.new
74
83
  assert_nil pt.paranoid_value
@@ -94,12 +103,34 @@ class ParanoidTest < ParanoidBaseTest
94
103
  assert_equal 1, ParanoidString.count
95
104
  end
96
105
 
106
+ def test_recovery!
107
+ ParanoidBoolean.first.destroy
108
+ ParanoidBoolean.create(name: "paranoid")
109
+
110
+ assert_raise do
111
+ ParanoidBoolean.only_deleted.first.recover!
112
+ end
113
+ end
114
+
115
+ # Rails does not allow saving deleted records
116
+ def test_no_save_after_destroy
117
+ paranoid = ParanoidString.first
118
+ paranoid.destroy
119
+ paranoid.name = "Let's update!"
120
+
121
+ assert_not paranoid.save
122
+ assert_raises ActiveRecord::RecordNotSaved do
123
+ paranoid.save!
124
+ end
125
+ end
126
+
97
127
  def setup_recursive_tests
98
128
  @paranoid_time_object = ParanoidTime.first
99
129
 
100
130
  # Create one extra ParanoidHasManyDependant record so that we can validate
101
131
  # the correct dependants are recovered.
102
- ParanoidTime.where('id <> ?', @paranoid_time_object.id).first.paranoid_has_many_dependants.create(:name => "should not be recovered").destroy
132
+ ParanoidTime.where("id <> ?", @paranoid_time_object.id).first
133
+ .paranoid_has_many_dependants.create(name: "should not be recovered").destroy
103
134
 
104
135
  @paranoid_boolean_count = ParanoidBoolean.count
105
136
 
@@ -108,20 +139,21 @@ class ParanoidTest < ParanoidBaseTest
108
139
  assert_equal 1, NotParanoid.count
109
140
 
110
141
  (1..3).each do |i|
111
- has_many_object = @paranoid_time_object.paranoid_has_many_dependants.create(:name => "has_many_#{i}")
112
- has_many_object.create_paranoid_belongs_dependant(:name => "belongs_to_#{i}")
142
+ has_many_object = @paranoid_time_object.paranoid_has_many_dependants
143
+ .create(name: "has_many_#{i}")
144
+ has_many_object.create_paranoid_belongs_dependant(name: "belongs_to_#{i}")
113
145
  has_many_object.save
114
146
 
115
- paranoid_boolean = @paranoid_time_object.paranoid_booleans.create(:name => "boolean_#{i}")
116
- paranoid_boolean.create_paranoid_has_one_dependant(:name => "has_one_#{i}")
147
+ paranoid_boolean = @paranoid_time_object.paranoid_booleans
148
+ .create(name: "boolean_#{i}")
149
+ paranoid_boolean.create_paranoid_has_one_dependant(name: "has_one_#{i}")
117
150
  paranoid_boolean.save
118
151
 
119
- @paranoid_time_object.not_paranoids.create(:name => "not_paranoid_a#{i}")
120
-
152
+ @paranoid_time_object.not_paranoids.create(name: "not_paranoid_a#{i}")
121
153
  end
122
154
 
123
- @paranoid_time_object.create_not_paranoid(:name => "not_paranoid_belongs_to")
124
- @paranoid_time_object.create_has_one_not_paranoid(:name => "has_one_not_paranoid")
155
+ @paranoid_time_object.create_not_paranoid(name: "not_paranoid_belongs_to")
156
+ @paranoid_time_object.create_has_one_not_paranoid(name: "has_one_not_paranoid")
125
157
 
126
158
  assert_equal 3, ParanoidTime.count
127
159
  assert_equal 3, ParanoidHasManyDependant.count
@@ -172,7 +204,7 @@ class ParanoidTest < ParanoidBaseTest
172
204
  @paranoid_time_object.destroy
173
205
  @paranoid_time_object.reload
174
206
 
175
- @paranoid_time_object.recover(:recursive => true)
207
+ @paranoid_time_object.recover(recursive: true)
176
208
 
177
209
  assert_equal 3, ParanoidTime.count
178
210
  assert_equal 3, ParanoidHasManyDependant.count
@@ -186,17 +218,21 @@ class ParanoidTest < ParanoidBaseTest
186
218
  def test_recursive_recovery_dependant_window
187
219
  setup_recursive_tests
188
220
 
189
- @paranoid_time_object.destroy
190
- @paranoid_time_object.reload
191
-
192
221
  # Stop the following from recovering:
193
222
  # - ParanoidHasManyDependant and its ParanoidBelongsDependant
194
223
  # - A single ParanoidBelongsDependant, but not its parent
195
- dependants = @paranoid_time_object.paranoid_has_many_dependants.with_deleted
196
- dependants.first.update_attribute(:deleted_at, 2.days.ago)
197
- ParanoidBelongsDependant.with_deleted.where(:id => dependants.last.paranoid_belongs_dependant_id).first.update_attribute(:deleted_at, 1.hour.ago)
224
+ Time.stub :now, 2.days.ago do
225
+ @paranoid_time_object.paranoid_has_many_dependants.first.destroy
226
+ end
227
+ Time.stub :now, 1.hour.ago do
228
+ @paranoid_time_object.paranoid_has_many_dependants
229
+ .last.paranoid_belongs_dependant
230
+ .destroy
231
+ end
232
+ @paranoid_time_object.destroy
233
+ @paranoid_time_object.reload
198
234
 
199
- @paranoid_time_object.recover(:recursive => true)
235
+ @paranoid_time_object.recover(recursive: true)
200
236
 
201
237
  assert_equal 3, ParanoidTime.count
202
238
  assert_equal 2, ParanoidHasManyDependant.count
@@ -209,31 +245,31 @@ class ParanoidTest < ParanoidBaseTest
209
245
 
210
246
  def test_recursive_recovery_for_belongs_to_polymorphic
211
247
  child_1 = ParanoidAndroid.create
212
- section_1 = ParanoidSection.create(:paranoid_thing => child_1)
248
+ section_1 = ParanoidSection.create(paranoid_thing: child_1)
213
249
 
214
- child_2 = ParanoidHuman.create(:gender => 'male')
215
- section_2 = ParanoidSection.create(:paranoid_thing => child_2)
250
+ child_2 = ParanoidPolygon.create(sides: 3)
251
+ section_2 = ParanoidSection.create(paranoid_thing: child_2)
216
252
 
217
253
  assert_equal section_1.paranoid_thing, child_1
218
254
  assert_equal section_1.paranoid_thing.class, ParanoidAndroid
219
255
  assert_equal section_2.paranoid_thing, child_2
220
- assert_equal section_2.paranoid_thing.class, ParanoidHuman
256
+ assert_equal section_2.paranoid_thing.class, ParanoidPolygon
221
257
 
222
- parent = ParanoidTime.create(:name => "paranoid_parent")
258
+ parent = ParanoidTime.create(name: "paranoid_parent")
223
259
  parent.paranoid_sections << section_1
224
260
  parent.paranoid_sections << section_2
225
261
 
226
262
  assert_equal 4, ParanoidTime.count
227
263
  assert_equal 2, ParanoidSection.count
228
264
  assert_equal 1, ParanoidAndroid.count
229
- assert_equal 1, ParanoidHuman.count
265
+ assert_equal 1, ParanoidPolygon.count
230
266
 
231
267
  parent.destroy
232
268
 
233
269
  assert_equal 3, ParanoidTime.count
234
270
  assert_equal 0, ParanoidSection.count
235
271
  assert_equal 0, ParanoidAndroid.count
236
- assert_equal 0, ParanoidHuman.count
272
+ assert_equal 0, ParanoidPolygon.count
237
273
 
238
274
  parent.reload
239
275
  parent.recover
@@ -241,7 +277,7 @@ class ParanoidTest < ParanoidBaseTest
241
277
  assert_equal 4, ParanoidTime.count
242
278
  assert_equal 2, ParanoidSection.count
243
279
  assert_equal 1, ParanoidAndroid.count
244
- assert_equal 1, ParanoidHuman.count
280
+ assert_equal 1, ParanoidPolygon.count
245
281
  end
246
282
 
247
283
  def test_non_recursive_recovery
@@ -250,7 +286,7 @@ class ParanoidTest < ParanoidBaseTest
250
286
  @paranoid_time_object.destroy
251
287
  @paranoid_time_object.reload
252
288
 
253
- @paranoid_time_object.recover(:recursive => false)
289
+ @paranoid_time_object.recover(recursive: false)
254
290
 
255
291
  assert_equal 3, ParanoidTime.count
256
292
  assert_equal 0, ParanoidHasManyDependant.count
@@ -261,6 +297,24 @@ class ParanoidTest < ParanoidBaseTest
261
297
  assert_equal 0, HasOneNotParanoid.count
262
298
  end
263
299
 
300
+ def test_dirty
301
+ pt = ParanoidTime.create
302
+ pt.destroy
303
+ assert_not pt.changed?
304
+ end
305
+
306
+ def test_delete_dirty
307
+ pt = ParanoidTime.create
308
+ pt.delete
309
+ assert_not pt.changed?
310
+ end
311
+
312
+ def test_destroy_fully_dirty
313
+ pt = ParanoidTime.create
314
+ pt.destroy_fully!
315
+ assert_not pt.changed?
316
+ end
317
+
264
318
  def test_deleted?
265
319
  ParanoidTime.first.destroy
266
320
  assert ParanoidTime.with_deleted.first.deleted?
@@ -269,6 +323,43 @@ class ParanoidTest < ParanoidBaseTest
269
323
  assert ParanoidString.with_deleted.first.deleted?
270
324
  end
271
325
 
326
+ def test_delete_deleted?
327
+ ParanoidTime.first.delete
328
+ assert ParanoidTime.with_deleted.first.deleted?
329
+
330
+ ParanoidString.first.delete
331
+ assert ParanoidString.with_deleted.first.deleted?
332
+ end
333
+
334
+ def test_destroy_fully_deleted?
335
+ object = ParanoidTime.first
336
+ object.destroy_fully!
337
+ assert object.deleted?
338
+
339
+ object = ParanoidString.first
340
+ object.destroy_fully!
341
+ assert object.deleted?
342
+ end
343
+
344
+ def test_deleted_fully?
345
+ ParanoidTime.first.destroy
346
+ assert_not ParanoidTime.with_deleted.first.deleted_fully?
347
+
348
+ ParanoidString.first.destroy
349
+ assert ParanoidString.with_deleted.first.deleted?
350
+ end
351
+
352
+ def test_delete_deleted_fully?
353
+ ParanoidTime.first.delete
354
+ assert_not ParanoidTime.with_deleted.first.deleted_fully?
355
+ end
356
+
357
+ def test_destroy_fully_deleted_fully?
358
+ object = ParanoidTime.first
359
+ object.destroy_fully!
360
+ assert object.deleted_fully?
361
+ end
362
+
272
363
  def test_paranoid_destroy_callbacks
273
364
  @paranoid_with_callback = ParanoidWithCallback.first
274
365
  ParanoidWithCallback.transaction do
@@ -308,6 +399,14 @@ class ParanoidTest < ParanoidBaseTest
308
399
  assert @paranoid_with_callback.called_after_recover
309
400
  end
310
401
 
402
+ def test_recovery_callbacks_without_destroy
403
+ @paranoid_with_callback = ParanoidWithCallback.first
404
+ @paranoid_with_callback.recover
405
+
406
+ assert_nil @paranoid_with_callback.called_before_recover
407
+ assert_nil @paranoid_with_callback.called_after_recover
408
+ end
409
+
311
410
  def test_delete_by_multiple_id_is_paranoid
312
411
  model_a = ParanoidBelongsDependant.create
313
412
  model_b = ParanoidBelongsDependant.create
@@ -356,81 +455,179 @@ class ParanoidTest < ParanoidBaseTest
356
455
 
357
456
  # Test string type columns that don't have a nil value when not deleted (Y/N for example)
358
457
  def test_string_type_with_no_nil_value_before_destroy
359
- ps = ParanoidString.create!(:deleted => 'not dead')
360
- assert_equal 1, ParanoidString.where(:id => ps).count
458
+ ps = ParanoidString.create!(deleted: "not dead")
459
+ assert_equal 1, ParanoidString.where(id: ps).count
361
460
  end
362
461
 
363
462
  def test_string_type_with_no_nil_value_after_destroy
364
- ps = ParanoidString.create!(:deleted => 'not dead')
463
+ ps = ParanoidString.create!(deleted: "not dead")
365
464
  ps.destroy
366
- assert_equal 0, ParanoidString.where(:id => ps).count
465
+ assert_equal 0, ParanoidString.where(id: ps).count
367
466
  end
368
467
 
369
468
  def test_string_type_with_no_nil_value_before_destroy_with_deleted
370
- ps = ParanoidString.create!(:deleted => 'not dead')
371
- assert_equal 1, ParanoidString.with_deleted.where(:id => ps).count
469
+ ps = ParanoidString.create!(deleted: "not dead")
470
+ assert_equal 1, ParanoidString.with_deleted.where(id: ps).count
372
471
  end
373
472
 
374
473
  def test_string_type_with_no_nil_value_after_destroy_with_deleted
375
- ps = ParanoidString.create!(:deleted => 'not dead')
474
+ ps = ParanoidString.create!(deleted: "not dead")
376
475
  ps.destroy
377
- assert_equal 1, ParanoidString.with_deleted.where(:id => ps).count
476
+ assert_equal 1, ParanoidString.with_deleted.where(id: ps).count
378
477
  end
379
478
 
380
479
  def test_string_type_with_no_nil_value_before_destroy_only_deleted
381
- ps = ParanoidString.create!(:deleted => 'not dead')
382
- assert_equal 0, ParanoidString.only_deleted.where(:id => ps).count
480
+ ps = ParanoidString.create!(deleted: "not dead")
481
+ assert_equal 0, ParanoidString.only_deleted.where(id: ps).count
383
482
  end
384
483
 
385
484
  def test_string_type_with_no_nil_value_after_destroy_only_deleted
386
- ps = ParanoidString.create!(:deleted => 'not dead')
485
+ ps = ParanoidString.create!(deleted: "not dead")
387
486
  ps.destroy
388
- assert_equal 1, ParanoidString.only_deleted.where(:id => ps).count
487
+ assert_equal 1, ParanoidString.only_deleted.where(id: ps).count
389
488
  end
390
489
 
391
490
  def test_string_type_with_no_nil_value_after_destroyed_twice
392
- ps = ParanoidString.create!(:deleted => 'not dead')
491
+ ps = ParanoidString.create!(deleted: "not dead")
393
492
  2.times { ps.destroy }
394
- assert_equal 0, ParanoidString.with_deleted.where(:id => ps).count
493
+ assert_equal 0, ParanoidString.with_deleted.where(id: ps).count
395
494
  end
396
495
 
397
496
  # Test boolean type columns, that are not nullable
398
497
  def test_boolean_type_with_no_nil_value_before_destroy
399
- ps = ParanoidBooleanNotNullable.create!()
400
- assert_equal 1, ParanoidBooleanNotNullable.where(:id => ps).count
498
+ ps = ParanoidBooleanNotNullable.create!
499
+ assert_equal 1, ParanoidBooleanNotNullable.where(id: ps).count
401
500
  end
402
501
 
403
502
  def test_boolean_type_with_no_nil_value_after_destroy
404
- ps = ParanoidBooleanNotNullable.create!()
503
+ ps = ParanoidBooleanNotNullable.create!
405
504
  ps.destroy
406
- assert_equal 0, ParanoidBooleanNotNullable.where(:id => ps).count
505
+ assert_equal 0, ParanoidBooleanNotNullable.where(id: ps).count
407
506
  end
408
507
 
409
508
  def test_boolean_type_with_no_nil_value_before_destroy_with_deleted
410
- ps = ParanoidBooleanNotNullable.create!()
411
- assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(:id => ps).count
509
+ ps = ParanoidBooleanNotNullable.create!
510
+ assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(id: ps).count
412
511
  end
413
512
 
414
513
  def test_boolean_type_with_no_nil_value_after_destroy_with_deleted
415
- ps = ParanoidBooleanNotNullable.create!()
514
+ ps = ParanoidBooleanNotNullable.create!
416
515
  ps.destroy
417
- assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(:id => ps).count
516
+ assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(id: ps).count
418
517
  end
419
518
 
420
519
  def test_boolean_type_with_no_nil_value_before_destroy_only_deleted
421
- ps = ParanoidBooleanNotNullable.create!()
422
- assert_equal 0, ParanoidBooleanNotNullable.only_deleted.where(:id => ps).count
520
+ ps = ParanoidBooleanNotNullable.create!
521
+ assert_equal 0, ParanoidBooleanNotNullable.only_deleted.where(id: ps).count
423
522
  end
424
523
 
425
524
  def test_boolean_type_with_no_nil_value_after_destroy_only_deleted
426
- ps = ParanoidBooleanNotNullable.create!()
525
+ ps = ParanoidBooleanNotNullable.create!
427
526
  ps.destroy
428
- assert_equal 1, ParanoidBooleanNotNullable.only_deleted.where(:id => ps).count
527
+ assert_equal 1, ParanoidBooleanNotNullable.only_deleted.where(id: ps).count
429
528
  end
430
529
 
431
530
  def test_boolean_type_with_no_nil_value_after_destroyed_twice
432
- ps = ParanoidBooleanNotNullable.create!()
531
+ ps = ParanoidBooleanNotNullable.create!
532
+ 2.times { ps.destroy }
533
+ assert_equal 0, ParanoidBooleanNotNullable.with_deleted.where(id: ps).count
534
+ end
535
+
536
+ def test_no_double_tap_destroys_fully
537
+ ps = ParanoidNoDoubleTapDestroysFully.create!
433
538
  2.times { ps.destroy }
434
- assert_equal 0, ParanoidBooleanNotNullable.with_deleted.where(:id => ps).count
539
+ assert_equal 1, ParanoidNoDoubleTapDestroysFully.with_deleted.where(id: ps).count
540
+ end
541
+
542
+ def test_decrement_counters
543
+ paranoid_boolean = ParanoidBoolean.create!
544
+ paranoid_with_counter_cache = ParanoidWithCounterCache
545
+ .create!(paranoid_boolean: paranoid_boolean)
546
+
547
+ assert_equal 1, paranoid_boolean.paranoid_with_counter_caches_count
548
+
549
+ paranoid_with_counter_cache.destroy
550
+
551
+ assert_equal 0, paranoid_boolean.reload.paranoid_with_counter_caches_count
552
+ end
553
+
554
+ def test_decrement_custom_counters
555
+ paranoid_boolean = ParanoidBoolean.create!
556
+ paranoid_with_custom_counter_cache = ParanoidWithCustomCounterCache
557
+ .create!(paranoid_boolean: paranoid_boolean)
558
+
559
+ assert_equal 1, paranoid_boolean.custom_counter_cache
560
+
561
+ paranoid_with_custom_counter_cache.destroy
562
+
563
+ assert_equal 0, paranoid_boolean.reload.custom_counter_cache
564
+ end
565
+
566
+ def test_destroy_with_optional_belongs_to_and_counter_cache
567
+ ps = ParanoidWithCounterCacheOnOptionalBelognsTo.create!
568
+ ps.destroy
569
+ assert_equal 1, ParanoidWithCounterCacheOnOptionalBelognsTo.only_deleted
570
+ .where(id: ps).count
571
+ end
572
+
573
+ def test_hard_destroy_decrement_counters
574
+ paranoid_boolean = ParanoidBoolean.create!
575
+ paranoid_with_counter_cache = ParanoidWithCounterCache
576
+ .create!(paranoid_boolean: paranoid_boolean)
577
+
578
+ assert_equal 1, paranoid_boolean.paranoid_with_counter_caches_count
579
+
580
+ paranoid_with_counter_cache.destroy_fully!
581
+
582
+ assert_equal 0, paranoid_boolean.reload.paranoid_with_counter_caches_count
583
+ end
584
+
585
+ def test_hard_destroy_decrement_custom_counters
586
+ paranoid_boolean = ParanoidBoolean.create!
587
+ paranoid_with_custom_counter_cache = ParanoidWithCustomCounterCache
588
+ .create!(paranoid_boolean: paranoid_boolean)
589
+
590
+ assert_equal 1, paranoid_boolean.custom_counter_cache
591
+
592
+ paranoid_with_custom_counter_cache.destroy_fully!
593
+
594
+ assert_equal 0, paranoid_boolean.reload.custom_counter_cache
595
+ end
596
+
597
+ def test_increment_counters
598
+ paranoid_boolean = ParanoidBoolean.create!
599
+ paranoid_with_counter_cache = ParanoidWithCounterCache
600
+ .create!(paranoid_boolean: paranoid_boolean)
601
+
602
+ assert_equal 1, paranoid_boolean.paranoid_with_counter_caches_count
603
+
604
+ paranoid_with_counter_cache.destroy
605
+
606
+ assert_equal 0, paranoid_boolean.reload.paranoid_with_counter_caches_count
607
+
608
+ paranoid_with_counter_cache.recover
609
+
610
+ assert_equal 1, paranoid_boolean.reload.paranoid_with_counter_caches_count
611
+ end
612
+
613
+ def test_increment_custom_counters
614
+ paranoid_boolean = ParanoidBoolean.create!
615
+ paranoid_with_custom_counter_cache = ParanoidWithCustomCounterCache
616
+ .create!(paranoid_boolean: paranoid_boolean)
617
+
618
+ assert_equal 1, paranoid_boolean.custom_counter_cache
619
+
620
+ paranoid_with_custom_counter_cache.destroy
621
+
622
+ assert_equal 0, paranoid_boolean.reload.custom_counter_cache
623
+
624
+ paranoid_with_custom_counter_cache.recover
625
+
626
+ assert_equal 1, paranoid_boolean.reload.custom_counter_cache
627
+ end
628
+
629
+ def test_explicitly_setting_table_name_after_acts_as_paranoid_macro
630
+ assert_equal "explicit_table.deleted_at", ParanoidWithExplicitTableNameAfterMacro
631
+ .paranoid_column_reference
435
632
  end
436
633
  end