acts_as_paranoid 0.6.2 → 0.7.3

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