acts_as_paranoid 0.6.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +128 -0
- data/README.md +154 -56
- data/lib/acts_as_paranoid.rb +34 -31
- data/lib/acts_as_paranoid/associations.rb +21 -17
- data/lib/acts_as_paranoid/core.rb +139 -58
- data/lib/acts_as_paranoid/relation.rb +2 -0
- data/lib/acts_as_paranoid/validations.rb +8 -69
- data/lib/acts_as_paranoid/version.rb +3 -1
- data/test/test_associations.rb +157 -38
- data/test/test_core.rb +269 -48
- data/test/test_default_scopes.rb +7 -6
- data/test/test_helper.rb +155 -62
- data/test/test_inheritance.rb +3 -1
- data/test/test_relations.rb +18 -10
- data/test/test_validations.rb +9 -7
- metadata +92 -33
- data/lib/acts_as_paranoid/preloader_association.rb +0 -16
- data/test/test_preloader_association.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '096b348280798fe5ac4770a6c57bdb0731d2c5df9e7d361551cf065fe71f0b56'
|
4
|
+
data.tar.gz: 3d923644ebb1ccb3e06d9c04d8a0797f1677fcec880a188dd04ec8b19c9a957a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e677d8e734d9c6d72fd68feaad170f928fb159ea6a90e400632ce8365f8120a991eae46508bb04d641117fa2e24d3e38e9df6699c1d70b2cd994a4cf85c49379
|
7
|
+
data.tar.gz: b58a42cbf60696baffac255deb673476e5e339dbbe4bd1681959442ca2fc33a51f6d2e146755fc8f79539976d47c6244927969c82a86fdb70a553de44281e512
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# CHANGELOG
|
2
|
+
|
3
|
+
Notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
## 0.7.1
|
6
|
+
|
7
|
+
* Support Rails 6.1 ([#191], by [Matijs van Zuijlen][mvz])
|
8
|
+
* Support `belongs_to` with both `:touch` and `:counter_cache` options ([#208],
|
9
|
+
by [Matijs van Zuijlen][mvz] with [Paul Druziak][pauldruziak])
|
10
|
+
* Support Ruby 3.0 ([#209], by [Matijs van Zuijlen][mvz])
|
11
|
+
|
12
|
+
## 0.7.0
|
13
|
+
|
14
|
+
### Breaking changes
|
15
|
+
|
16
|
+
* Support Rails 5.2+ only ([#126], by [Daniel Rice][danielricecodes])
|
17
|
+
* Update set of supported rubies to 2.4-2.7 ([#144], [#173] by [Matijs van Zuijlen][mvz])
|
18
|
+
|
19
|
+
### Improvements
|
20
|
+
|
21
|
+
* Handle `with_deleted` association option as a scope ([#147], by [Matijs van Zuijlen][mvz])
|
22
|
+
* Simplify validation override ([#158], by [Matijs van Zuijlen][mvz])
|
23
|
+
* Use correct unscope syntax so unscope works on Rails Edge ([#160],
|
24
|
+
by [Matijs van Zuijlen][mvz])
|
25
|
+
* Fix ruby 2.7 keyword argument deprecation warning ([#161], by [Jon Riddle][wtfspm])
|
26
|
+
|
27
|
+
### Documentation
|
28
|
+
|
29
|
+
* Document save after destroy behavior ([#146], by [Matijs van Zuijlen][mvz])
|
30
|
+
* Update version number instructions for installing gem ([#164],
|
31
|
+
by [Kevin McAlear][kevinmcalear])
|
32
|
+
* Add example with `destroyed_fully?` and `deleted_fully?` to the readme ([#170],
|
33
|
+
by [Kiril Mitov][thebravoman])
|
34
|
+
|
35
|
+
### Internal
|
36
|
+
|
37
|
+
* Improve code quality using RuboCop ([#148], [#152], [#159], [#163], [#171] and [#173],
|
38
|
+
by [Matijs van Zuijlen][mvz])
|
39
|
+
* Measure code coverage using SimpleCov ([#150] and [#175] by [Matijs van Zuijlen][mvz])
|
40
|
+
* Silence warnings emitted during tests ([#156], by [Matijs van Zuijlen][mvz])
|
41
|
+
* Make rake tasks more robust and intuitive ([#157], by [Matijs van Zuijlen][mvz])
|
42
|
+
|
43
|
+
## 0.6.3
|
44
|
+
|
45
|
+
* Update Travis CI configuration ([#137], by [Matijs van Zuijlen][mvz])
|
46
|
+
* Add predicate to check if record was soft deleted or hard deleted ([#136],
|
47
|
+
by [Aymeric Le Dorze][aymeric-ledorze])
|
48
|
+
* Add support for recover! method ([#75], by [vinoth][avinoth])
|
49
|
+
* Fix a record being dirty after destroying it ([#135], by
|
50
|
+
[Aymeric Le Dorze][aymeric-ledorze])
|
51
|
+
|
52
|
+
## 0.6.2
|
53
|
+
|
54
|
+
* Prevent recovery of non-deleted records
|
55
|
+
([#133], by [Mary Beliveau][marycodes2] and [Valerie Woolard][valeriecodes])
|
56
|
+
* Allow model to set `table_name` after `acts_as_paranoid` macro
|
57
|
+
([#131], by [Alex Wheeler][AlexWheeler])
|
58
|
+
* Make counter cache work with a custom column name and with optional
|
59
|
+
associations ([#123], by [Ned Campion][nedcampion])
|
60
|
+
|
61
|
+
## 0.6.1
|
62
|
+
|
63
|
+
* Add support for Rails 6 ([#124], by [Daniel Rice][danielricecodes],
|
64
|
+
[Josh Bryant][jbryant92], and [Romain Alexandre][RomainAlexandre])
|
65
|
+
* Add support for incrementing and decrementing counter cache columns on
|
66
|
+
associated objects ([#119], by [Dimitar Lukanov][shadydealer])
|
67
|
+
* Add `:double_tap_destroys_fully` option, with default `true` ([#116],
|
68
|
+
by [Michael Riviera][ri4a])
|
69
|
+
* Officially support Ruby 2.6 ([#114], by [Matijs van Zuijlen][mvz])
|
70
|
+
|
71
|
+
## 0.6.0 and earlier
|
72
|
+
|
73
|
+
(To be added)
|
74
|
+
|
75
|
+
<!-- Contributors -->
|
76
|
+
|
77
|
+
[AlexWheeler]: https://github.com/AlexWheeler
|
78
|
+
[RomainAlexandre]: https://github.com/RomainAlexandre
|
79
|
+
[avinoth]: https://github.com/avinoth
|
80
|
+
[aymeric-ledorze]: https://github.com/aymeric-ledorze
|
81
|
+
[danielricecodes]: https://github.com/danielricecodes
|
82
|
+
[jbryant92]: https://github.com/jbryant92
|
83
|
+
[kevinmcalear]: https://github.com/kevinmcalear
|
84
|
+
[marycodes2]: https://github.com/marycodes2
|
85
|
+
[mvz]: https://github.com/mvz
|
86
|
+
[nedcampion]: https://github.com/nedcampion
|
87
|
+
[ri4a]: https://github.com/ri4a
|
88
|
+
[pauldruziak]: https://github.com/pauldruziak
|
89
|
+
[shadydealer]: https://github.com/shadydealer
|
90
|
+
[thebravoman]: https://github.com/thebravoman
|
91
|
+
[valeriecodes]: https://github.com/valeriecodes
|
92
|
+
[wtfspm]: https://github.com/wtfspm
|
93
|
+
|
94
|
+
<!-- issues & pull requests -->
|
95
|
+
|
96
|
+
[#209]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/209
|
97
|
+
[#208]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/208
|
98
|
+
[#191]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/191
|
99
|
+
[#175]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/175
|
100
|
+
[#173]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/173
|
101
|
+
[#171]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/171
|
102
|
+
[#170]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/170
|
103
|
+
[#164]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/164
|
104
|
+
[#163]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/163
|
105
|
+
[#161]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/161
|
106
|
+
[#160]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/160
|
107
|
+
[#159]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/159
|
108
|
+
[#158]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/158
|
109
|
+
[#157]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/157
|
110
|
+
[#156]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/156
|
111
|
+
[#152]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/152
|
112
|
+
[#150]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/150
|
113
|
+
[#148]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/148
|
114
|
+
[#147]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/147
|
115
|
+
[#146]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/146
|
116
|
+
[#144]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/144
|
117
|
+
[#137]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/137
|
118
|
+
[#136]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/136
|
119
|
+
[#135]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/135
|
120
|
+
[#133]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/133
|
121
|
+
[#131]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/131
|
122
|
+
[#126]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/126
|
123
|
+
[#124]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/124
|
124
|
+
[#123]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/123
|
125
|
+
[#119]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/119
|
126
|
+
[#116]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/116
|
127
|
+
[#114]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/114
|
128
|
+
[#75]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/75
|
data/README.md
CHANGED
@@ -9,35 +9,38 @@ recoverable later.
|
|
9
9
|
|
10
10
|
## Support
|
11
11
|
|
12
|
-
**This branch targets Rails
|
12
|
+
**This branch targets Rails 5.2+ and Ruby 2.4+ only**
|
13
13
|
|
14
|
-
If you're working with
|
15
|
-
require an older version of the
|
14
|
+
If you're working with Rails 5.1 and earlier, or with Ruby 2.3 or earlier,
|
15
|
+
please switch to the corresponding branch or require an older version of the
|
16
|
+
`acts_as_paranoid` gem.
|
16
17
|
|
17
|
-
### Known issues
|
18
|
+
### Known issues
|
18
19
|
|
19
|
-
* Using acts_as_paranoid and ActiveStorage on the same model
|
20
|
+
* Using `acts_as_paranoid` and ActiveStorage on the same model
|
20
21
|
[leads to a SystemStackError](https://github.com/ActsAsParanoid/acts_as_paranoid/issues/103).
|
21
|
-
* You cannot directly create a model in a deleted state
|
22
|
+
* You cannot directly create a model in a deleted state, or update a model
|
23
|
+
after it's been deleted.
|
22
24
|
|
23
25
|
## Usage
|
24
26
|
|
25
27
|
#### Install gem:
|
26
28
|
|
27
|
-
```
|
28
|
-
gem 'acts_as_paranoid', '~> 0.
|
29
|
+
```ruby
|
30
|
+
gem 'acts_as_paranoid', '~> 0.7.0'
|
29
31
|
```
|
30
|
-
|
32
|
+
|
33
|
+
```shell
|
31
34
|
bundle install
|
32
35
|
```
|
33
36
|
|
34
37
|
#### Create migration
|
35
38
|
|
36
|
-
```
|
39
|
+
```shell
|
37
40
|
bin/rails generate migration AddDeletedAtToParanoiac deleted_at:datetime:index
|
38
41
|
```
|
39
42
|
|
40
|
-
#### Enable ActsAsParanoid
|
43
|
+
#### Enable ActsAsParanoid
|
41
44
|
|
42
45
|
```ruby
|
43
46
|
class Paranoiac < ActiveRecord::Base
|
@@ -45,31 +48,42 @@ class Paranoiac < ActiveRecord::Base
|
|
45
48
|
end
|
46
49
|
```
|
47
50
|
|
48
|
-
|
49
|
-
|
50
|
-
- `:column => 'deleted_at'`
|
51
|
-
- `:column_type => 'time'`
|
51
|
+
By default, ActsAsParanoid assumes a record's *deletion* is stored in a
|
52
|
+
`datetime` column called `deleted_at`.
|
52
53
|
|
53
54
|
### Options
|
54
55
|
|
55
|
-
If you are using a different column name and type to store a record's
|
56
|
+
If you are using a different column name and type to store a record's
|
57
|
+
*deletion*, you can specify them as follows:
|
56
58
|
|
57
|
-
-
|
58
|
-
-
|
59
|
+
- `column: 'deleted'`
|
60
|
+
- `column_type: 'boolean'`
|
59
61
|
|
60
|
-
While *column* can be anything (as long as it exists in your database), *type*
|
62
|
+
While *column* can be anything (as long as it exists in your database), *type*
|
63
|
+
is restricted to:
|
61
64
|
|
62
65
|
- `boolean`
|
63
66
|
- `time` or
|
64
67
|
- `string`
|
65
68
|
|
66
|
-
|
69
|
+
Note that the `time` type corresponds to the database column type `datetime`
|
70
|
+
in your Rails migrations and schema.
|
67
71
|
|
68
|
-
If your column type is a `
|
72
|
+
If your column type is a `string`, you can also specify which value to use when
|
73
|
+
marking an object as deleted by passing `:deleted_value` (default is
|
74
|
+
"deleted"). Any records with a non-matching value in this column will be
|
75
|
+
treated normally, i.e., as not deleted.
|
76
|
+
|
77
|
+
If your column type is a `boolean`, it is possible to specify `allow_nulls`
|
78
|
+
option which is `true` by default. When set to `false`, entities that have
|
79
|
+
`false` value in this column will be considered not deleted, and those which
|
80
|
+
have `true` will be considered deleted. When `true` everything that has a
|
81
|
+
not-null value will be considered deleted.
|
69
82
|
|
70
83
|
### Filtering
|
71
84
|
|
72
|
-
If a record is deleted by ActsAsParanoid, it won't be retrieved when accessing
|
85
|
+
If a record is deleted by ActsAsParanoid, it won't be retrieved when accessing
|
86
|
+
the database.
|
73
87
|
|
74
88
|
So, `Paranoiac.all` will **not** include the **deleted records**.
|
75
89
|
|
@@ -80,7 +94,8 @@ Paranoiac.only_deleted # retrieves only the deleted records
|
|
80
94
|
Paranoiac.with_deleted # retrieves all records, deleted or not
|
81
95
|
```
|
82
96
|
|
83
|
-
When using the default `column_type` of `'time'`, the following extra scopes
|
97
|
+
When using the default `column_type` of `'time'`, the following extra scopes
|
98
|
+
are provided:
|
84
99
|
|
85
100
|
```ruby
|
86
101
|
time = Time.now
|
@@ -100,20 +115,33 @@ In order to really delete a record, just use:
|
|
100
115
|
paranoiac.destroy_fully!
|
101
116
|
Paranoiac.delete_all!(conditions)
|
102
117
|
```
|
103
|
-
**NOTE:** The `.destroy!` method is still usable, but equivalent to `.destroy`. It just hides the object.
|
104
118
|
|
105
|
-
|
119
|
+
**NOTE:** The `.destroy!` method is still usable, but equivalent to `.destroy`.
|
120
|
+
It just hides the object.
|
121
|
+
|
122
|
+
Alternatively you can permanently delete a record by calling `destroy` or
|
123
|
+
`delete_all` on the object **twice**.
|
106
124
|
|
107
|
-
If a record was already deleted (hidden by `ActsAsParanoid`) and you delete it
|
125
|
+
If a record was already deleted (hidden by `ActsAsParanoid`) and you delete it
|
126
|
+
again, it will be removed from the database.
|
108
127
|
|
109
128
|
Take this example:
|
110
129
|
|
111
130
|
```ruby
|
112
131
|
p = Paranoiac.first
|
113
|
-
|
114
|
-
|
132
|
+
|
133
|
+
# does NOT delete the first record, just hides it
|
134
|
+
p.destroy
|
135
|
+
|
136
|
+
# deletes the first record from the database
|
137
|
+
Paranoiac.only_deleted.where(id: p.id).first.destroy
|
115
138
|
```
|
116
139
|
|
140
|
+
This behaviour can be disabled by setting the configuration option. In a future
|
141
|
+
version, `false` will be the default setting.
|
142
|
+
|
143
|
+
- `double_tap_destroys_fully: false`
|
144
|
+
|
117
145
|
### Recovery
|
118
146
|
|
119
147
|
Recovery is easy. Just invoke `recover` on it, like this:
|
@@ -122,34 +150,39 @@ Recovery is easy. Just invoke `recover` on it, like this:
|
|
122
150
|
Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover
|
123
151
|
```
|
124
152
|
|
125
|
-
All associations marked as
|
153
|
+
All associations marked as `dependent: :destroy` are also recursively recovered.
|
126
154
|
|
127
|
-
If you would like to disable this behavior, you can call `recover` with the
|
155
|
+
If you would like to disable this behavior, you can call `recover` with the
|
156
|
+
`recursive` option:
|
128
157
|
|
129
158
|
```ruby
|
130
|
-
Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover(:
|
159
|
+
Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover(recursive: false)
|
131
160
|
```
|
132
161
|
|
133
|
-
If you would like to change this default behavior for one model, you can use
|
162
|
+
If you would like to change this default behavior for one model, you can use
|
163
|
+
the `recover_dependent_associations` option
|
134
164
|
|
135
165
|
```ruby
|
136
166
|
class Paranoiac < ActiveRecord::Base
|
137
|
-
acts_as_paranoid :
|
167
|
+
acts_as_paranoid recover_dependent_associations: false
|
138
168
|
end
|
139
169
|
```
|
140
170
|
|
141
|
-
By default, dependent records will be recovered if they were deleted within 2
|
171
|
+
By default, dependent records will be recovered if they were deleted within 2
|
172
|
+
minutes of the object upon which they depend.
|
142
173
|
|
143
|
-
This restores the objects to the state before the recursive deletion without
|
174
|
+
This restores the objects to the state before the recursive deletion without
|
175
|
+
restoring other objects that were deleted earlier.
|
144
176
|
|
145
|
-
The behavior is only available when both parent and dependant are using
|
177
|
+
The behavior is only available when both parent and dependant are using
|
178
|
+
timestamp fields to mark deletion, which is the default behavior.
|
146
179
|
|
147
180
|
This window can be changed with the `dependent_recovery_window` option:
|
148
181
|
|
149
182
|
```ruby
|
150
183
|
class Paranoiac < ActiveRecord::Base
|
151
184
|
acts_as_paranoid
|
152
|
-
has_many :paranoids, :
|
185
|
+
has_many :paranoids, dependent: :destroy
|
153
186
|
end
|
154
187
|
|
155
188
|
class Paranoid < ActiveRecord::Base
|
@@ -157,18 +190,42 @@ class Paranoid < ActiveRecord::Base
|
|
157
190
|
|
158
191
|
# Paranoid objects will be recovered alongside Paranoic objects
|
159
192
|
# if they were deleted within 10 minutes of the Paranoic object
|
160
|
-
acts_as_paranoid :
|
193
|
+
acts_as_paranoid dependent_recovery_window: 10.minutes
|
161
194
|
end
|
162
195
|
```
|
163
196
|
|
164
197
|
or in the recover statement
|
165
198
|
|
166
199
|
```ruby
|
167
|
-
Paranoiac.only_deleted.where("name = ?", "not dead yet").first
|
200
|
+
Paranoiac.only_deleted.where("name = ?", "not dead yet").first
|
201
|
+
.recover(recovery_window: 30.seconds)
|
202
|
+
```
|
203
|
+
|
204
|
+
### recover!
|
205
|
+
|
206
|
+
You can invoke `recover!` if you wish to raise an error if the recovery fails.
|
207
|
+
The error generally stems from ActiveRecord.
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover!
|
211
|
+
# => ActiveRecord::RecordInvalid: Validation failed: Name already exists
|
212
|
+
```
|
213
|
+
|
214
|
+
Optionally, you may also raise the error by passing `raise_error: true` to the
|
215
|
+
`recover` method. This behaves the same as `recover!`.
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover(raise_error: true)
|
168
219
|
```
|
169
220
|
|
170
221
|
### Validation
|
171
|
-
|
222
|
+
|
223
|
+
ActiveRecord's built-in uniqueness validation does not account for records
|
224
|
+
deleted by ActsAsParanoid. If you want to check for uniqueness among
|
225
|
+
non-deleted records only, use the macro `validates_as_paranoid` in your model.
|
226
|
+
Then, instead of using `validates_uniqueness_of`, use
|
227
|
+
`validates_uniqueness_of_without_deleted`. This will keep deleted records from
|
228
|
+
counting against the uniqueness check.
|
172
229
|
|
173
230
|
```ruby
|
174
231
|
class Paranoiac < ActiveRecord::Base
|
@@ -177,10 +234,10 @@ class Paranoiac < ActiveRecord::Base
|
|
177
234
|
validates_uniqueness_of_without_deleted :name
|
178
235
|
end
|
179
236
|
|
180
|
-
p1 = Paranoiac.create(:
|
237
|
+
p1 = Paranoiac.create(name: 'foo')
|
181
238
|
p1.destroy
|
182
239
|
|
183
|
-
p2 = Paranoiac.new(:
|
240
|
+
p2 = Paranoiac.new(name: 'foo')
|
184
241
|
p2.valid? #=> true
|
185
242
|
p2.save
|
186
243
|
|
@@ -188,16 +245,34 @@ p1.recover #=> fails validation!
|
|
188
245
|
```
|
189
246
|
|
190
247
|
### Status
|
191
|
-
|
248
|
+
|
249
|
+
A paranoid object could be deleted or destroyed fully.
|
250
|
+
|
251
|
+
You can check if the object is deleted with the `deleted?` helper
|
252
|
+
|
253
|
+
```ruby
|
254
|
+
Paranoiac.create(name: 'foo').destroy
|
255
|
+
Paranoiac.with_deleted.first.deleted? #=> true
|
256
|
+
```
|
257
|
+
|
258
|
+
After the first call to `.destroy` the object is `deleted?`.
|
259
|
+
|
260
|
+
You can check if the object is fully destroyed with `destroyed_fully?` or `deleted_fully?`.
|
192
261
|
|
193
262
|
```ruby
|
194
|
-
Paranoiac.create(:
|
263
|
+
Paranoiac.create(name: 'foo').destroy
|
195
264
|
Paranoiac.with_deleted.first.deleted? #=> true
|
265
|
+
Paranoiac.with_deleted.first.destroyed_fully? #=> false
|
266
|
+
p1 = Paranoiac.with_deleted.first
|
267
|
+
p1.destroy # this fully destroys the object
|
268
|
+
p1.destroyed_fully? #=> true
|
269
|
+
p1.deleted_fully? #=> true
|
196
270
|
```
|
197
271
|
|
198
272
|
### Scopes
|
199
273
|
|
200
|
-
As you've probably guessed, `with_deleted` and `only_deleted` are scopes. You
|
274
|
+
As you've probably guessed, `with_deleted` and `only_deleted` are scopes. You
|
275
|
+
can, however, chain them freely with other scopes you might have.
|
201
276
|
|
202
277
|
For example:
|
203
278
|
|
@@ -216,10 +291,10 @@ You can work freely with scopes and it will just work:
|
|
216
291
|
```ruby
|
217
292
|
class Paranoiac < ActiveRecord::Base
|
218
293
|
acts_as_paranoid
|
219
|
-
scope :pretty, where(:
|
294
|
+
scope :pretty, where(pretty: true)
|
220
295
|
end
|
221
296
|
|
222
|
-
Paranoiac.create(:
|
297
|
+
Paranoiac.create(pretty: true)
|
223
298
|
|
224
299
|
Paranoiac.pretty.count #=> 1
|
225
300
|
Paranoiac.only_deleted.count #=> 0
|
@@ -236,11 +311,13 @@ Paranoiac.pretty.only_deleted.count #=> 1
|
|
236
311
|
|
237
312
|
Associations are also supported.
|
238
313
|
|
239
|
-
From the simplest behaviors you'd expect to more nifty things like the ones
|
314
|
+
From the simplest behaviors you'd expect to more nifty things like the ones
|
315
|
+
mentioned previously or the usage of the `:with_deleted` option with
|
316
|
+
`belongs_to`
|
240
317
|
|
241
318
|
```ruby
|
242
319
|
class Parent < ActiveRecord::Base
|
243
|
-
has_many :children, :
|
320
|
+
has_many :children, class_name: "ParanoiacChild"
|
244
321
|
end
|
245
322
|
|
246
323
|
class ParanoiacChild < ActiveRecord::Base
|
@@ -248,7 +325,8 @@ class ParanoiacChild < ActiveRecord::Base
|
|
248
325
|
belongs_to :parent
|
249
326
|
|
250
327
|
# You may need to provide a foreign_key like this
|
251
|
-
belongs_to :parent_including_deleted, :
|
328
|
+
belongs_to :parent_including_deleted, class_name: "Parent",
|
329
|
+
foreign_key: 'parent_id', with_deleted: true
|
252
330
|
end
|
253
331
|
|
254
332
|
parent = Parent.first
|
@@ -259,19 +337,38 @@ child.parent #=> nil
|
|
259
337
|
child.parent_including_deleted #=> Parent (it works!)
|
260
338
|
```
|
261
339
|
|
340
|
+
### Callbacks
|
341
|
+
|
342
|
+
There are couple of callbacks that you may use when dealing with deletion and
|
343
|
+
recovery of objects. There is `before_recover` and `after_recover` which will
|
344
|
+
be triggered before and after the recovery of an object respectively.
|
345
|
+
|
346
|
+
Default ActiveRecord callbacks such as `before_destroy` and `after_destroy` will
|
347
|
+
be triggered around `.destroy!` and `.destroy_fully!`.
|
348
|
+
|
349
|
+
```ruby
|
350
|
+
class Paranoiac < ActiveRecord::Base
|
351
|
+
acts_as_paranoid
|
352
|
+
|
353
|
+
before_recover :set_counts
|
354
|
+
after_recover :update_logs
|
355
|
+
end
|
356
|
+
```
|
357
|
+
|
262
358
|
## Caveats
|
263
359
|
|
264
360
|
Watch out for these caveats:
|
265
361
|
|
266
|
-
|
267
|
-
-
|
268
|
-
|
269
|
-
|
270
|
-
-
|
362
|
+
- You cannot use scopes named `with_deleted` and `only_deleted`
|
363
|
+
- You cannot use scopes named `deleted_inside_time_window`,
|
364
|
+
`deleted_before_time`, `deleted_after_time` **if** your paranoid column's
|
365
|
+
type is `time`
|
366
|
+
- You cannot name association `*_with_deleted`
|
367
|
+
- `unscoped` will return all records, deleted or not
|
271
368
|
|
272
369
|
# Acknowledgements
|
273
370
|
|
274
|
-
* To [Rick Olson](https://github.com/technoweenie) for creating acts_as_paranoid
|
371
|
+
* To [Rick Olson](https://github.com/technoweenie) for creating `acts_as_paranoid`
|
275
372
|
* To [cheerfulstoic](https://github.com/cheerfulstoic) for adding recursive recovery
|
276
373
|
* To [Jonathan Vaught](https://github.com/gravelpup) for adding paranoid validations
|
277
374
|
* To [Geoffrey Hichborn](https://github.com/phene) for improving the overral code quality and adding support for after_commit
|
@@ -283,5 +380,6 @@ Watch out for these caveats:
|
|
283
380
|
* To [Jean Boussier](https://github.com/byroot) for initial Rails 4.0.0 support
|
284
381
|
* To [Matijs van Zuijlen](https://github.com/mvz) for Rails 4.1 and 4.2 support
|
285
382
|
* To [Andrey Ponomarenko](https://github.com/sjke) for Rails 5 support
|
383
|
+
* To [Daniel Rice](https://github.com/danielricecodes), [Josh Bryant](https://github.com/jbryant92), and [Romain Alexandre](https://github.com/RomainAlexandre) for Rails 6.0 support.
|
286
384
|
|
287
385
|
See `LICENSE`.
|