paranoia 2.2.1 → 2.3.0
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/.travis.yml +6 -6
- data/CHANGELOG.md +28 -3
- data/CODE_OF_CONDUCT.md +74 -0
- data/README.md +15 -0
- data/lib/paranoia.rb +46 -8
- data/lib/paranoia/version.rb +1 -1
- data/test/paranoia_test.rb +108 -20
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d592d028e0a4ad7c1909649973803af1ef85102
|
4
|
+
data.tar.gz: a4fb1bb5daec2bd6b61c4beaa9b2ce2d415a2661
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a7d46b3e08208ae25969ddfe75d30ed0651ac649f834dd1ccb872197ce22ef93427281ce5c396c96d36a95f52ba53e54b81910970cedcd1ecd65d040502e819
|
7
|
+
data.tar.gz: 86866ca4cfd172783fbf7c7363ece9c1aea905129e210b228a315a34f2d2d6f343d5bbdd95cf96dfd8b3aa6d6d52e5391d4c026a84434a2f53fd6d23d37db6ea
|
data/.travis.yml
CHANGED
@@ -2,25 +2,25 @@ sudo: false
|
|
2
2
|
language: ruby
|
3
3
|
cache: bundler
|
4
4
|
rvm:
|
5
|
-
- 2.1.10
|
6
5
|
- 2.2.6
|
7
6
|
- 2.3.3
|
7
|
+
- 2.4.1
|
8
8
|
- jruby-9.1.6.0
|
9
9
|
|
10
10
|
env:
|
11
11
|
matrix:
|
12
|
-
- RAILS='~> 4.1.16'
|
13
12
|
- RAILS='~> 4.2.7.1'
|
14
13
|
- RAILS='~> 5.0.0.1'
|
14
|
+
- RAILS='~> 5.1.0.rc1'
|
15
15
|
|
16
16
|
matrix:
|
17
17
|
exclude:
|
18
|
-
- env: RAILS='~> 5.
|
19
|
-
rvm: 2.
|
18
|
+
- env: RAILS='~> 5.1.0.rc1'
|
19
|
+
rvm: 2.2.6
|
20
20
|
allow_failures:
|
21
|
-
- env: RAILS='~> 4.1.16'
|
22
|
-
rvm: jruby-9.1.6.0
|
23
21
|
- env: RAILS='~> 4.2.7.1'
|
24
22
|
rvm: jruby-9.1.6.0
|
25
23
|
- env: RAILS='~> 5.0.0.1'
|
26
24
|
rvm: jruby-9.1.6.0
|
25
|
+
- env: RAILS='~> 5.1.0.rc1'
|
26
|
+
rvm: jruby-9.1.6.0
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,31 @@
|
|
1
1
|
# paranoia Changelog
|
2
2
|
|
3
|
-
## 2.
|
3
|
+
## 2.3.0 (2017-04-14)
|
4
|
+
|
5
|
+
* [#393](https://github.com/rubysherpas/paranoia/pull/393) Drop support for Rails 4.1 and begin supporting Rails 5.1.
|
6
|
+
|
7
|
+
[Miklós Fazekas (@mfazekas)](https://github.com/mfazekas)
|
8
|
+
|
9
|
+
* [#391](https://github.com/rubysherpas/paranoia/pull/391) Use Contributor Covenant Version 1.4
|
10
|
+
|
11
|
+
[Ben A. Morgan (@BenMorganIO)](https://github.com/BenMorganIO)
|
12
|
+
|
13
|
+
* [#390](https://github.com/rubysherpas/paranoia/pull/390) Fix counter cache with double destroy, really_destroy, and restore
|
14
|
+
|
15
|
+
[Chris Oliver (@excid3)](https://github.com/excid3)
|
16
|
+
|
17
|
+
* [#389](https://github.com/rubysherpas/paranoia/pull/389) Added association not soft destroyed validator
|
18
|
+
|
19
|
+
_Fixes [#380](https://github.com/rubysherpas/paranoia/issues/380)_
|
20
|
+
|
21
|
+
[Edward Poot (@edwardmp)](https://github.com/edwardmp)
|
22
|
+
|
23
|
+
* [#383](https://github.com/rubysherpas/paranoia/pull/383) Add recovery window feature
|
24
|
+
|
25
|
+
_Fixes [#359](https://github.com/rubysherpas/paranoia/issues/359)_
|
26
|
+
|
27
|
+
[Andrzej Piątyszek (@konto-andrzeja)](https://github.com/konto-andrzeja)
|
28
|
+
|
4
29
|
|
5
30
|
## 2.2.1 (2017-02-15)
|
6
31
|
|
@@ -46,7 +71,7 @@
|
|
46
71
|
|
47
72
|
* `#destroyed?` is no longer overridden. Use `#paranoia_destroyed?` for the existing behaviour. [Washington Luiz](https://github.com/huoxito)
|
48
73
|
* `#persisted?` is no longer overridden.
|
49
|
-
* ActiveRecord 4.0 no longer has `#destroy!` as an alias for `#really_destroy
|
74
|
+
* ActiveRecord 4.0 no longer has `#destroy!` as an alias for `#really_destroy!`.
|
50
75
|
* `#destroy` will now raise an exception if called on a readonly record.
|
51
76
|
* `#destroy` on a hard deleted record is now a successful noop.
|
52
77
|
* `#destroy` on a new record will set deleted_at (previously this raised an error)
|
@@ -54,7 +79,7 @@
|
|
54
79
|
|
55
80
|
### Bug Fixes
|
56
81
|
|
57
|
-
* Calling `#destroy` twice will not hard-delete records. Use `#really_destroy
|
82
|
+
* Calling `#destroy` twice will not hard-delete records. Use `#really_destroy!` if this is desired.
|
58
83
|
* Fix errors on non-paranoid has_one dependent associations
|
59
84
|
|
60
85
|
## 2.0.5 (2015-01-22)
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at ben@benmorgan.io. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/README.md
CHANGED
@@ -181,6 +181,21 @@ Client.restore(id, :recursive => true)
|
|
181
181
|
client.restore(:recursive => true)
|
182
182
|
```
|
183
183
|
|
184
|
+
If you want to restore a record and only those dependently destroyed associated records that were deleted within 2 minutes of the object upon which they depend:
|
185
|
+
|
186
|
+
``` ruby
|
187
|
+
Client.restore(id, :recursive => true. :recovery_window => 2.minutes)
|
188
|
+
# or
|
189
|
+
client.restore(:recursive => true, :recovery_window => 2.minutes)
|
190
|
+
```
|
191
|
+
|
192
|
+
Note that by default paranoia will not prevent that a soft destroyed object can't be associated with another object of a different model.
|
193
|
+
A Rails validator is provided should you require this functionality:
|
194
|
+
``` ruby
|
195
|
+
validates :some_assocation, association_not_soft_destroyed: true
|
196
|
+
```
|
197
|
+
This validator makes sure that `some_assocation` is not soft destroyed. If the object is soft destroyed the main object is rendered invalid and an validation error is added.
|
198
|
+
|
184
199
|
For more information, please look at the tests.
|
185
200
|
|
186
201
|
#### About indexes:
|
data/lib/paranoia.rb
CHANGED
@@ -76,6 +76,7 @@ module Paranoia
|
|
76
76
|
def destroy
|
77
77
|
transaction do
|
78
78
|
run_callbacks(:destroy) do
|
79
|
+
@_disable_counter_cache = deleted?
|
79
80
|
result = delete
|
80
81
|
next result unless result && ActiveRecord::VERSION::STRING >= '4.2'
|
81
82
|
each_counter_cached_associations do |association|
|
@@ -84,6 +85,7 @@ module Paranoia
|
|
84
85
|
next unless send(association.reflection.name)
|
85
86
|
association.decrement_counters
|
86
87
|
end
|
88
|
+
@_disable_counter_cache = false
|
87
89
|
result
|
88
90
|
end
|
89
91
|
end
|
@@ -105,14 +107,22 @@ module Paranoia
|
|
105
107
|
def restore!(opts = {})
|
106
108
|
self.class.transaction do
|
107
109
|
run_callbacks(:restore) do
|
110
|
+
recovery_window_range = get_recovery_window_range(opts)
|
108
111
|
# Fixes a bug where the build would error because attributes were frozen.
|
109
112
|
# This only happened on Rails versions earlier than 4.1.
|
110
113
|
noop_if_frozen = ActiveRecord.version < Gem::Version.new("4.1")
|
111
|
-
if (noop_if_frozen && !@attributes.frozen?) || !noop_if_frozen
|
114
|
+
if within_recovery_window?(recovery_window_range) && ((noop_if_frozen && !@attributes.frozen?) || !noop_if_frozen)
|
115
|
+
@_disable_counter_cache = !deleted?
|
112
116
|
write_attribute paranoia_column, paranoia_sentinel_value
|
113
117
|
update_columns(paranoia_restore_attributes)
|
118
|
+
each_counter_cached_associations do |association|
|
119
|
+
if send(association.reflection.name)
|
120
|
+
association.increment_counters
|
121
|
+
end
|
122
|
+
end
|
123
|
+
@_disable_counter_cache = false
|
114
124
|
end
|
115
|
-
restore_associated_records if opts[:recursive]
|
125
|
+
restore_associated_records(recovery_window_range) if opts[:recursive]
|
116
126
|
end
|
117
127
|
end
|
118
128
|
|
@@ -120,6 +130,17 @@ module Paranoia
|
|
120
130
|
end
|
121
131
|
alias :restore :restore!
|
122
132
|
|
133
|
+
def get_recovery_window_range(opts)
|
134
|
+
return opts[:recovery_window_range] if opts[:recovery_window_range]
|
135
|
+
return unless opts[:recovery_window]
|
136
|
+
(deleted_at - opts[:recovery_window]..deleted_at + opts[:recovery_window])
|
137
|
+
end
|
138
|
+
|
139
|
+
def within_recovery_window?(recovery_window_range)
|
140
|
+
return true unless recovery_window_range
|
141
|
+
recovery_window_range.cover?(deleted_at)
|
142
|
+
end
|
143
|
+
|
123
144
|
def paranoia_destroyed?
|
124
145
|
send(paranoia_column) != paranoia_sentinel_value
|
125
146
|
end
|
@@ -128,6 +149,7 @@ module Paranoia
|
|
128
149
|
def really_destroy!
|
129
150
|
transaction do
|
130
151
|
run_callbacks(:real_destroy) do
|
152
|
+
@_disable_counter_cache = deleted?
|
131
153
|
dependent_reflections = self.class.reflections.select do |name, reflection|
|
132
154
|
reflection.options[:dependent] == :destroy
|
133
155
|
end
|
@@ -151,6 +173,10 @@ module Paranoia
|
|
151
173
|
|
152
174
|
private
|
153
175
|
|
176
|
+
def each_counter_cached_associations
|
177
|
+
!@_disable_counter_cache && defined?(super) ? super : []
|
178
|
+
end
|
179
|
+
|
154
180
|
def paranoia_restore_attributes
|
155
181
|
{
|
156
182
|
paranoia_column => paranoia_sentinel_value
|
@@ -169,7 +195,7 @@ module Paranoia
|
|
169
195
|
|
170
196
|
# restore associated records that have been soft deleted when
|
171
197
|
# we called #destroy
|
172
|
-
def restore_associated_records
|
198
|
+
def restore_associated_records(recovery_window_range = nil)
|
173
199
|
destroyed_associations = self.class.reflect_on_all_associations.select do |association|
|
174
200
|
association.options[:dependent] == :destroy
|
175
201
|
end
|
@@ -180,9 +206,11 @@ module Paranoia
|
|
180
206
|
unless association_data.nil?
|
181
207
|
if association_data.paranoid?
|
182
208
|
if association.collection?
|
183
|
-
association_data.only_deleted.each
|
209
|
+
association_data.only_deleted.each do |record|
|
210
|
+
record.restore(:recursive => true, :recovery_window_range => recovery_window_range)
|
211
|
+
end
|
184
212
|
else
|
185
|
-
association_data.restore(:recursive => true)
|
213
|
+
association_data.restore(:recursive => true, :recovery_window_range => recovery_window_range)
|
186
214
|
end
|
187
215
|
end
|
188
216
|
end
|
@@ -200,7 +228,8 @@ module Paranoia
|
|
200
228
|
|
201
229
|
association_class = association_class_name.constantize
|
202
230
|
if association_class.paranoid?
|
203
|
-
association_class.only_deleted.where(association_find_conditions).first
|
231
|
+
association_class.only_deleted.where(association_find_conditions).first
|
232
|
+
.try!(:restore, recursive: true, :recovery_window_range => recovery_window_range)
|
204
233
|
end
|
205
234
|
end
|
206
235
|
end
|
@@ -269,8 +298,8 @@ require 'paranoia/rspec' if defined? RSpec
|
|
269
298
|
module ActiveRecord
|
270
299
|
module Validations
|
271
300
|
module UniquenessParanoiaValidator
|
272
|
-
def build_relation(klass,
|
273
|
-
relation = super
|
301
|
+
def build_relation(klass, *args)
|
302
|
+
relation = super
|
274
303
|
return relation unless klass.respond_to?(:paranoia_column)
|
275
304
|
arel_paranoia_scope = klass.arel_table[klass.paranoia_column].eq(klass.paranoia_sentinel_value)
|
276
305
|
if ActiveRecord::VERSION::STRING >= "5.0"
|
@@ -284,5 +313,14 @@ module ActiveRecord
|
|
284
313
|
class UniquenessValidator < ActiveModel::EachValidator
|
285
314
|
prepend UniquenessParanoiaValidator
|
286
315
|
end
|
316
|
+
|
317
|
+
class AssociationNotSoftDestroyedValidator < ActiveModel::EachValidator
|
318
|
+
def validate_each(record, attribute, value)
|
319
|
+
# if association is soft destroyed, add an error
|
320
|
+
if value.present? && value.deleted?
|
321
|
+
record.errors[attribute] << 'has been soft-deleted'
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
287
325
|
end
|
288
326
|
end
|
data/lib/paranoia/version.rb
CHANGED
data/test/paranoia_test.rb
CHANGED
@@ -21,6 +21,7 @@ def setup!
|
|
21
21
|
'paranoid_model_with_foreign_key_belongs' => 'parent_model_id INTEGER, deleted_at DATETIME, has_one_foreign_key_id INTEGER',
|
22
22
|
'paranoid_model_with_timestamps' => 'parent_model_id INTEGER, created_at DATETIME, updated_at DATETIME, deleted_at DATETIME',
|
23
23
|
'not_paranoid_model_with_belongs' => 'parent_model_id INTEGER, paranoid_model_with_has_one_id INTEGER',
|
24
|
+
'not_paranoid_model_with_belongs_and_assocation_not_soft_destroyed_validator' => 'parent_model_id INTEGER, paranoid_model_with_has_one_id INTEGER',
|
24
25
|
'paranoid_model_with_has_one_and_builds' => 'parent_model_id INTEGER, color VARCHAR(32), deleted_at DATETIME, has_one_foreign_key_id INTEGER',
|
25
26
|
'featureful_models' => 'deleted_at DATETIME, name VARCHAR(32)',
|
26
27
|
'plain_models' => 'deleted_at DATETIME',
|
@@ -117,9 +118,9 @@ class ParanoiaTest < test_framework
|
|
117
118
|
model.remove_called_variables # clear called callback flags
|
118
119
|
model.destroy
|
119
120
|
|
120
|
-
|
121
|
-
|
122
|
-
|
121
|
+
assert_nil model.instance_variable_get(:@update_callback_called)
|
122
|
+
assert_nil model.instance_variable_get(:@save_callback_called)
|
123
|
+
assert_nil model.instance_variable_get(:@validate_called)
|
123
124
|
|
124
125
|
assert model.instance_variable_get(:@destroy_callback_called)
|
125
126
|
assert model.instance_variable_get(:@after_destroy_callback_called)
|
@@ -133,12 +134,12 @@ class ParanoiaTest < test_framework
|
|
133
134
|
model.remove_called_variables # clear called callback flags
|
134
135
|
model.delete
|
135
136
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
137
|
+
assert_nil model.instance_variable_get(:@update_callback_called)
|
138
|
+
assert_nil model.instance_variable_get(:@save_callback_called)
|
139
|
+
assert_nil model.instance_variable_get(:@validate_called)
|
140
|
+
assert_nil model.instance_variable_get(:@destroy_callback_called)
|
141
|
+
assert_nil model.instance_variable_get(:@after_destroy_callback_called)
|
142
|
+
assert_nil model.instance_variable_get(:@after_commit_callback_called)
|
142
143
|
end
|
143
144
|
|
144
145
|
def test_delete_in_transaction_behavior_for_plain_models_callbacks
|
@@ -149,11 +150,11 @@ class ParanoiaTest < test_framework
|
|
149
150
|
model.delete
|
150
151
|
end
|
151
152
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
153
|
+
assert_nil model.instance_variable_get(:@update_callback_called)
|
154
|
+
assert_nil model.instance_variable_get(:@save_callback_called)
|
155
|
+
assert_nil model.instance_variable_get(:@validate_called)
|
156
|
+
assert_nil model.instance_variable_get(:@destroy_callback_called)
|
157
|
+
assert_nil model.instance_variable_get(:@after_destroy_callback_called)
|
157
158
|
assert model.instance_variable_get(:@after_commit_callback_called)
|
158
159
|
end
|
159
160
|
|
@@ -226,7 +227,7 @@ class ParanoiaTest < test_framework
|
|
226
227
|
end
|
227
228
|
|
228
229
|
def test_default_sentinel_value
|
229
|
-
|
230
|
+
assert_nil ParanoidModel.paranoia_sentinel_value
|
230
231
|
end
|
231
232
|
|
232
233
|
def test_without_default_scope_option
|
@@ -375,7 +376,7 @@ class ParanoiaTest < test_framework
|
|
375
376
|
model = CallbackModel.new
|
376
377
|
model.save
|
377
378
|
model.delete
|
378
|
-
|
379
|
+
assert_nil model.instance_variable_get(:@destroy_callback_called)
|
379
380
|
end
|
380
381
|
|
381
382
|
def test_destroy_behavior_for_callbacks
|
@@ -580,6 +581,38 @@ class ParanoiaTest < test_framework
|
|
580
581
|
refute c.paranoia_destroyed?
|
581
582
|
end
|
582
583
|
|
584
|
+
def test_restore_with_associations_using_recovery_window
|
585
|
+
parent = ParentModel.create
|
586
|
+
first_child = parent.very_related_models.create
|
587
|
+
second_child = parent.very_related_models.create
|
588
|
+
|
589
|
+
parent.destroy
|
590
|
+
second_child.update(deleted_at: parent.deleted_at + 11.minutes)
|
591
|
+
|
592
|
+
parent.restore!(:recursive => true)
|
593
|
+
assert_equal true, parent.deleted_at.nil?
|
594
|
+
assert_equal true, first_child.reload.deleted_at.nil?
|
595
|
+
assert_equal true, second_child.reload.deleted_at.nil?
|
596
|
+
|
597
|
+
parent.destroy
|
598
|
+
second_child.update(deleted_at: parent.deleted_at + 11.minutes)
|
599
|
+
|
600
|
+
parent.restore(:recursive => true, :recovery_window => 10.minutes)
|
601
|
+
assert_equal true, parent.deleted_at.nil?
|
602
|
+
assert_equal true, first_child.reload.deleted_at.nil?
|
603
|
+
assert_equal false, second_child.reload.deleted_at.nil?
|
604
|
+
|
605
|
+
second_child.restore
|
606
|
+
parent.destroy
|
607
|
+
first_child.update(deleted_at: parent.deleted_at - 11.minutes)
|
608
|
+
second_child.update(deleted_at: parent.deleted_at - 9.minutes)
|
609
|
+
|
610
|
+
ParentModel.restore(parent.id, :recursive => true, :recovery_window => 10.minutes)
|
611
|
+
assert_equal true, parent.reload.deleted_at.nil?
|
612
|
+
assert_equal false, first_child.reload.deleted_at.nil?
|
613
|
+
assert_equal true, second_child.reload.deleted_at.nil?
|
614
|
+
end
|
615
|
+
|
583
616
|
def test_restore_with_associations
|
584
617
|
parent = ParentModel.create
|
585
618
|
first_child = parent.very_related_models.create
|
@@ -916,8 +949,8 @@ class ParanoiaTest < test_framework
|
|
916
949
|
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
917
950
|
related_model = parent_model_with_counter_cache_column.related_models.create
|
918
951
|
|
919
|
-
|
920
|
-
|
952
|
+
assert_nil related_model.instance_variable_get(:@after_destroy_callback_called)
|
953
|
+
assert_nil related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
|
921
954
|
|
922
955
|
related_model.destroy
|
923
956
|
|
@@ -932,6 +965,18 @@ class ParanoiaTest < test_framework
|
|
932
965
|
related.valid?
|
933
966
|
end
|
934
967
|
|
968
|
+
def test_assocation_not_soft_destroyed_validator
|
969
|
+
notParanoidModel = NotParanoidModelWithBelongsAndAssocationNotSoftDestroyedValidator.create
|
970
|
+
parentModel = ParentModel.create
|
971
|
+
assert notParanoidModel.valid?
|
972
|
+
|
973
|
+
notParanoidModel.parent_model = parentModel
|
974
|
+
assert notParanoidModel.valid?
|
975
|
+
parentModel.destroy
|
976
|
+
assert !notParanoidModel.valid?
|
977
|
+
assert notParanoidModel.errors.full_messages.include? "Parent model has been soft-deleted"
|
978
|
+
end
|
979
|
+
|
935
980
|
# TODO: find a fix for Rails 4.1
|
936
981
|
if ActiveRecord::VERSION::STRING !~ /\A4\.1/
|
937
982
|
def test_counter_cache_column_update_on_really_destroy
|
@@ -950,14 +995,52 @@ class ParanoiaTest < test_framework
|
|
950
995
|
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
951
996
|
related_model = parent_model_with_counter_cache_column.related_models.create
|
952
997
|
|
953
|
-
|
954
|
-
|
998
|
+
assert_nil related_model.instance_variable_get(:@after_destroy_callback_called)
|
999
|
+
assert_nil related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
|
955
1000
|
|
956
1001
|
related_model.really_destroy!
|
957
1002
|
|
958
1003
|
assert related_model.instance_variable_get(:@after_destroy_callback_called)
|
959
1004
|
assert related_model.instance_variable_get(:@after_commit_on_destroy_callback_called)
|
960
1005
|
end
|
1006
|
+
|
1007
|
+
def test_counter_cache_column_on_double_destroy
|
1008
|
+
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1009
|
+
related_model = parent_model_with_counter_cache_column.related_models.create
|
1010
|
+
|
1011
|
+
related_model.destroy
|
1012
|
+
related_model.destroy
|
1013
|
+
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
def test_counter_cache_column_on_double_restore
|
1017
|
+
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1018
|
+
related_model = parent_model_with_counter_cache_column.related_models.create
|
1019
|
+
|
1020
|
+
related_model.destroy
|
1021
|
+
related_model.restore
|
1022
|
+
related_model.restore
|
1023
|
+
assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
def test_counter_cache_column_on_destroy_and_really_destroy
|
1027
|
+
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1028
|
+
related_model = parent_model_with_counter_cache_column.related_models.create
|
1029
|
+
|
1030
|
+
related_model.destroy
|
1031
|
+
related_model.really_destroy!
|
1032
|
+
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
def test_counter_cache_column_on_restore
|
1036
|
+
parent_model_with_counter_cache_column = ParentModelWithCounterCacheColumn.create
|
1037
|
+
related_model = parent_model_with_counter_cache_column.related_models.create
|
1038
|
+
|
1039
|
+
related_model.destroy
|
1040
|
+
assert_equal 0, parent_model_with_counter_cache_column.reload.related_models_count
|
1041
|
+
related_model.restore
|
1042
|
+
assert_equal 1, parent_model_with_counter_cache_column.reload.related_models_count
|
1043
|
+
end
|
961
1044
|
end
|
962
1045
|
|
963
1046
|
private
|
@@ -1233,6 +1316,11 @@ class NotParanoidModelWithBelong < ActiveRecord::Base
|
|
1233
1316
|
belongs_to :paranoid_model_with_has_one
|
1234
1317
|
end
|
1235
1318
|
|
1319
|
+
class NotParanoidModelWithBelongsAndAssocationNotSoftDestroyedValidator < NotParanoidModelWithBelong
|
1320
|
+
belongs_to :parent_model
|
1321
|
+
validates :parent_model, association_not_soft_destroyed: true
|
1322
|
+
end
|
1323
|
+
|
1236
1324
|
class FlaggedModel < PlainModel
|
1237
1325
|
acts_as_paranoid :flag_column => :is_deleted
|
1238
1326
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paranoia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- radarlistener@gmail.com
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- ".gitignore"
|
77
77
|
- ".travis.yml"
|
78
78
|
- CHANGELOG.md
|
79
|
+
- CODE_OF_CONDUCT.md
|
79
80
|
- CONTRIBUTING.md
|
80
81
|
- Gemfile
|
81
82
|
- LICENSE
|
@@ -106,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
107
|
version: 1.3.6
|
107
108
|
requirements: []
|
108
109
|
rubyforge_project:
|
109
|
-
rubygems_version: 2.6.
|
110
|
+
rubygems_version: 2.6.11
|
110
111
|
signing_key:
|
111
112
|
specification_version: 4
|
112
113
|
summary: Paranoia is a re-implementation of acts_as_paranoid for Rails 3, 4, and 5,
|