paranoia 2.5.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +8 -3
- data/CHANGELOG.md +22 -0
- data/Gemfile +6 -4
- data/README.md +1 -0
- data/lib/paranoia/rspec.rb +21 -18
- data/lib/paranoia/version.rb +1 -1
- data/lib/paranoia.rb +13 -3
- data/paranoia.gemspec +6 -1
- metadata +3 -4
- data/test/paranoia_test.rb +0 -1388
data/test/paranoia_test.rb
DELETED
@@ -1,1388 +0,0 @@
|
|
1
|
-
require 'bundler/setup'
|
2
|
-
require 'active_record'
|
3
|
-
require 'minitest/autorun'
|
4
|
-
require 'paranoia'
|
5
|
-
|
6
|
-
test_framework = defined?(MiniTest::Test) ? MiniTest::Test : MiniTest::Unit::TestCase
|
7
|
-
|
8
|
-
if ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks=)
|
9
|
-
ActiveRecord::Base.raise_in_transactional_callbacks = true
|
10
|
-
end
|
11
|
-
|
12
|
-
def connect!
|
13
|
-
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', database: ':memory:'
|
14
|
-
end
|
15
|
-
|
16
|
-
def setup!
|
17
|
-
connect!
|
18
|
-
{
|
19
|
-
'parent_model_with_counter_cache_columns' => 'related_models_count INTEGER DEFAULT 0',
|
20
|
-
'parent_models' => 'deleted_at DATETIME',
|
21
|
-
'paranoid_models' => 'parent_model_id INTEGER, deleted_at DATETIME',
|
22
|
-
'paranoid_model_with_belongs' => 'parent_model_id INTEGER, deleted_at DATETIME, paranoid_model_with_has_one_id INTEGER',
|
23
|
-
'paranoid_model_with_build_belongs' => 'parent_model_id INTEGER, deleted_at DATETIME, paranoid_model_with_has_one_and_build_id INTEGER, name VARCHAR(32)',
|
24
|
-
'paranoid_model_with_anthor_class_name_belongs' => 'parent_model_id INTEGER, deleted_at DATETIME, paranoid_model_with_has_one_id INTEGER',
|
25
|
-
'paranoid_model_with_foreign_key_belongs' => 'parent_model_id INTEGER, deleted_at DATETIME, has_one_foreign_key_id INTEGER',
|
26
|
-
'paranoid_model_with_timestamps' => 'parent_model_id INTEGER, created_at DATETIME, updated_at DATETIME, deleted_at DATETIME',
|
27
|
-
'not_paranoid_model_with_belongs' => 'parent_model_id INTEGER, paranoid_model_with_has_one_id INTEGER',
|
28
|
-
'not_paranoid_model_with_belongs_and_assocation_not_soft_destroyed_validator' => 'parent_model_id INTEGER, paranoid_model_with_has_one_id INTEGER',
|
29
|
-
'paranoid_model_with_has_one_and_builds' => 'parent_model_id INTEGER, color VARCHAR(32), deleted_at DATETIME, has_one_foreign_key_id INTEGER',
|
30
|
-
'featureful_models' => 'deleted_at DATETIME, name VARCHAR(32)',
|
31
|
-
'plain_models' => 'deleted_at DATETIME',
|
32
|
-
'callback_models' => 'deleted_at DATETIME',
|
33
|
-
'fail_callback_models' => 'deleted_at DATETIME',
|
34
|
-
'related_models' => 'parent_model_id INTEGER, parent_model_with_counter_cache_column_id INTEGER, deleted_at DATETIME',
|
35
|
-
'asplode_models' => 'parent_model_id INTEGER, deleted_at DATETIME',
|
36
|
-
'employers' => 'name VARCHAR(32), deleted_at DATETIME',
|
37
|
-
'employees' => 'deleted_at DATETIME',
|
38
|
-
'jobs' => 'employer_id INTEGER NOT NULL, employee_id INTEGER NOT NULL, deleted_at DATETIME',
|
39
|
-
'custom_column_models' => 'destroyed_at DATETIME',
|
40
|
-
'custom_sentinel_models' => 'deleted_at DATETIME NOT NULL',
|
41
|
-
'non_paranoid_models' => 'parent_model_id INTEGER',
|
42
|
-
'polymorphic_models' => 'parent_id INTEGER, parent_type STRING, deleted_at DATETIME',
|
43
|
-
'namespaced_paranoid_has_ones' => 'deleted_at DATETIME, paranoid_belongs_tos_id INTEGER',
|
44
|
-
'namespaced_paranoid_belongs_tos' => 'deleted_at DATETIME, paranoid_has_one_id INTEGER',
|
45
|
-
'unparanoid_unique_models' => 'name VARCHAR(32), paranoid_with_unparanoids_id INTEGER',
|
46
|
-
'active_column_models' => 'deleted_at DATETIME, active BOOLEAN',
|
47
|
-
'active_column_model_with_uniqueness_validations' => 'name VARCHAR(32), deleted_at DATETIME, active BOOLEAN',
|
48
|
-
'paranoid_model_with_belongs_to_active_column_model_with_has_many_relationships' => 'name VARCHAR(32), deleted_at DATETIME, active BOOLEAN, active_column_model_with_has_many_relationship_id INTEGER',
|
49
|
-
'active_column_model_with_has_many_relationships' => 'name VARCHAR(32), deleted_at DATETIME, active BOOLEAN',
|
50
|
-
'without_default_scope_models' => 'deleted_at DATETIME'
|
51
|
-
}.each do |table_name, columns_as_sql_string|
|
52
|
-
ActiveRecord::Base.connection.execute "CREATE TABLE #{table_name} (id INTEGER NOT NULL PRIMARY KEY, #{columns_as_sql_string})"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
class WithDifferentConnection < ActiveRecord::Base
|
57
|
-
establish_connection adapter: 'sqlite3', database: ':memory:'
|
58
|
-
connection.execute 'CREATE TABLE with_different_connections (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)'
|
59
|
-
acts_as_paranoid
|
60
|
-
end
|
61
|
-
|
62
|
-
setup!
|
63
|
-
|
64
|
-
class ParanoiaTest < test_framework
|
65
|
-
def setup
|
66
|
-
connection = ActiveRecord::Base.connection
|
67
|
-
cleaner = ->(source) {
|
68
|
-
ActiveRecord::Base.connection.execute "DELETE FROM #{source}"
|
69
|
-
}
|
70
|
-
|
71
|
-
if ActiveRecord::VERSION::MAJOR < 5
|
72
|
-
connection.tables.each(&cleaner)
|
73
|
-
else
|
74
|
-
connection.data_sources.each(&cleaner)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_plain_model_class_is_not_paranoid
|
79
|
-
assert_equal false, PlainModel.paranoid?
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_paranoid_model_class_is_paranoid
|
83
|
-
assert_equal true, ParanoidModel.paranoid?
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_plain_models_are_not_paranoid
|
87
|
-
assert_equal false, PlainModel.new.paranoid?
|
88
|
-
end
|
89
|
-
|
90
|
-
def test_paranoid_models_are_paranoid
|
91
|
-
assert_equal true, ParanoidModel.new.paranoid?
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_paranoid_models_to_param
|
95
|
-
model = ParanoidModel.new
|
96
|
-
model.save
|
97
|
-
to_param = model.to_param
|
98
|
-
|
99
|
-
model.destroy
|
100
|
-
|
101
|
-
assert model.to_param
|
102
|
-
assert_equal to_param, model.to_param
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_destroy_behavior_for_plain_models
|
106
|
-
model = PlainModel.new
|
107
|
-
assert_equal 0, model.class.count
|
108
|
-
model.save!
|
109
|
-
assert_equal 1, model.class.count
|
110
|
-
model.destroy
|
111
|
-
|
112
|
-
assert_equal true, model.deleted_at.nil?
|
113
|
-
|
114
|
-
assert_equal 0, model.class.count
|
115
|
-
assert_equal 0, model.class.unscoped.count
|
116
|
-
end
|
117
|
-
|
118
|
-
# Anti-regression test for #81, which would've introduced a bug to break this test.
|
119
|
-
def test_destroy_behavior_for_plain_models_callbacks
|
120
|
-
model = CallbackModel.new
|
121
|
-
model.save
|
122
|
-
model.remove_called_variables # clear called callback flags
|
123
|
-
model.destroy
|
124
|
-
|
125
|
-
assert_nil model.instance_variable_get(:@update_callback_called)
|
126
|
-
assert_nil model.instance_variable_get(:@save_callback_called)
|
127
|
-
assert_nil model.instance_variable_get(:@validate_called)
|
128
|
-
|
129
|
-
assert model.instance_variable_get(:@destroy_callback_called)
|
130
|
-
assert model.instance_variable_get(:@after_destroy_callback_called)
|
131
|
-
assert model.instance_variable_get(:@after_commit_callback_called)
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_destroy_behavior_for_freshly_loaded_plain_models_callbacks
|
135
|
-
model = CallbackModel.new
|
136
|
-
model.save
|
137
|
-
|
138
|
-
model = CallbackModel.find(model.id)
|
139
|
-
model.destroy
|
140
|
-
|
141
|
-
assert_nil model.instance_variable_get(:@update_callback_called)
|
142
|
-
assert_nil model.instance_variable_get(:@save_callback_called)
|
143
|
-
assert_nil model.instance_variable_get(:@validate_called)
|
144
|
-
|
145
|
-
assert model.instance_variable_get(:@destroy_callback_called)
|
146
|
-
assert model.instance_variable_get(:@after_destroy_callback_called)
|
147
|
-
assert model.instance_variable_get(:@after_commit_callback_called)
|
148
|
-
end
|
149
|
-
|
150
|
-
def test_delete_behavior_for_plain_models_callbacks
|
151
|
-
model = CallbackModel.new
|
152
|
-
model.save
|
153
|
-
model.remove_called_variables # clear called callback flags
|
154
|
-
model.delete
|
155
|
-
|
156
|
-
assert_nil model.instance_variable_get(:@update_callback_called)
|
157
|
-
assert_nil model.instance_variable_get(:@save_callback_called)
|
158
|
-
assert_nil model.instance_variable_get(:@validate_called)
|
159
|
-
assert_nil model.instance_variable_get(:@destroy_callback_called)
|
160
|
-
assert_nil model.instance_variable_get(:@after_destroy_callback_called)
|
161
|
-
assert_nil model.instance_variable_get(:@after_commit_callback_called)
|
162
|
-
end
|
163
|
-
|
164
|
-
def test_delete_in_transaction_behavior_for_plain_models_callbacks
|
165
|
-
model = CallbackModel.new
|
166
|
-
model.save
|
167
|
-
model.remove_called_variables # clear called callback flags
|
168
|
-
CallbackModel.transaction do
|
169
|
-
model.delete
|
170
|
-
end
|
171
|
-
|
172
|
-
assert_nil model.instance_variable_get(:@update_callback_called)
|
173
|
-
assert_nil model.instance_variable_get(:@save_callback_called)
|
174
|
-
assert_nil model.instance_variable_get(:@validate_called)
|
175
|
-
assert_nil model.instance_variable_get(:@destroy_callback_called)
|
176
|
-
assert_nil model.instance_variable_get(:@after_destroy_callback_called)
|
177
|
-
assert model.instance_variable_get(:@after_commit_callback_called)
|
178
|
-
end
|
179
|
-
|
180
|
-
def test_destroy_behavior_for_paranoid_models
|
181
|
-
model = ParanoidModel.new
|
182
|
-
assert_equal 0, model.class.count
|
183
|
-
model.save!
|
184
|
-
assert_equal 1, model.class.count
|
185
|
-
model.destroy
|
186
|
-
|
187
|
-
assert_equal false, model.deleted_at.nil?
|
188
|
-
|
189
|
-
assert_equal 0, model.class.count
|
190
|
-
assert_equal 1, model.class.unscoped.count
|
191
|
-
end
|
192
|
-
|
193
|
-
def test_update_columns_on_paranoia_destroyed
|
194
|
-
record = ParentModel.create
|
195
|
-
record.destroy
|
196
|
-
|
197
|
-
assert record.update_columns deleted_at: Time.now
|
198
|
-
end
|
199
|
-
|
200
|
-
def test_scoping_behavior_for_paranoid_models
|
201
|
-
parent1 = ParentModel.create
|
202
|
-
parent2 = ParentModel.create
|
203
|
-
p1 = ParanoidModel.create(:parent_model => parent1)
|
204
|
-
p2 = ParanoidModel.create(:parent_model => parent2)
|
205
|
-
p1.destroy
|
206
|
-
p2.destroy
|
207
|
-
|
208
|
-
assert_equal 0, parent1.paranoid_models.count
|
209
|
-
assert_equal 1, parent1.paranoid_models.only_deleted.count
|
210
|
-
|
211
|
-
assert_equal 2, ParanoidModel.only_deleted.joins(:parent_model).count
|
212
|
-
assert_equal 1, parent1.paranoid_models.deleted.count
|
213
|
-
assert_equal 0, parent1.paranoid_models.without_deleted.count
|
214
|
-
p3 = ParanoidModel.create(:parent_model => parent1)
|
215
|
-
assert_equal 2, parent1.paranoid_models.with_deleted.count
|
216
|
-
assert_equal 1, parent1.paranoid_models.without_deleted.count
|
217
|
-
assert_equal [p1,p3], parent1.paranoid_models.with_deleted
|
218
|
-
end
|
219
|
-
|
220
|
-
def test_only_deleted_with_joins
|
221
|
-
c1 = ActiveColumnModelWithHasManyRelationship.create(name: 'Jacky')
|
222
|
-
c2 = ActiveColumnModelWithHasManyRelationship.create(name: 'Thomas')
|
223
|
-
p1 = ParanoidModelWithBelongsToActiveColumnModelWithHasManyRelationship.create(name: 'Hello', active_column_model_with_has_many_relationship: c1)
|
224
|
-
|
225
|
-
c1.destroy
|
226
|
-
assert_equal 1, ActiveColumnModelWithHasManyRelationship.count
|
227
|
-
assert_equal 1, ActiveColumnModelWithHasManyRelationship.only_deleted.count
|
228
|
-
assert_equal 1, ActiveColumnModelWithHasManyRelationship.only_deleted.joins(:paranoid_model_with_belongs_to_active_column_model_with_has_many_relationships).count
|
229
|
-
end
|
230
|
-
|
231
|
-
def test_destroy_behavior_for_custom_column_models
|
232
|
-
model = CustomColumnModel.new
|
233
|
-
assert_equal 0, model.class.count
|
234
|
-
model.save!
|
235
|
-
assert_nil model.destroyed_at
|
236
|
-
assert_equal 1, model.class.count
|
237
|
-
model.destroy
|
238
|
-
|
239
|
-
assert_equal false, model.destroyed_at.nil?
|
240
|
-
assert model.paranoia_destroyed?
|
241
|
-
|
242
|
-
assert_equal 0, model.class.count
|
243
|
-
assert_equal 1, model.class.unscoped.count
|
244
|
-
assert_equal 1, model.class.only_deleted.count
|
245
|
-
assert_equal 1, model.class.deleted.count
|
246
|
-
end
|
247
|
-
|
248
|
-
def test_default_sentinel_value
|
249
|
-
assert_nil ParanoidModel.paranoia_sentinel_value
|
250
|
-
end
|
251
|
-
|
252
|
-
def test_without_default_scope_option
|
253
|
-
model = WithoutDefaultScopeModel.create
|
254
|
-
model.destroy
|
255
|
-
assert_equal 1, model.class.count
|
256
|
-
assert_equal 1, model.class.only_deleted.count
|
257
|
-
assert_equal 0, model.class.where(deleted_at: nil).count
|
258
|
-
end
|
259
|
-
|
260
|
-
def test_active_column_model
|
261
|
-
model = ActiveColumnModel.new
|
262
|
-
assert_equal 0, model.class.count
|
263
|
-
model.save!
|
264
|
-
assert_nil model.deleted_at
|
265
|
-
assert_equal true, model.active
|
266
|
-
assert_equal 1, model.class.count
|
267
|
-
model.destroy
|
268
|
-
|
269
|
-
assert_equal false, model.deleted_at.nil?
|
270
|
-
assert_nil model.active
|
271
|
-
assert model.paranoia_destroyed?
|
272
|
-
|
273
|
-
assert_equal 0, model.class.count
|
274
|
-
assert_equal 1, model.class.unscoped.count
|
275
|
-
assert_equal 1, model.class.only_deleted.count
|
276
|
-
assert_equal 1, model.class.deleted.count
|
277
|
-
end
|
278
|
-
|
279
|
-
def test_active_column_model_with_uniqueness_validation_only_checks_non_deleted_records
|
280
|
-
a = ActiveColumnModelWithUniquenessValidation.create!(name: "A")
|
281
|
-
a.destroy
|
282
|
-
b = ActiveColumnModelWithUniquenessValidation.new(name: "A")
|
283
|
-
assert b.valid?
|
284
|
-
end
|
285
|
-
|
286
|
-
def test_active_column_model_with_uniqueness_validation_still_works_on_non_deleted_records
|
287
|
-
a = ActiveColumnModelWithUniquenessValidation.create!(name: "A")
|
288
|
-
b = ActiveColumnModelWithUniquenessValidation.new(name: "A")
|
289
|
-
refute b.valid?
|
290
|
-
end
|
291
|
-
|
292
|
-
def test_sentinel_value_for_custom_sentinel_models
|
293
|
-
model = CustomSentinelModel.new
|
294
|
-
assert_equal 0, model.class.count
|
295
|
-
model.save!
|
296
|
-
assert_equal DateTime.new(0), model.deleted_at
|
297
|
-
assert_equal 1, model.class.count
|
298
|
-
model.destroy
|
299
|
-
|
300
|
-
assert DateTime.new(0) != model.deleted_at
|
301
|
-
assert model.paranoia_destroyed?
|
302
|
-
|
303
|
-
assert_equal 0, model.class.count
|
304
|
-
assert_equal 1, model.class.unscoped.count
|
305
|
-
assert_equal 1, model.class.only_deleted.count
|
306
|
-
assert_equal 1, model.class.deleted.count
|
307
|
-
|
308
|
-
model.restore
|
309
|
-
assert_equal DateTime.new(0), model.deleted_at
|
310
|
-
assert !model.destroyed?
|
311
|
-
|
312
|
-
assert_equal 1, model.class.count
|
313
|
-
assert_equal 1, model.class.unscoped.count
|
314
|
-
assert_equal 0, model.class.only_deleted.count
|
315
|
-
assert_equal 0, model.class.deleted.count
|
316
|
-
end
|
317
|
-
|
318
|
-
def test_destroy_behavior_for_featureful_paranoid_models
|
319
|
-
model = get_featureful_model
|
320
|
-
assert_equal 0, model.class.count
|
321
|
-
model.save!
|
322
|
-
assert_equal 1, model.class.count
|
323
|
-
model.destroy
|
324
|
-
|
325
|
-
assert_equal false, model.deleted_at.nil?
|
326
|
-
|
327
|
-
assert_equal 0, model.class.count
|
328
|
-
assert_equal 1, model.class.unscoped.count
|
329
|
-
end
|
330
|
-
|
331
|
-
def test_destroy_behavior_for_has_one_with_build_and_validation_error
|
332
|
-
model = ParanoidModelWithHasOneAndBuild.create
|
333
|
-
model.destroy
|
334
|
-
end
|
335
|
-
|
336
|
-
# Regression test for #24
|
337
|
-
def test_chaining_for_paranoid_models
|
338
|
-
scope = FeaturefulModel.where(:name => "foo").only_deleted
|
339
|
-
assert_equal({'name' => "foo"}, scope.where_values_hash)
|
340
|
-
end
|
341
|
-
|
342
|
-
def test_only_destroyed_scope_for_paranoid_models
|
343
|
-
model = ParanoidModel.new
|
344
|
-
model.save
|
345
|
-
model.destroy
|
346
|
-
model2 = ParanoidModel.new
|
347
|
-
model2.save
|
348
|
-
|
349
|
-
assert_equal model, ParanoidModel.only_deleted.last
|
350
|
-
assert_equal false, ParanoidModel.only_deleted.include?(model2)
|
351
|
-
end
|
352
|
-
|
353
|
-
def test_default_scope_for_has_many_relationships
|
354
|
-
parent = ParentModel.create
|
355
|
-
assert_equal 0, parent.related_models.count
|
356
|
-
|
357
|
-
child = parent.related_models.create
|
358
|
-
assert_equal 1, parent.related_models.count
|
359
|
-
|
360
|
-
child.destroy
|
361
|
-
assert_equal false, child.deleted_at.nil?
|
362
|
-
|
363
|
-
assert_equal 0, parent.related_models.count
|
364
|
-
assert_equal 1, parent.related_models.unscoped.count
|
365
|
-
end
|
366
|
-
|
367
|
-
def test_default_scope_for_has_many_through_relationships
|
368
|
-
employer = Employer.create
|
369
|
-
employee = Employee.create
|
370
|
-
assert_equal 0, employer.jobs.count
|
371
|
-
assert_equal 0, employer.employees.count
|
372
|
-
assert_equal 0, employee.jobs.count
|
373
|
-
assert_equal 0, employee.employers.count
|
374
|
-
|
375
|
-
job = Job.create :employer => employer, :employee => employee
|
376
|
-
assert_equal 1, employer.jobs.count
|
377
|
-
assert_equal 1, employer.employees.count
|
378
|
-
assert_equal 1, employee.jobs.count
|
379
|
-
assert_equal 1, employee.employers.count
|
380
|
-
|
381
|
-
employee2 = Employee.create
|
382
|
-
job2 = Job.create :employer => employer, :employee => employee2
|
383
|
-
employee2.destroy
|
384
|
-
assert_equal 2, employer.jobs.count
|
385
|
-
assert_equal 1, employer.employees.count
|
386
|
-
|
387
|
-
job.destroy
|
388
|
-
assert_equal 1, employer.jobs.count
|
389
|
-
assert_equal 0, employer.employees.count
|
390
|
-
assert_equal 0, employee.jobs.count
|
391
|
-
assert_equal 0, employee.employers.count
|
392
|
-
end
|
393
|
-
|
394
|
-
def test_delete_behavior_for_callbacks
|
395
|
-
model = CallbackModel.new
|
396
|
-
model.save
|
397
|
-
model.delete
|
398
|
-
assert_nil model.instance_variable_get(:@destroy_callback_called)
|
399
|
-
end
|
400
|
-
|
401
|
-
def test_destroy_behavior_for_callbacks
|
402
|
-
model = CallbackModel.new
|
403
|
-
model.save
|
404
|
-
model.destroy
|
405
|
-
assert model.instance_variable_get(:@destroy_callback_called)
|
406
|
-
end
|
407
|
-
|
408
|
-
def test_destroy_on_readonly_record
|
409
|
-
# Just to demonstrate the AR behaviour
|
410
|
-
model = NonParanoidModel.create!
|
411
|
-
model.readonly!
|
412
|
-
assert_raises ActiveRecord::ReadOnlyRecord do
|
413
|
-
model.destroy
|
414
|
-
end
|
415
|
-
|
416
|
-
# Mirrors behaviour above
|
417
|
-
model = ParanoidModel.create!
|
418
|
-
model.readonly!
|
419
|
-
assert_raises ActiveRecord::ReadOnlyRecord do
|
420
|
-
model.destroy
|
421
|
-
end
|
422
|
-
end
|
423
|
-
|
424
|
-
def test_destroy_on_really_destroyed_record
|
425
|
-
model = ParanoidModel.create!
|
426
|
-
model.really_destroy!
|
427
|
-
assert model.really_destroyed?
|
428
|
-
assert model.paranoia_destroyed?
|
429
|
-
model.destroy
|
430
|
-
assert model.really_destroyed?
|
431
|
-
assert model.paranoia_destroyed?
|
432
|
-
end
|
433
|
-
|
434
|
-
def test_destroy_on_unsaved_record
|
435
|
-
# Just to demonstrate the AR behaviour
|
436
|
-
model = NonParanoidModel.new
|
437
|
-
model.destroy!
|
438
|
-
assert model.destroyed?
|
439
|
-
model.destroy!
|
440
|
-
assert model.destroyed?
|
441
|
-
|
442
|
-
# Mirrors behaviour above
|
443
|
-
model = ParanoidModel.new
|
444
|
-
model.destroy!
|
445
|
-
assert model.paranoia_destroyed?
|
446
|
-
model.destroy!
|
447
|
-
assert model.paranoia_destroyed?
|
448
|
-
end
|
449
|
-
|
450
|
-
def test_restore
|
451
|
-
model = ParanoidModel.new
|
452
|
-
model.save
|
453
|
-
id = model.id
|
454
|
-
model.destroy
|
455
|
-
|
456
|
-
assert model.paranoia_destroyed?
|
457
|
-
|
458
|
-
model = ParanoidModel.only_deleted.find(id)
|
459
|
-
model.restore!
|
460
|
-
model.reload
|
461
|
-
|
462
|
-
assert_equal false, model.paranoia_destroyed?
|
463
|
-
end
|
464
|
-
|
465
|
-
def test_restore_on_object_return_self
|
466
|
-
model = ParanoidModel.create
|
467
|
-
model.destroy
|
468
|
-
|
469
|
-
assert_equal model.class, model.restore.class
|
470
|
-
end
|
471
|
-
|
472
|
-
# Regression test for #92
|
473
|
-
def test_destroy_twice
|
474
|
-
model = ParanoidModel.new
|
475
|
-
model.save
|
476
|
-
model.destroy
|
477
|
-
model.destroy
|
478
|
-
|
479
|
-
assert_equal 1, ParanoidModel.unscoped.where(id: model.id).count
|
480
|
-
end
|
481
|
-
|
482
|
-
# Regression test for #92
|
483
|
-
def test_destroy_bang_twice
|
484
|
-
model = ParanoidModel.new
|
485
|
-
model.save!
|
486
|
-
model.destroy!
|
487
|
-
model.destroy!
|
488
|
-
|
489
|
-
assert_equal 1, ParanoidModel.unscoped.where(id: model.id).count
|
490
|
-
end
|
491
|
-
|
492
|
-
def test_destroy_return_value_on_success
|
493
|
-
model = ParanoidModel.create
|
494
|
-
return_value = model.destroy
|
495
|
-
|
496
|
-
assert_equal(return_value, model)
|
497
|
-
end
|
498
|
-
|
499
|
-
def test_destroy_return_value_on_failure
|
500
|
-
model = FailCallbackModel.create
|
501
|
-
return_value = model.destroy
|
502
|
-
|
503
|
-
assert_equal(return_value, false)
|
504
|
-
end
|
505
|
-
|
506
|
-
def test_restore_behavior_for_callbacks
|
507
|
-
model = CallbackModel.new
|
508
|
-
model.save
|
509
|
-
id = model.id
|
510
|
-
model.destroy
|
511
|
-
|
512
|
-
assert model.paranoia_destroyed?
|
513
|
-
|
514
|
-
model = CallbackModel.only_deleted.find(id)
|
515
|
-
model.restore!
|
516
|
-
model.reload
|
517
|
-
|
518
|
-
assert model.instance_variable_get(:@restore_callback_called)
|
519
|
-
end
|
520
|
-
|
521
|
-
def test_really_destroy
|
522
|
-
model = ParanoidModel.new
|
523
|
-
model.save
|
524
|
-
model.really_destroy!
|
525
|
-
refute ParanoidModel.unscoped.exists?(model.id)
|
526
|
-
end
|
527
|
-
|
528
|
-
def test_real_destroy_dependent_destroy
|
529
|
-
parent = ParentModel.create
|
530
|
-
child1 = parent.very_related_models.create
|
531
|
-
child2 = parent.non_paranoid_models.create
|
532
|
-
child3 = parent.create_non_paranoid_model
|
533
|
-
|
534
|
-
parent.really_destroy!
|
535
|
-
|
536
|
-
refute RelatedModel.unscoped.exists?(child1.id)
|
537
|
-
refute NonParanoidModel.unscoped.exists?(child2.id)
|
538
|
-
refute NonParanoidModel.unscoped.exists?(child3.id)
|
539
|
-
end
|
540
|
-
|
541
|
-
def test_real_destroy_dependent_destroy_after_normal_destroy
|
542
|
-
parent = ParentModel.create
|
543
|
-
child = parent.very_related_models.create
|
544
|
-
parent.destroy
|
545
|
-
parent.really_destroy!
|
546
|
-
refute RelatedModel.unscoped.exists?(child.id)
|
547
|
-
end
|
548
|
-
|
549
|
-
def test_real_destroy_dependent_destroy_after_normal_destroy_does_not_delete_other_children
|
550
|
-
parent_1 = ParentModel.create
|
551
|
-
child_1 = parent_1.very_related_models.create
|
552
|
-
|
553
|
-
parent_2 = ParentModel.create
|
554
|
-
child_2 = parent_2.very_related_models.create
|
555
|
-
parent_1.destroy
|
556
|
-
parent_1.really_destroy!
|
557
|
-
assert RelatedModel.unscoped.exists?(child_2.id)
|
558
|
-
end
|
559
|
-
|
560
|
-
def test_really_destroy_behavior_for_callbacks
|
561
|
-
model = CallbackModel.new
|
562
|
-
model.save
|
563
|
-
model.really_destroy!
|
564
|
-
|
565
|
-
assert model.instance_variable_get(:@real_destroy_callback_called)
|
566
|
-
end
|
567
|
-
|
568
|
-
def test_really_destroy_behavior_for_active_column_model
|
569
|
-
model = ActiveColumnModel.new
|
570
|
-
model.save
|
571
|
-
model.really_destroy!
|
572
|
-
|
573
|
-
refute ParanoidModel.unscoped.exists?(model.id)
|
574
|
-
end
|
575
|
-
|
576
|
-
def test_really_delete
|
577
|
-
model = ParanoidModel.new
|
578
|
-
model.save
|
579
|
-
model.really_delete
|
580
|
-
|
581
|
-
refute ParanoidModel.unscoped.exists?(model.id)
|
582
|
-
end
|
583
|
-
|
584
|
-
def test_multiple_restore
|
585
|
-
a = ParanoidModel.new
|
586
|
-
a.save
|
587
|
-
a_id = a.id
|
588
|
-
a.destroy
|
589
|
-
|
590
|
-
b = ParanoidModel.new
|
591
|
-
b.save
|
592
|
-
b_id = b.id
|
593
|
-
b.destroy
|
594
|
-
|
595
|
-
c = ParanoidModel.new
|
596
|
-
c.save
|
597
|
-
c_id = c.id
|
598
|
-
c.destroy
|
599
|
-
|
600
|
-
ParanoidModel.restore([a_id, c_id])
|
601
|
-
|
602
|
-
a.reload
|
603
|
-
b.reload
|
604
|
-
c.reload
|
605
|
-
|
606
|
-
refute a.paranoia_destroyed?
|
607
|
-
assert b.paranoia_destroyed?
|
608
|
-
refute c.paranoia_destroyed?
|
609
|
-
end
|
610
|
-
|
611
|
-
def test_restore_with_associations_using_recovery_window
|
612
|
-
parent = ParentModel.create
|
613
|
-
first_child = parent.very_related_models.create
|
614
|
-
second_child = parent.very_related_models.create
|
615
|
-
|
616
|
-
parent.destroy
|
617
|
-
second_child.update(deleted_at: parent.deleted_at + 11.minutes)
|
618
|
-
|
619
|
-
parent.restore!(:recursive => true)
|
620
|
-
assert_equal true, parent.deleted_at.nil?
|
621
|
-
assert_equal true, first_child.reload.deleted_at.nil?
|
622
|
-
assert_equal true, second_child.reload.deleted_at.nil?
|
623
|
-
|
624
|
-
parent.destroy
|
625
|
-
second_child.update(deleted_at: parent.deleted_at + 11.minutes)
|
626
|
-
|
627
|
-
parent.restore(:recursive => true, :recovery_window => 10.minutes)
|
628
|
-
assert_equal true, parent.deleted_at.nil?
|
629
|
-
assert_equal true, first_child.reload.deleted_at.nil?
|
630
|
-
assert_equal false, second_child.reload.deleted_at.nil?
|
631
|
-
|
632
|
-
second_child.restore
|
633
|
-
parent.destroy
|
634
|
-
first_child.update(deleted_at: parent.deleted_at - 11.minutes)
|
635
|
-
second_child.update(deleted_at: parent.deleted_at - 9.minutes)
|
636
|
-
|
637
|
-
ParentModel.restore(parent.id, :recursive => true, :recovery_window => 10.minutes)
|
638
|
-
assert_equal true, parent.reload.deleted_at.nil?
|
639
|
-
assert_equal false, first_child.reload.deleted_at.nil?
|
640
|
-
assert_equal true, second_child.reload.deleted_at.nil?
|
641
|
-
end
|
642
|
-
|
643
|
-
def test_restore_with_associations
|
644
|
-
parent = ParentModel.create
|
645
|
-
first_child = parent.very_related_models.create
|
646
|
-
second_child = parent.non_paranoid_models.create
|
647
|
-
|
648
|
-
parent.destroy
|
649
|
-
assert_equal false, parent.deleted_at.nil?
|
650
|
-
assert_equal false, first_child.reload.deleted_at.nil?
|
651
|
-
assert_equal true, second_child.destroyed?
|
652
|
-
|
653
|
-
parent.restore!
|
654
|
-
assert_equal true, parent.deleted_at.nil?
|
655
|
-
assert_equal false, first_child.reload.deleted_at.nil?
|
656
|
-
assert_equal true, second_child.destroyed?
|
657
|
-
|
658
|
-
parent.destroy
|
659
|
-
parent.restore(:recursive => true)
|
660
|
-
assert_equal true, parent.deleted_at.nil?
|
661
|
-
assert_equal true, first_child.reload.deleted_at.nil?
|
662
|
-
assert_equal true, second_child.destroyed?
|
663
|
-
|
664
|
-
parent.destroy
|
665
|
-
ParentModel.restore(parent.id, :recursive => true)
|
666
|
-
assert_equal true, parent.reload.deleted_at.nil?
|
667
|
-
assert_equal true, first_child.reload.deleted_at.nil?
|
668
|
-
assert_equal true, second_child.destroyed?
|
669
|
-
end
|
670
|
-
|
671
|
-
# regression tests for #118
|
672
|
-
def test_restore_with_has_one_association
|
673
|
-
# setup and destroy test objects
|
674
|
-
hasOne = ParanoidModelWithHasOne.create
|
675
|
-
belongsTo = ParanoidModelWithBelong.create
|
676
|
-
anthorClassName = ParanoidModelWithAnthorClassNameBelong.create
|
677
|
-
foreignKey = ParanoidModelWithForeignKeyBelong.create
|
678
|
-
notParanoidModel = NotParanoidModelWithBelong.create
|
679
|
-
|
680
|
-
hasOne.paranoid_model_with_belong = belongsTo
|
681
|
-
hasOne.class_name_belong = anthorClassName
|
682
|
-
hasOne.paranoid_model_with_foreign_key_belong = foreignKey
|
683
|
-
hasOne.not_paranoid_model_with_belong = notParanoidModel
|
684
|
-
hasOne.save!
|
685
|
-
|
686
|
-
hasOne.destroy
|
687
|
-
assert_equal false, hasOne.deleted_at.nil?
|
688
|
-
assert_equal false, belongsTo.deleted_at.nil?
|
689
|
-
|
690
|
-
# Does it restore has_one associations?
|
691
|
-
hasOne.restore(:recursive => true)
|
692
|
-
hasOne.save!
|
693
|
-
|
694
|
-
assert_equal true, hasOne.reload.deleted_at.nil?
|
695
|
-
assert_equal true, belongsTo.reload.deleted_at.nil?, "#{belongsTo.deleted_at}"
|
696
|
-
assert_equal true, notParanoidModel.destroyed?
|
697
|
-
assert ParanoidModelWithBelong.with_deleted.reload.count != 0, "There should be a record"
|
698
|
-
assert ParanoidModelWithAnthorClassNameBelong.with_deleted.reload.count != 0, "There should be an other record"
|
699
|
-
assert ParanoidModelWithForeignKeyBelong.with_deleted.reload.count != 0, "There should be a foreign_key record"
|
700
|
-
end
|
701
|
-
|
702
|
-
def test_new_restore_with_has_one_association
|
703
|
-
# setup and destroy test objects
|
704
|
-
hasOne = ParanoidModelWithHasOne.create
|
705
|
-
belongsTo = ParanoidModelWithBelong.create
|
706
|
-
anthorClassName = ParanoidModelWithAnthorClassNameBelong.create
|
707
|
-
foreignKey = ParanoidModelWithForeignKeyBelong.create
|
708
|
-
notParanoidModel = NotParanoidModelWithBelong.create
|
709
|
-
|
710
|
-
hasOne.paranoid_model_with_belong = belongsTo
|
711
|
-
hasOne.class_name_belong = anthorClassName
|
712
|
-
hasOne.paranoid_model_with_foreign_key_belong = foreignKey
|
713
|
-
hasOne.not_paranoid_model_with_belong = notParanoidModel
|
714
|
-
hasOne.save!
|
715
|
-
|
716
|
-
hasOne.destroy
|
717
|
-
assert_equal false, hasOne.deleted_at.nil?
|
718
|
-
assert_equal false, belongsTo.deleted_at.nil?
|
719
|
-
|
720
|
-
# Does it restore has_one associations?
|
721
|
-
newHasOne = ParanoidModelWithHasOne.with_deleted.find(hasOne.id)
|
722
|
-
newHasOne.restore(:recursive => true)
|
723
|
-
newHasOne.save!
|
724
|
-
|
725
|
-
assert_equal true, hasOne.reload.deleted_at.nil?
|
726
|
-
assert_equal true, belongsTo.reload.deleted_at.nil?, "#{belongsTo.deleted_at}"
|
727
|
-
assert_equal true, notParanoidModel.destroyed?
|
728
|
-
assert ParanoidModelWithBelong.with_deleted.reload.count != 0, "There should be a record"
|
729
|
-
assert ParanoidModelWithAnthorClassNameBelong.with_deleted.reload.count != 0, "There should be an other record"
|
730
|
-
assert ParanoidModelWithForeignKeyBelong.with_deleted.reload.count != 0, "There should be a foreign_key record"
|
731
|
-
end
|
732
|
-
|
733
|
-
def test_model_restore_with_has_one_association
|
734
|
-
# setup and destroy test objects
|
735
|
-
hasOne = ParanoidModelWithHasOne.create
|
736
|
-
belongsTo = ParanoidModelWithBelong.create
|
737
|
-
anthorClassName = ParanoidModelWithAnthorClassNameBelong.create
|
738
|
-
foreignKey = ParanoidModelWithForeignKeyBelong.create
|
739
|
-
notParanoidModel = NotParanoidModelWithBelong.create
|
740
|
-
|
741
|
-
hasOne.paranoid_model_with_belong = belongsTo
|
742
|
-
hasOne.class_name_belong = anthorClassName
|
743
|
-
hasOne.paranoid_model_with_foreign_key_belong = foreignKey
|
744
|
-
hasOne.not_paranoid_model_with_belong = notParanoidModel
|
745
|
-
hasOne.save!
|
746
|
-
|
747
|
-
hasOne.destroy
|
748
|
-
assert_equal false, hasOne.deleted_at.nil?
|
749
|
-
assert_equal false, belongsTo.deleted_at.nil?
|
750
|
-
|
751
|
-
# Does it restore has_one associations?
|
752
|
-
ParanoidModelWithHasOne.restore(hasOne.id, :recursive => true)
|
753
|
-
hasOne.save!
|
754
|
-
|
755
|
-
assert_equal true, hasOne.reload.deleted_at.nil?
|
756
|
-
assert_equal true, belongsTo.reload.deleted_at.nil?, "#{belongsTo.deleted_at}"
|
757
|
-
assert_equal true, notParanoidModel.destroyed?
|
758
|
-
assert ParanoidModelWithBelong.with_deleted.reload.count != 0, "There should be a record"
|
759
|
-
assert ParanoidModelWithAnthorClassNameBelong.with_deleted.reload.count != 0, "There should be an other record"
|
760
|
-
assert ParanoidModelWithForeignKeyBelong.with_deleted.reload.count != 0, "There should be a foreign_key record"
|
761
|
-
end
|
762
|
-
|
763
|
-
def test_restore_with_nil_has_one_association
|
764
|
-
# setup and destroy test object
|
765
|
-
hasOne = ParanoidModelWithHasOne.create
|
766
|
-
hasOne.destroy
|
767
|
-
assert_equal false, hasOne.reload.deleted_at.nil?
|
768
|
-
|
769
|
-
# Does it raise NoMethodException on restore of nil
|
770
|
-
hasOne.restore(:recursive => true)
|
771
|
-
|
772
|
-
assert hasOne.reload.deleted_at.nil?
|
773
|
-
end
|
774
|
-
|
775
|
-
def test_restore_with_module_scoped_has_one_association
|
776
|
-
# setup and destroy test object
|
777
|
-
hasOne = Namespaced::ParanoidHasOne.create
|
778
|
-
hasOne.destroy
|
779
|
-
assert_equal false, hasOne.reload.deleted_at.nil?
|
780
|
-
|
781
|
-
# Does it raise "uninitialized constant ParanoidBelongsTo"
|
782
|
-
# on restore of ParanoidHasOne?
|
783
|
-
hasOne.restore(:recursive => true)
|
784
|
-
|
785
|
-
assert hasOne.reload.deleted_at.nil?
|
786
|
-
end
|
787
|
-
|
788
|
-
# covers #185
|
789
|
-
def test_restoring_recursive_has_one_restores_correct_object
|
790
|
-
hasOnes = 2.times.map { ParanoidModelWithHasOne.create }
|
791
|
-
belongsTos = 2.times.map { ParanoidModelWithBelong.create }
|
792
|
-
|
793
|
-
hasOnes[0].update paranoid_model_with_belong: belongsTos[0]
|
794
|
-
hasOnes[1].update paranoid_model_with_belong: belongsTos[1]
|
795
|
-
|
796
|
-
hasOnes.each(&:destroy)
|
797
|
-
|
798
|
-
ParanoidModelWithHasOne.restore(hasOnes[1].id, :recursive => true)
|
799
|
-
hasOnes.each(&:reload)
|
800
|
-
belongsTos.each(&:reload)
|
801
|
-
|
802
|
-
# without #185, belongsTos[0] will be restored instead of belongsTos[1]
|
803
|
-
refute_nil hasOnes[0].deleted_at
|
804
|
-
refute_nil belongsTos[0].deleted_at
|
805
|
-
assert_nil hasOnes[1].deleted_at
|
806
|
-
assert_nil belongsTos[1].deleted_at
|
807
|
-
end
|
808
|
-
|
809
|
-
# covers #131
|
810
|
-
def test_has_one_really_destroy_with_nil
|
811
|
-
model = ParanoidModelWithHasOne.create
|
812
|
-
model.really_destroy!
|
813
|
-
|
814
|
-
refute ParanoidModelWithBelong.unscoped.exists?(model.id)
|
815
|
-
end
|
816
|
-
|
817
|
-
def test_has_one_really_destroy_with_record
|
818
|
-
model = ParanoidModelWithHasOne.create { |record| record.build_paranoid_model_with_belong }
|
819
|
-
model.really_destroy!
|
820
|
-
|
821
|
-
refute ParanoidModelWithBelong.unscoped.exists?(model.id)
|
822
|
-
end
|
823
|
-
|
824
|
-
def test_observers_notified
|
825
|
-
a = ParanoidModelWithObservers.create
|
826
|
-
a.destroy
|
827
|
-
a.restore!
|
828
|
-
|
829
|
-
assert a.observers_notified.select {|args| args == [:before_restore, a]}
|
830
|
-
assert a.observers_notified.select {|args| args == [:after_restore, a]}
|
831
|
-
end
|
832
|
-
|
833
|
-
def test_observers_not_notified_if_not_supported
|
834
|
-
a = ParanoidModelWithObservers.create
|
835
|
-
a.destroy
|
836
|
-
a.restore!
|
837
|
-
# essentially, we're just ensuring that this doesn't crash
|
838
|
-
end
|
839
|
-
|
840
|
-
def test_validates_uniqueness_only_checks_non_deleted_records
|
841
|
-
a = Employer.create!(name: "A")
|
842
|
-
a.destroy
|
843
|
-
b = Employer.new(name: "A")
|
844
|
-
assert b.valid?
|
845
|
-
end
|
846
|
-
|
847
|
-
def test_validates_uniqueness_still_works_on_non_deleted_records
|
848
|
-
a = Employer.create!(name: "A")
|
849
|
-
b = Employer.new(name: "A")
|
850
|
-
refute b.valid?
|
851
|
-
end
|
852
|
-
|
853
|
-
def test_updated_at_modification_on_destroy
|
854
|
-
paranoid_model = ParanoidModelWithTimestamp.create(:parent_model => ParentModel.create, :updated_at => 1.day.ago)
|
855
|
-
assert paranoid_model.updated_at < 10.minutes.ago
|
856
|
-
paranoid_model.destroy
|
857
|
-
assert paranoid_model.updated_at > 10.minutes.ago
|
858
|
-
end
|
859
|
-
|
860
|
-
def test_updated_at_modification_on_restore
|
861
|
-
parent1 = ParentModel.create
|
862
|
-
pt1 = ParanoidModelWithTimestamp.create(:parent_model => parent1)
|
863
|
-
ParanoidModelWithTimestamp.record_timestamps = false
|
864
|
-
pt1.update_columns(created_at: 20.years.ago, updated_at: 10.years.ago, deleted_at: 10.years.ago)
|
865
|
-
ParanoidModelWithTimestamp.record_timestamps = true
|
866
|
-
assert pt1.updated_at < 10.minutes.ago
|
867
|
-
refute pt1.deleted_at.nil?
|
868
|
-
pt1.restore!
|
869
|
-
assert pt1.deleted_at.nil?
|
870
|
-
assert pt1.updated_at > 10.minutes.ago
|
871
|
-
end
|
872
|
-
|
873
|
-
def test_i_am_the_destroyer
|
874
|
-
expected = %Q{
|
875
|
-
Sharon: "There should be a method called I_AM_THE_DESTROYER!"
|
876
|
-
Ryan: "What should this method do?"
|
877
|
-
Sharon: "It should fix all the spelling errors on the page!"
|
878
|
-
}
|
879
|
-
assert_output expected do
|
880
|
-
ParanoidModel.I_AM_THE_DESTROYER!
|
881
|
-
end
|
882
|
-
end
|
883
|
-
|
884
|
-
def test_destroy_fails_if_callback_raises_exception
|
885
|
-
parent = AsplodeModel.create
|
886
|
-
|
887
|
-
assert_raises(StandardError) { parent.destroy }
|
888
|
-
|
889
|
-
#transaction should be rolled back, so parent NOT deleted
|
890
|
-
refute parent.destroyed?, 'Parent record was destroyed, even though AR callback threw exception'
|
891
|
-
end
|
892
|
-
|
893
|
-
def test_destroy_fails_if_association_callback_raises_exception
|
894
|
-
parent = ParentModel.create
|
895
|
-
children = []
|
896
|
-
3.times { children << parent.asplode_models.create }
|
897
|
-
|
898
|
-
assert_raises(StandardError) { parent.destroy }
|
899
|
-
|
900
|
-
#transaction should be rolled back, so parent and children NOT deleted
|
901
|
-
refute parent.destroyed?, 'Parent record was destroyed, even though AR callback threw exception'
|
902
|
-
refute children.any?(&:destroyed?), 'Child record was destroyed, even though AR callback threw exception'
|
903
|
-
end
|
904
|
-
|
905
|
-
def test_restore_model_with_different_connection
|
906
|
-
ActiveRecord::Base.remove_connection # Disconnect the main connection
|
907
|
-
a = WithDifferentConnection.create
|
908
|
-
a.destroy!
|
909
|
-
a.restore!
|
910
|
-
# This test passes if no exception is raised
|
911
|
-
ensure
|
912
|
-
setup! # Reconnect the main connection
|
913
|
-
end
|
914
|
-
|
915
|
-
def test_restore_clear_association_cache_if_associations_present
|
916
|
-
parent = ParentModel.create
|
917
|
-
3.times { parent.very_related_models.create }
|
918
|
-
|
919
|
-
parent.destroy
|
920
|
-
|
921
|
-
assert_equal 0, parent.very_related_models.count
|
922
|
-
assert_equal 0, parent.very_related_models.size
|
923
|
-
|
924
|
-
parent.restore(recursive: true)
|
925
|
-
|
926
|
-
assert_equal 3, parent.very_related_models.count
|
927
|
-
assert_equal 3, parent.very_related_models.size
|
928
|
-
end
|
929
|
-
|
930
|
-
def test_model_without_db_connection
|
931
|
-
ActiveRecord::Base.remove_connection
|
932
|
-
|
933
|
-
NoConnectionModel.class_eval{ acts_as_paranoid }
|
934
|
-
ensure
|
935
|
-
setup!
|
936
|
-
end
|
937
|
-
|
938
|
-
def test_restore_recursive_on_polymorphic_has_one_association
|
939
|
-
parent = ParentModel.create
|
940
|
-
polymorphic = PolymorphicModel.create(parent: parent)
|
941
|
-
|
942
|
-
parent.destroy
|
943
|
-
|
944
|
-
assert_equal 0, polymorphic.class.count
|
945
|
-
|
946
|
-
parent.restore(recursive: true)
|
947
|
-
|
948
|
-
assert_equal 1, polymorphic.class.count
|
949
|
-
end
|
950
|
-
|
951
|
-
# Ensure that we're checking parent_type when restoring
|
952
|
-
def test_missing_restore_recursive_on_polymorphic_has_one_association
|
953
|
-
parent = ParentModel.create
|
954
|
-
polymorphic = PolymorphicModel.create(parent_id: parent.id, parent_type: 'ParanoidModel')
|
955
|
-
|
956
|
-
parent.destroy
|
957
|
-
polymorphic.destroy
|
958
|
-
|
959
|
-
assert_equal 0, polymorphic.class.count
|
960
|
-
|
961
|
-
parent.restore(recursive: true)
|
962
|
-
|
963
|
-
assert_equal 0, polymorphic.class.count
|
964
|
-
end
|
965
|
-
|
966
|
-
def test_counter_cache_column_update_on_destroy#_and_restore_and_really_destroy
|
967
|
-
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
968
|
-
related_model = parent_model_with_counter_cache_column.related_models.create
|
969
|
-
|
970
|
-
assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count
|
971
|
-
related_model.destroy
|
972
|
-
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
|
973
|
-
end
|
974
|
-
|
975
|
-
def test_callbacks_for_counter_cache_column_update_on_destroy
|
976
|
-
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
977
|
-
related_model = parent_model_with_counter_cache_column.related_models.create
|
978
|
-
|
979
|
-
assert_nil related_model.instance_variable_get(:@after_destroy_callback_called)
|
980
|
-
assert_nil related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
|
981
|
-
|
982
|
-
related_model.destroy
|
983
|
-
|
984
|
-
assert related_model.instance_variable_get(:@after_destroy_callback_called)
|
985
|
-
# assert related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
|
986
|
-
end
|
987
|
-
|
988
|
-
def test_uniqueness_for_unparanoid_associated
|
989
|
-
parent_model = ParanoidWithUnparanoids.create
|
990
|
-
related = parent_model.unparanoid_unique_models.create
|
991
|
-
# will raise exception if model is not checked for paranoia
|
992
|
-
related.valid?
|
993
|
-
end
|
994
|
-
|
995
|
-
def test_assocation_not_soft_destroyed_validator
|
996
|
-
notParanoidModel = NotParanoidModelWithBelongsAndAssocationNotSoftDestroyedValidator.create
|
997
|
-
parentModel = ParentModel.create
|
998
|
-
assert notParanoidModel.valid?
|
999
|
-
|
1000
|
-
notParanoidModel.parent_model = parentModel
|
1001
|
-
assert notParanoidModel.valid?
|
1002
|
-
parentModel.destroy
|
1003
|
-
assert !notParanoidModel.valid?
|
1004
|
-
assert notParanoidModel.errors.full_messages.include? "Parent model has been soft-deleted"
|
1005
|
-
end
|
1006
|
-
|
1007
|
-
# TODO: find a fix for Rails 4.1
|
1008
|
-
if ActiveRecord::VERSION::STRING !~ /\A4\.1/
|
1009
|
-
def test_counter_cache_column_update_on_really_destroy
|
1010
|
-
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1011
|
-
related_model = parent_model_with_counter_cache_column.related_models.create
|
1012
|
-
|
1013
|
-
assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count
|
1014
|
-
related_model.really_destroy!
|
1015
|
-
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
|
1016
|
-
end
|
1017
|
-
end
|
1018
|
-
|
1019
|
-
# TODO: find a fix for Rails 4.0 and 4.1
|
1020
|
-
if ActiveRecord::VERSION::STRING >= '4.2'
|
1021
|
-
def test_callbacks_for_counter_cache_column_update_on_really_destroy!
|
1022
|
-
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1023
|
-
related_model = parent_model_with_counter_cache_column.related_models.create
|
1024
|
-
|
1025
|
-
assert_nil related_model.instance_variable_get(:@after_destroy_callback_called)
|
1026
|
-
assert_nil related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
|
1027
|
-
|
1028
|
-
related_model.really_destroy!
|
1029
|
-
|
1030
|
-
assert related_model.instance_variable_get(:@after_destroy_callback_called)
|
1031
|
-
assert related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
|
1032
|
-
end
|
1033
|
-
|
1034
|
-
def test_counter_cache_column_on_double_destroy
|
1035
|
-
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1036
|
-
related_model = parent_model_with_counter_cache_column.related_models.create
|
1037
|
-
|
1038
|
-
related_model.destroy
|
1039
|
-
related_model.destroy
|
1040
|
-
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
|
1041
|
-
end
|
1042
|
-
|
1043
|
-
def test_counter_cache_column_on_double_restore
|
1044
|
-
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1045
|
-
related_model = parent_model_with_counter_cache_column.related_models.create
|
1046
|
-
|
1047
|
-
related_model.destroy
|
1048
|
-
related_model.restore
|
1049
|
-
related_model.restore
|
1050
|
-
assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count
|
1051
|
-
end
|
1052
|
-
|
1053
|
-
def test_counter_cache_column_on_destroy_and_really_destroy
|
1054
|
-
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1055
|
-
related_model = parent_model_with_counter_cache_column.related_models.create
|
1056
|
-
|
1057
|
-
related_model.destroy
|
1058
|
-
related_model.really_destroy!
|
1059
|
-
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
|
1060
|
-
end
|
1061
|
-
|
1062
|
-
def test_counter_cache_column_on_restore
|
1063
|
-
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1064
|
-
related_model = parent_model_with_counter_cache_column.related_models.create
|
1065
|
-
|
1066
|
-
related_model.destroy
|
1067
|
-
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
|
1068
|
-
related_model.restore
|
1069
|
-
assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count
|
1070
|
-
end
|
1071
|
-
end
|
1072
|
-
|
1073
|
-
private
|
1074
|
-
def get_featureful_model
|
1075
|
-
FeaturefulModel.new(:name => "not empty")
|
1076
|
-
end
|
1077
|
-
end
|
1078
|
-
|
1079
|
-
# Helper classes
|
1080
|
-
|
1081
|
-
class ParanoidModel < ActiveRecord::Base
|
1082
|
-
belongs_to :parent_model
|
1083
|
-
acts_as_paranoid
|
1084
|
-
end
|
1085
|
-
|
1086
|
-
class ParanoidWithUnparanoids < ActiveRecord::Base
|
1087
|
-
self.table_name = 'plain_models'
|
1088
|
-
has_many :unparanoid_unique_models
|
1089
|
-
end
|
1090
|
-
|
1091
|
-
class UnparanoidUniqueModel < ActiveRecord::Base
|
1092
|
-
belongs_to :paranoid_with_unparanoids
|
1093
|
-
validates :name, :uniqueness => true
|
1094
|
-
end
|
1095
|
-
|
1096
|
-
class FailCallbackModel < ActiveRecord::Base
|
1097
|
-
belongs_to :parent_model
|
1098
|
-
acts_as_paranoid
|
1099
|
-
|
1100
|
-
before_destroy { |_|
|
1101
|
-
if ActiveRecord::VERSION::MAJOR < 5
|
1102
|
-
false
|
1103
|
-
else
|
1104
|
-
throw :abort
|
1105
|
-
end
|
1106
|
-
}
|
1107
|
-
end
|
1108
|
-
|
1109
|
-
class FeaturefulModel < ActiveRecord::Base
|
1110
|
-
acts_as_paranoid
|
1111
|
-
validates :name, :presence => true, :uniqueness => true
|
1112
|
-
end
|
1113
|
-
|
1114
|
-
class NonParanoidChildModel < ActiveRecord::Base
|
1115
|
-
validates :name, :presence => true, :uniqueness => true
|
1116
|
-
end
|
1117
|
-
|
1118
|
-
class PlainModel < ActiveRecord::Base
|
1119
|
-
end
|
1120
|
-
|
1121
|
-
class CallbackModel < ActiveRecord::Base
|
1122
|
-
acts_as_paranoid
|
1123
|
-
before_destroy { |model| model.instance_variable_set :@destroy_callback_called, true }
|
1124
|
-
before_restore { |model| model.instance_variable_set :@restore_callback_called, true }
|
1125
|
-
before_update { |model| model.instance_variable_set :@update_callback_called, true }
|
1126
|
-
before_save { |model| model.instance_variable_set :@save_callback_called, true}
|
1127
|
-
before_real_destroy { |model| model.instance_variable_set :@real_destroy_callback_called, true }
|
1128
|
-
|
1129
|
-
after_destroy { |model| model.instance_variable_set :@after_destroy_callback_called, true }
|
1130
|
-
after_commit { |model| model.instance_variable_set :@after_commit_callback_called, true }
|
1131
|
-
|
1132
|
-
validate { |model| model.instance_variable_set :@validate_called, true }
|
1133
|
-
|
1134
|
-
def remove_called_variables
|
1135
|
-
instance_variables.each {|name| (name.to_s.end_with?('_called')) ? remove_instance_variable(name) : nil}
|
1136
|
-
end
|
1137
|
-
end
|
1138
|
-
|
1139
|
-
class ParentModel < ActiveRecord::Base
|
1140
|
-
acts_as_paranoid
|
1141
|
-
has_many :paranoid_models
|
1142
|
-
has_many :related_models
|
1143
|
-
has_many :very_related_models, :class_name => 'RelatedModel', dependent: :destroy
|
1144
|
-
has_many :non_paranoid_models, dependent: :destroy
|
1145
|
-
has_one :non_paranoid_model, dependent: :destroy
|
1146
|
-
has_many :asplode_models, dependent: :destroy
|
1147
|
-
has_one :polymorphic_model, as: :parent, dependent: :destroy
|
1148
|
-
end
|
1149
|
-
|
1150
|
-
class ParentModelWithCounterCacheColumn < ActiveRecord::Base
|
1151
|
-
has_many :related_models
|
1152
|
-
end
|
1153
|
-
|
1154
|
-
class RelatedModel < ActiveRecord::Base
|
1155
|
-
acts_as_paranoid
|
1156
|
-
belongs_to :parent_model
|
1157
|
-
belongs_to :parent_model_with_counter_cache_column, counter_cache: true
|
1158
|
-
|
1159
|
-
after_destroy do |model|
|
1160
|
-
if parent_model_with_counter_cache_column && parent_model_with_counter_cache_column.reload.related_models_count == 0
|
1161
|
-
model.instance_variable_set :@after_destroy_callback_called, true
|
1162
|
-
end
|
1163
|
-
end
|
1164
|
-
after_commit :set_after_commit_on_destroy_callback_called, on: :destroy
|
1165
|
-
|
1166
|
-
def set_after_commit_on_destroy_callback_called
|
1167
|
-
if parent_model_with_counter_cache_column && parent_model_with_counter_cache_column.reload.related_models_count == 0
|
1168
|
-
self.instance_variable_set :@after_commit_on_destroy_callback_called, true
|
1169
|
-
end
|
1170
|
-
end
|
1171
|
-
end
|
1172
|
-
|
1173
|
-
class Employer < ActiveRecord::Base
|
1174
|
-
acts_as_paranoid
|
1175
|
-
validates_uniqueness_of :name
|
1176
|
-
has_many :jobs
|
1177
|
-
has_many :employees, :through => :jobs
|
1178
|
-
end
|
1179
|
-
|
1180
|
-
class Employee < ActiveRecord::Base
|
1181
|
-
acts_as_paranoid
|
1182
|
-
has_many :jobs
|
1183
|
-
has_many :employers, :through => :jobs
|
1184
|
-
end
|
1185
|
-
|
1186
|
-
class Job < ActiveRecord::Base
|
1187
|
-
acts_as_paranoid
|
1188
|
-
belongs_to :employer
|
1189
|
-
belongs_to :employee
|
1190
|
-
end
|
1191
|
-
|
1192
|
-
class CustomColumnModel < ActiveRecord::Base
|
1193
|
-
acts_as_paranoid column: :destroyed_at
|
1194
|
-
end
|
1195
|
-
|
1196
|
-
class CustomSentinelModel < ActiveRecord::Base
|
1197
|
-
acts_as_paranoid sentinel_value: DateTime.new(0)
|
1198
|
-
end
|
1199
|
-
|
1200
|
-
class WithoutDefaultScopeModel < ActiveRecord::Base
|
1201
|
-
acts_as_paranoid without_default_scope: true
|
1202
|
-
end
|
1203
|
-
|
1204
|
-
class ActiveColumnModel < ActiveRecord::Base
|
1205
|
-
acts_as_paranoid column: :active, sentinel_value: true
|
1206
|
-
|
1207
|
-
def paranoia_restore_attributes
|
1208
|
-
{
|
1209
|
-
deleted_at: nil,
|
1210
|
-
active: true
|
1211
|
-
}
|
1212
|
-
end
|
1213
|
-
|
1214
|
-
def paranoia_destroy_attributes
|
1215
|
-
{
|
1216
|
-
deleted_at: current_time_from_proper_timezone,
|
1217
|
-
active: nil
|
1218
|
-
}
|
1219
|
-
end
|
1220
|
-
end
|
1221
|
-
|
1222
|
-
class ActiveColumnModelWithUniquenessValidation < ActiveRecord::Base
|
1223
|
-
validates :name, :uniqueness => true
|
1224
|
-
acts_as_paranoid column: :active, sentinel_value: true
|
1225
|
-
|
1226
|
-
def paranoia_restore_attributes
|
1227
|
-
{
|
1228
|
-
deleted_at: nil,
|
1229
|
-
active: true
|
1230
|
-
}
|
1231
|
-
end
|
1232
|
-
|
1233
|
-
def paranoia_destroy_attributes
|
1234
|
-
{
|
1235
|
-
deleted_at: current_time_from_proper_timezone,
|
1236
|
-
active: nil
|
1237
|
-
}
|
1238
|
-
end
|
1239
|
-
end
|
1240
|
-
|
1241
|
-
class ActiveColumnModelWithHasManyRelationship < ActiveRecord::Base
|
1242
|
-
has_many :paranoid_model_with_belongs_to_active_column_model_with_has_many_relationships
|
1243
|
-
acts_as_paranoid column: :active, sentinel_value: true
|
1244
|
-
|
1245
|
-
def paranoia_restore_attributes
|
1246
|
-
{
|
1247
|
-
deleted_at: nil,
|
1248
|
-
active: true
|
1249
|
-
}
|
1250
|
-
end
|
1251
|
-
|
1252
|
-
def paranoia_destroy_attributes
|
1253
|
-
{
|
1254
|
-
deleted_at: current_time_from_proper_timezone,
|
1255
|
-
active: nil
|
1256
|
-
}
|
1257
|
-
end
|
1258
|
-
end
|
1259
|
-
|
1260
|
-
class ParanoidModelWithBelongsToActiveColumnModelWithHasManyRelationship < ActiveRecord::Base
|
1261
|
-
belongs_to :active_column_model_with_has_many_relationship
|
1262
|
-
|
1263
|
-
acts_as_paranoid column: :active, sentinel_value: true
|
1264
|
-
|
1265
|
-
def paranoia_restore_attributes
|
1266
|
-
{
|
1267
|
-
deleted_at: nil,
|
1268
|
-
active: true
|
1269
|
-
}
|
1270
|
-
end
|
1271
|
-
|
1272
|
-
def paranoia_destroy_attributes
|
1273
|
-
{
|
1274
|
-
deleted_at: current_time_from_proper_timezone,
|
1275
|
-
active: nil
|
1276
|
-
}
|
1277
|
-
end
|
1278
|
-
end
|
1279
|
-
|
1280
|
-
class NonParanoidModel < ActiveRecord::Base
|
1281
|
-
end
|
1282
|
-
|
1283
|
-
class ParanoidModelWithObservers < ParanoidModel
|
1284
|
-
def observers_notified
|
1285
|
-
@observers_notified ||= []
|
1286
|
-
end
|
1287
|
-
|
1288
|
-
def self.notify_observer(*args)
|
1289
|
-
observers_notified << args
|
1290
|
-
end
|
1291
|
-
end
|
1292
|
-
|
1293
|
-
class ParanoidModelWithoutObservers < ParanoidModel
|
1294
|
-
self.class.send(remove_method :notify_observers) if method_defined?(:notify_observers)
|
1295
|
-
end
|
1296
|
-
|
1297
|
-
# refer back to regression test for #118
|
1298
|
-
class ParanoidModelWithHasOne < ParanoidModel
|
1299
|
-
has_one :paranoid_model_with_belong, :dependent => :destroy
|
1300
|
-
has_one :class_name_belong, :dependent => :destroy, :class_name => "ParanoidModelWithAnthorClassNameBelong"
|
1301
|
-
has_one :paranoid_model_with_foreign_key_belong, :dependent => :destroy, :foreign_key => "has_one_foreign_key_id"
|
1302
|
-
has_one :not_paranoid_model_with_belong, :dependent => :destroy
|
1303
|
-
end
|
1304
|
-
|
1305
|
-
class ParanoidModelWithHasOneAndBuild < ActiveRecord::Base
|
1306
|
-
has_one :paranoid_model_with_build_belong, :dependent => :destroy
|
1307
|
-
validates :color, :presence => true
|
1308
|
-
after_validation :build_paranoid_model_with_build_belong, on: :create
|
1309
|
-
|
1310
|
-
private
|
1311
|
-
def build_paranoid_model_with_build_belong
|
1312
|
-
super.tap { |child| child.name = "foo" }
|
1313
|
-
end
|
1314
|
-
end
|
1315
|
-
|
1316
|
-
class ParanoidModelWithBuildBelong < ActiveRecord::Base
|
1317
|
-
acts_as_paranoid
|
1318
|
-
validates :name, :presence => true
|
1319
|
-
belongs_to :paranoid_model_with_has_one_and_build
|
1320
|
-
end
|
1321
|
-
|
1322
|
-
class ParanoidModelWithBelong < ActiveRecord::Base
|
1323
|
-
acts_as_paranoid
|
1324
|
-
belongs_to :paranoid_model_with_has_one
|
1325
|
-
end
|
1326
|
-
|
1327
|
-
class ParanoidModelWithAnthorClassNameBelong < ActiveRecord::Base
|
1328
|
-
acts_as_paranoid
|
1329
|
-
belongs_to :paranoid_model_with_has_one
|
1330
|
-
end
|
1331
|
-
|
1332
|
-
class ParanoidModelWithForeignKeyBelong < ActiveRecord::Base
|
1333
|
-
acts_as_paranoid
|
1334
|
-
belongs_to :paranoid_model_with_has_one
|
1335
|
-
end
|
1336
|
-
|
1337
|
-
class ParanoidModelWithTimestamp < ActiveRecord::Base
|
1338
|
-
belongs_to :parent_model
|
1339
|
-
acts_as_paranoid
|
1340
|
-
end
|
1341
|
-
|
1342
|
-
class NotParanoidModelWithBelong < ActiveRecord::Base
|
1343
|
-
belongs_to :paranoid_model_with_has_one
|
1344
|
-
end
|
1345
|
-
|
1346
|
-
class NotParanoidModelWithBelongsAndAssocationNotSoftDestroyedValidator < NotParanoidModelWithBelong
|
1347
|
-
belongs_to :parent_model
|
1348
|
-
validates :parent_model, association_not_soft_destroyed: true
|
1349
|
-
end
|
1350
|
-
|
1351
|
-
class FlaggedModel < PlainModel
|
1352
|
-
acts_as_paranoid :flag_column => :is_deleted
|
1353
|
-
end
|
1354
|
-
|
1355
|
-
class FlaggedModelWithCustomIndex < PlainModel
|
1356
|
-
acts_as_paranoid :flag_column => :is_deleted, :indexed_column => :is_deleted
|
1357
|
-
end
|
1358
|
-
|
1359
|
-
class AsplodeModel < ActiveRecord::Base
|
1360
|
-
acts_as_paranoid
|
1361
|
-
before_destroy do |r|
|
1362
|
-
raise StandardError, 'ASPLODE!'
|
1363
|
-
end
|
1364
|
-
end
|
1365
|
-
|
1366
|
-
class NoConnectionModel < ActiveRecord::Base
|
1367
|
-
end
|
1368
|
-
|
1369
|
-
class PolymorphicModel < ActiveRecord::Base
|
1370
|
-
acts_as_paranoid
|
1371
|
-
belongs_to :parent, polymorphic: true
|
1372
|
-
end
|
1373
|
-
|
1374
|
-
module Namespaced
|
1375
|
-
def self.table_name_prefix
|
1376
|
-
"namespaced_"
|
1377
|
-
end
|
1378
|
-
|
1379
|
-
class ParanoidHasOne < ActiveRecord::Base
|
1380
|
-
acts_as_paranoid
|
1381
|
-
has_one :paranoid_belongs_to, dependent: :destroy
|
1382
|
-
end
|
1383
|
-
|
1384
|
-
class ParanoidBelongsTo < ActiveRecord::Base
|
1385
|
-
acts_as_paranoid
|
1386
|
-
belongs_to :paranoid_has_one
|
1387
|
-
end
|
1388
|
-
end
|