paranoia 2.2.1 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,
|