acts_as_paranoid 0.6.2 → 0.7.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bcd9a9f5f44fbc3890442360530b48ed39f94bd8cbe4f49d245a2c27510f7fd
4
- data.tar.gz: 47c9aceb7415a3704b69b3bcaf7c8db64d402ecc9d1ef41352a70d0a386a819c
3
+ metadata.gz: 2a0dd97ab43e1d7a8a72327a1abf5df84ae9d3ff36c38caed38a808aacef6b01
4
+ data.tar.gz: a628f74884aff858620127b163b1998b5d790a0cfcbff4ad56e9851f962a3caf
5
5
  SHA512:
6
- metadata.gz: 78c376b394c50800f5f22db6a30a4dd607196a277266af7e24e04b209326e176471f916da360a1eb6e7e2c6573c506b211eccac42961a9a3ed686def7c105987
7
- data.tar.gz: b0025f38c28cfc80fb852673f4913edf25273912ca83a768e000a15a745edfa9069d6fda490e31cc8ffe39975651d339d7ce82ac07f1065936ef6832f6b5eef1
6
+ metadata.gz: 1488e86f1437d179e8aef1bc8b2e6da851a29d44ef9a93d7d2a60685bae36da50d69ec74bb19f6c4751257ddce5af556994c1d38beaef037b5753c063fdf409a
7
+ data.tar.gz: 630cec48256d5baf5e859f138fcc74b0a3718f6283ee08d47b36fa96cca9feba16bd6a2e1e4a3eeb3ecc210238d5ac8eb4ea31374ca8b0cfa07b57bdb9392368
data/CHANGELOG.md CHANGED
@@ -2,14 +2,88 @@
2
2
 
3
3
  Notable changes to this project will be documented in this file.
4
4
 
5
+ ## 0.7.3
6
+
7
+ ## Improvements
8
+
9
+ * Fix deletion time scopes ([#212] by [Matijs van Zuijlen][mvz])
10
+ * Reload `has_one` associations after dependent recovery ([#214],
11
+ by [Matijs van Zuijlen][mvz])
12
+ * Make dependent recovery work when parent is non-optional ([#227],
13
+ by [Matijs van Zuijlen][mvz])
14
+ * Avoid querying nil `belongs_to` associations when recovering ([#219],
15
+ by [Matijs van Zuijlen][mvz])
16
+ * On relations, deprecate `destroy!` in favour of `destroy_fully!` ([#222],
17
+ by [Matijs van Zuijlen][mvz])
18
+ * Deprecate the undocumented `:recovery_value` setting. Calculate the correct
19
+ value instead. ([#220], by [Matijs van Zuijlen][mvz])
20
+
21
+ ## Developer experience
22
+
23
+ * Log ActiveRecord activity to a visible log during tests ([#218],
24
+ by [Matijs van Zuijlen][mvz])
25
+
26
+ ## 0.7.2
27
+
28
+ * Do not set boolean column to NULL on recovery if nulls are not allowed
29
+ ([#193], by [Shodai Suzuki][soartec-lab])
30
+ * Add a CONTRIBUTING.md file ([#207], by [Matijs van Zuijlen][mvz])
31
+
32
+ ## 0.7.1
33
+
34
+ * Support Rails 6.1 ([#191], by [Matijs van Zuijlen][mvz])
35
+ * Support `belongs_to` with both `:touch` and `:counter_cache` options ([#208],
36
+ by [Matijs van Zuijlen][mvz] with [Paul Druziak][pauldruziak])
37
+ * Support Ruby 3.0 ([#209], by [Matijs van Zuijlen][mvz])
38
+
39
+ ## 0.7.0
40
+
41
+ ### Breaking changes
42
+
43
+ * Support Rails 5.2+ only ([#126], by [Daniel Rice][danielricecodes])
44
+ * Update set of supported rubies to 2.4-2.7 ([#144], [#173] by [Matijs van Zuijlen][mvz])
45
+
46
+ ### Improvements
47
+
48
+ * Handle `with_deleted` association option as a scope ([#147], by [Matijs van Zuijlen][mvz])
49
+ * Simplify validation override ([#158], by [Matijs van Zuijlen][mvz])
50
+ * Use correct unscope syntax so unscope works on Rails Edge ([#160],
51
+ by [Matijs van Zuijlen][mvz])
52
+ * Fix ruby 2.7 keyword argument deprecation warning ([#161], by [Jon Riddle][wtfspm])
53
+
54
+ ### Documentation
55
+
56
+ * Document save after destroy behavior ([#146], by [Matijs van Zuijlen][mvz])
57
+ * Update version number instructions for installing gem ([#164],
58
+ by [Kevin McAlear][kevinmcalear])
59
+ * Add example with `destroyed_fully?` and `deleted_fully?` to the readme ([#170],
60
+ by [Kiril Mitov][thebravoman])
61
+
62
+ ### Internal
63
+
64
+ * Improve code quality using RuboCop ([#148], [#152], [#159], [#163], [#171] and [#173],
65
+ by [Matijs van Zuijlen][mvz])
66
+ * Measure code coverage using SimpleCov ([#150] and [#175] by [Matijs van Zuijlen][mvz])
67
+ * Silence warnings emitted during tests ([#156], by [Matijs van Zuijlen][mvz])
68
+ * Make rake tasks more robust and intuitive ([#157], by [Matijs van Zuijlen][mvz])
69
+
70
+ ## 0.6.3
71
+
72
+ * Update Travis CI configuration ([#137], by [Matijs van Zuijlen][mvz])
73
+ * Add predicate to check if record was soft deleted or hard deleted ([#136],
74
+ by [Aymeric Le Dorze][aymeric-ledorze])
75
+ * Add support for recover! method ([#75], by [vinoth][avinoth])
76
+ * Fix a record being dirty after destroying it ([#135], by
77
+ [Aymeric Le Dorze][aymeric-ledorze])
78
+
5
79
  ## 0.6.2
6
80
 
7
81
  * Prevent recovery of non-deleted records
8
82
  ([#133], by [Mary Beliveau][marycodes2] and [Valerie Woolard][valeriecodes])
9
83
  * Allow model to set `table_name` after `acts_as_paranoid` macro
10
- ([#131], by [Alex Wheeler][AlexWheeler]).
84
+ ([#131], by [Alex Wheeler][AlexWheeler])
11
85
  * Make counter cache work with a custom column name and with optional
12
- associations ([#123], by [Ned Campion][nedcampion]).
86
+ associations ([#123], by [Ned Campion][nedcampion])
13
87
 
14
88
  ## 0.6.1
15
89
 
@@ -18,8 +92,8 @@ Notable changes to this project will be documented in this file.
18
92
  * Add support for incrementing and decrementing counter cache columns on
19
93
  associated objects ([#119], by [Dimitar Lukanov][shadydealer])
20
94
  * Add `:double_tap_destroys_fully` option, with default `true` ([#116],
21
- by [Michael Riviera][ri4a]).
22
- * Officially support Ruby 2.6 ([#114], by [Matijs van Zuijlen][mvz]).
95
+ by [Michael Riviera][ri4a])
96
+ * Officially support Ruby 2.6 ([#114], by [Matijs van Zuijlen][mvz])
23
97
 
24
98
  ## 0.6.0 and earlier
25
99
 
@@ -27,23 +101,65 @@ Notable changes to this project will be documented in this file.
27
101
 
28
102
  <!-- Contributors -->
29
103
 
30
- [ri4a]: https://github.com/ri4a
31
- [mvz]: https://github.com/mvz
32
- [shadydealer]: https://github.com/shadydealer
104
+ [AlexWheeler]: https://github.com/AlexWheeler
105
+ [RomainAlexandre]: https://github.com/RomainAlexandre
106
+ [avinoth]: https://github.com/avinoth
107
+ [aymeric-ledorze]: https://github.com/aymeric-ledorze
33
108
  [danielricecodes]: https://github.com/danielricecodes
34
109
  [jbryant92]: https://github.com/jbryant92
35
- [nedcampion]: https://github.com/nedcampion
36
- [RomainAlexandre]: https://github.com/RomainAlexandre
37
- [AlexWheeler]: https://github.com/AlexWheeler
110
+ [kevinmcalear]: https://github.com/kevinmcalear
38
111
  [marycodes2]: https://github.com/marycodes2
112
+ [mvz]: https://github.com/mvz
113
+ [nedcampion]: https://github.com/nedcampion
114
+ [ri4a]: https://github.com/ri4a
115
+ [pauldruziak]: https://github.com/pauldruziak
116
+ [shadydealer]: https://github.com/shadydealer
117
+ [soartec-lab]: https://github.com/soartec-lab
118
+ [thebravoman]: https://github.com/thebravoman
39
119
  [valeriecodes]: https://github.com/valeriecodes
120
+ [wtfspm]: https://github.com/wtfspm
40
121
 
41
122
  <!-- issues & pull requests -->
42
123
 
124
+ [#227]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/227
125
+ [#222]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/222
126
+ [#220]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/220
127
+ [#219]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/219
128
+ [#218]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/218
129
+ [#214]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/214
130
+ [#212]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/212
131
+ [#209]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/209
132
+ [#208]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/208
133
+ [#207]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/207
134
+ [#193]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/193
135
+ [#191]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/191
136
+ [#175]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/175
137
+ [#173]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/173
138
+ [#171]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/171
139
+ [#170]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/170
140
+ [#164]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/164
141
+ [#163]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/163
142
+ [#161]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/161
143
+ [#160]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/160
144
+ [#159]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/159
145
+ [#158]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/158
146
+ [#157]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/157
147
+ [#156]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/156
148
+ [#152]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/152
149
+ [#150]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/150
150
+ [#148]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/148
151
+ [#147]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/147
152
+ [#146]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/146
153
+ [#144]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/144
154
+ [#137]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/137
155
+ [#136]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/136
156
+ [#135]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/135
43
157
  [#133]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/133
44
158
  [#131]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/131
159
+ [#126]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/126
45
160
  [#124]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/124
46
161
  [#123]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/123
47
162
  [#119]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/119
48
163
  [#116]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/116
49
164
  [#114]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/114
165
+ [#75]: https://github.com/ActsAsParanoid/acts_as_paranoid/pull/75
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,59 @@
1
+ # Contributing to ActsAsParanoid
2
+
3
+ We welcome all contributions to ActsAsParanoid. Below are some guidelines to
4
+ help the process of handling issues and pull requests go smoothly.
5
+
6
+ ## Issues
7
+
8
+ When creating an issue, please try to provide as much information as possible.
9
+ Also, please follow the guidelines below to make it easier for us to figure out
10
+ what's going on. If you miss any of these points we will probably ask you to
11
+ improve the ticket.
12
+
13
+ - Include a clear title describing the problem
14
+ - Describe what you are trying to achieve
15
+ - Describe what you did, preferably including relevant code
16
+ - Describe what you expected to happen
17
+ - Describe what happened instead, possibly including relevant output
18
+ - Use [code blocks](https://github.github.com/gfm/#fenced-code-blocks) to
19
+ format any code and output in your ticket to make it readable.
20
+
21
+ ## Pull requests
22
+
23
+ If you have an idea for a particular feature, it's probably best to create a
24
+ GitHub issue for it before trying to implement it yourself. That way, we can
25
+ discuss the feature and whether it makes sense to include in ActsAsParanoid itself
26
+ before putting in the work to implement it.
27
+
28
+ If you want to send pull requests or patches, try to follow the instructions
29
+ below. **If you get stuck, please make a pull request anyway and we'll try to
30
+ help out.**
31
+
32
+ - Make sure `rake test` runs without reporting any failures.
33
+ - Add tests for your feature. Otherwise, we can't see if it works or if we
34
+ break it later.
35
+ - Make sure latest master merges cleanly with your branch. Things might
36
+ have moved around since you forked.
37
+ - Try not to include changes that are irrelevant to your feature in the
38
+ same commit.
39
+ - Keep an eye on the build results in GitHub Actions. If the build fails and it
40
+ seems due to your changes, please update your pull request with a fix.
41
+
42
+ ### The review process
43
+
44
+ - We will try to review your pull request as soon as possible but we can make no
45
+ guarantees. Feel free to ping us now and again.
46
+ - We will probably ask you to rebase your branch on current master at some point
47
+ during the review process.
48
+ If you are unsure how to do this,
49
+ [this in-depth guide](https://git-rebase.io/) should help out.
50
+ - If you have any unclear commit messages, work-in-progress commits, or commits
51
+ that just fix a mistake in a previous commits, we will ask you to clean up
52
+ the history.
53
+ Again, [the git-rebase guide](https://git-rebase.io/) should help out.
54
+ - At the end of the review process we may still choose not to merge your pull
55
+ request. For example, this could happen if we decide the proposed feature
56
+ should not be part of ActsAsParanoid, or if the technical implementation does not
57
+ match where we want to go with the architecture the project.
58
+ - We will generally not merge any pull requests that make the build fail, unless
59
+ it's very clearly not related to the changes in the pull request.
data/README.md CHANGED
@@ -9,35 +9,38 @@ recoverable later.
9
9
 
10
10
  ## Support
11
11
 
12
- **This branch targets Rails 4.2, 5.0 and 5.1, with experimental support for 5.2+**
12
+ **This branch targets Rails 5.2+ and Ruby 2.4+ only**
13
13
 
14
- If you're working with Rails 4.1-, switch to the corresponding branch, or
15
- require an older version of the `acts_as_paranoid` gem.
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 with Rails 5.2+
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
- ``` ruby
28
- gem 'acts_as_paranoid', '~> 0.6.0'
29
+ ```ruby
30
+ gem 'acts_as_paranoid', '~> 0.7.0'
29
31
  ```
30
- ``` shell
32
+
33
+ ```shell
31
34
  bundle install
32
35
  ```
33
36
 
34
37
  #### Create migration
35
38
 
36
- ``` shell
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
- The default column name and type are as follows:
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 *deletion*, you can specify them as follows:
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
- - `:column => 'deleted'`
58
- - `:column_type => 'boolean'`
59
+ - `column: 'deleted'`
60
+ - `column_type: 'boolean'`
59
61
 
60
- While *column* can be anything (as long as it exists in your database), *type* is restricted to:
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
- If your column type is a `string`, you can also specify which value to use when marking an object as deleted by passing `:deleted_value` (default is "deleted"). Any records with a non-matching value in this column will be treated normally (ie: not deleted).
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 `boolean`, it is possible to specify `allow_nulls` option which is `true` by default. When set to `false`, entities that have `false` value in this column will be considered not deleted, and those which have `true` will be considered deleted. When `true` everything that has a not-null value will be considered deleted.
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 the database.
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 are provided:
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,23 +115,32 @@ 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
- Alternatively you can permanently delete a record by calling `destroy` or `delete_all` on the object **twice**.
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 again, it will be removed from the database.
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
- p.destroy # does NOT delete the first record, just hides it
114
- Paranoiac.only_deleted.where(:id => p.id).first.destroy # deletes the first record from the database
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
 
117
- This behaviour can be disabled by setting the configuration option. In a future version, `false` will be the default setting.
140
+ This behaviour can be disabled by setting the configuration option. In a future
141
+ version, `false` will be the default setting.
118
142
 
119
- - `:double_tap_destroys_fully => false`
143
+ - `double_tap_destroys_fully: false`
120
144
 
121
145
  ### Recovery
122
146
 
@@ -126,34 +150,39 @@ Recovery is easy. Just invoke `recover` on it, like this:
126
150
  Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover
127
151
  ```
128
152
 
129
- All associations marked as `:dependent => :destroy` are also recursively recovered.
153
+ All associations marked as `dependent: :destroy` are also recursively recovered.
130
154
 
131
- If you would like to disable this behavior, you can call `recover` with the `recursive` option:
155
+ If you would like to disable this behavior, you can call `recover` with the
156
+ `recursive` option:
132
157
 
133
158
  ```ruby
134
- Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover(:recursive => false)
159
+ Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover(recursive: false)
135
160
  ```
136
161
 
137
- If you would like to change this default behavior for one model, you can use the `recover_dependent_associations` option
162
+ If you would like to change this default behavior for one model, you can use
163
+ the `recover_dependent_associations` option
138
164
 
139
165
  ```ruby
140
166
  class Paranoiac < ActiveRecord::Base
141
- acts_as_paranoid :recover_dependent_associations => false
167
+ acts_as_paranoid recover_dependent_associations: false
142
168
  end
143
169
  ```
144
170
 
145
- By default, dependent records will be recovered if they were deleted within 2 minutes of the object upon which they depend.
171
+ By default, dependent records will be recovered if they were deleted within 2
172
+ minutes of the object upon which they depend.
146
173
 
147
- This restores the objects to the state before the recursive deletion without restoring other objects that were deleted earlier.
174
+ This restores the objects to the state before the recursive deletion without
175
+ restoring other objects that were deleted earlier.
148
176
 
149
- The behavior is only available when both parent and dependant are using timestamp fields to mark deletion, which is the default behavior.
177
+ The behavior is only available when both parent and dependant are using
178
+ timestamp fields to mark deletion, which is the default behavior.
150
179
 
151
180
  This window can be changed with the `dependent_recovery_window` option:
152
181
 
153
182
  ```ruby
154
183
  class Paranoiac < ActiveRecord::Base
155
184
  acts_as_paranoid
156
- has_many :paranoids, :dependent => :destroy
185
+ has_many :paranoids, dependent: :destroy
157
186
  end
158
187
 
159
188
  class Paranoid < ActiveRecord::Base
@@ -161,18 +190,42 @@ class Paranoid < ActiveRecord::Base
161
190
 
162
191
  # Paranoid objects will be recovered alongside Paranoic objects
163
192
  # if they were deleted within 10 minutes of the Paranoic object
164
- acts_as_paranoid :dependent_recovery_window => 10.minutes
193
+ acts_as_paranoid dependent_recovery_window: 10.minutes
165
194
  end
166
195
  ```
167
196
 
168
197
  or in the recover statement
169
198
 
170
199
  ```ruby
171
- Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover(:recovery_window => 30.seconds)
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)
172
219
  ```
173
220
 
174
221
  ### Validation
175
- ActiveRecord's built-in uniqueness validation does not account for records deleted by ActsAsParanoid. If you want to check for uniqueness among non-deleted records only, use the macro `validates_as_paranoid` in your model. Then, instead of using `validates_uniqueness_of`, use `validates_uniqueness_of_without_deleted`. This will keep deleted records from counting against the uniqueness check.
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.
176
229
 
177
230
  ```ruby
178
231
  class Paranoiac < ActiveRecord::Base
@@ -181,10 +234,10 @@ class Paranoiac < ActiveRecord::Base
181
234
  validates_uniqueness_of_without_deleted :name
182
235
  end
183
236
 
184
- p1 = Paranoiac.create(:name => 'foo')
237
+ p1 = Paranoiac.create(name: 'foo')
185
238
  p1.destroy
186
239
 
187
- p2 = Paranoiac.new(:name => 'foo')
240
+ p2 = Paranoiac.new(name: 'foo')
188
241
  p2.valid? #=> true
189
242
  p2.save
190
243
 
@@ -192,16 +245,34 @@ p1.recover #=> fails validation!
192
245
  ```
193
246
 
194
247
  ### Status
195
- You can check the status of your paranoid objects with the `deleted?` helper
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
196
252
 
197
253
  ```ruby
198
- Paranoiac.create(:name => 'foo').destroy
254
+ Paranoiac.create(name: 'foo').destroy
199
255
  Paranoiac.with_deleted.first.deleted? #=> true
200
256
  ```
201
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?`.
261
+
262
+ ```ruby
263
+ Paranoiac.create(name: 'foo').destroy
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
270
+ ```
271
+
202
272
  ### Scopes
203
273
 
204
- As you've probably guessed, `with_deleted` and `only_deleted` are scopes. You can, however, chain them freely with other scopes you might have.
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.
205
276
 
206
277
  For example:
207
278
 
@@ -220,10 +291,10 @@ You can work freely with scopes and it will just work:
220
291
  ```ruby
221
292
  class Paranoiac < ActiveRecord::Base
222
293
  acts_as_paranoid
223
- scope :pretty, where(:pretty => true)
294
+ scope :pretty, where(pretty: true)
224
295
  end
225
296
 
226
- Paranoiac.create(:pretty => true)
297
+ Paranoiac.create(pretty: true)
227
298
 
228
299
  Paranoiac.pretty.count #=> 1
229
300
  Paranoiac.only_deleted.count #=> 0
@@ -240,11 +311,13 @@ Paranoiac.pretty.only_deleted.count #=> 1
240
311
 
241
312
  Associations are also supported.
242
313
 
243
- From the simplest behaviors you'd expect to more nifty things like the ones mentioned previously or the usage of the `:with_deleted` option with `belongs_to`
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`
244
317
 
245
318
  ```ruby
246
319
  class Parent < ActiveRecord::Base
247
- has_many :children, :class_name => "ParanoiacChild"
320
+ has_many :children, class_name: "ParanoiacChild"
248
321
  end
249
322
 
250
323
  class ParanoiacChild < ActiveRecord::Base
@@ -252,7 +325,8 @@ class ParanoiacChild < ActiveRecord::Base
252
325
  belongs_to :parent
253
326
 
254
327
  # You may need to provide a foreign_key like this
255
- belongs_to :parent_including_deleted, :class_name => "Parent", :foreign_key => 'parent_id', :with_deleted => true
328
+ belongs_to :parent_including_deleted, class_name: "Parent",
329
+ foreign_key: 'parent_id', with_deleted: true
256
330
  end
257
331
 
258
332
  parent = Parent.first
@@ -263,18 +337,38 @@ child.parent #=> nil
263
337
  child.parent_including_deleted #=> Parent (it works!)
264
338
  ```
265
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
+
266
358
  ## Caveats
267
359
 
268
360
  Watch out for these caveats:
269
361
 
270
- - You cannot use scopes named `with_deleted` and `only_deleted`
271
- - You cannot use scopes named `deleted_inside_time_window`, `deleted_before_time`, `deleted_after_time` **if** your paranoid column's type is `time`
272
- - You cannot name association `*_with_deleted`
273
- - `unscoped` will return all records, deleted or not
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
274
368
 
275
369
  # Acknowledgements
276
370
 
277
- * 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`
278
372
  * To [cheerfulstoic](https://github.com/cheerfulstoic) for adding recursive recovery
279
373
  * To [Jonathan Vaught](https://github.com/gravelpup) for adding paranoid validations
280
374
  * To [Geoffrey Hichborn](https://github.com/phene) for improving the overral code quality and adding support for after_commit