discard 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.travis.yml +6 -4
- data/README.md +90 -38
- data/lib/discard/model.rb +16 -3
- data/lib/discard/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 99f47416f1c4bdc6ed76c7814e6f1b88baea019acf8d38abbbbf709d42db0efa
|
4
|
+
data.tar.gz: c6699d73d311300e8cdeecd1cb2498c3b25197a10292f28993abc237ad1abd5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebd11402b212e931423a98484b598675eac16ef4eb878a701fd1479da488bd503058d0679053be16b43bab4e651b50cd512c6d14f19d131dae02fbcbc3396c78
|
7
|
+
data.tar.gz: f5baab64f5a951f1c55c73615490587d44291296645c4e4317c6918dcdc52675c3fa1856f86db03de2341518d9836ab2ad7e011d914599ebbc27d425406f5ccf
|
data/.travis.yml
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- 2.2.
|
5
|
-
- 2.3.
|
6
|
-
- 2.4.
|
4
|
+
- 2.2.9
|
5
|
+
- 2.3.6
|
6
|
+
- 2.4.3
|
7
|
+
- 2.5.0
|
7
8
|
env:
|
8
9
|
matrix:
|
9
10
|
- RAILS_VERSION='~> 4.2.0'
|
10
11
|
- RAILS_VERSION='~> 5.0.0'
|
11
|
-
- RAILS_VERSION='~> 5.1.
|
12
|
+
- RAILS_VERSION='~> 5.1.0'
|
13
|
+
- RAILS_VERSION='~> 5.2.x'
|
12
14
|
before_install: gem install bundler -v 1.14.6
|
data/README.md
CHANGED
@@ -8,42 +8,12 @@ Soft deletes for ActiveRecord done right.
|
|
8
8
|
|
9
9
|
A simple ActiveRecord mixin to add conventions for flagging records as discarded.
|
10
10
|
|
11
|
-
## Why should I use this?
|
12
|
-
|
13
|
-
I've worked with and have helped maintain
|
14
|
-
[paranoia](https://github.com/rubysherpas/paranoia) for a while. I'm convinced
|
15
|
-
it does the wrong thing for most cases.
|
16
|
-
|
17
|
-
Paranoia and
|
18
|
-
[acts_as_paranoid](https://github.com/ActsAsParanoid/acts_as_paranoid) both
|
19
|
-
attempt to emulate deletes by setting a column and adding a default scope on the
|
20
|
-
model. This requires some ActiveRecord hackery, and leads to some surprising
|
21
|
-
and awkward behaviour.
|
22
|
-
|
23
|
-
* A default scope is added to hide soft-deleted records, which necessitates
|
24
|
-
adding `.with_deleted` to associations or anywhere soft-deleted records
|
25
|
-
should be found. :disappointed:
|
26
|
-
* Adding `belongs_to :child, -> { with_deleted }` helps, but doesn't work for
|
27
|
-
joins and eager-loading.
|
28
|
-
* `delete` is overridden (`really_delete` will actually delete the record) :unamused:
|
29
|
-
* `destroy` is overridden (`really_destroy` will actually delete the record) :pensive:
|
30
|
-
* `dependent: :destroy` associations are deleted when performing soft-destroys :scream:
|
31
|
-
* requiring any dependent records to also be `acts_as_paranoid` to avoid losing data. :grimacing:
|
32
|
-
|
33
|
-
There are some use cases where these behaviours make sense: if you really did
|
34
|
-
want to _almost_ delete the record. More often developers are just looking to
|
35
|
-
hide some records, or mark them as inactive.
|
36
|
-
|
37
|
-
Discard takes a different approach. It doesn't override any ActiveRecord
|
38
|
-
methods and instead simply provides convenience methods and scopes for
|
39
|
-
discarding (hiding), restoring, and querying records.
|
40
|
-
|
41
11
|
## Installation
|
42
12
|
|
43
13
|
Add this line to your application's Gemfile:
|
44
14
|
|
45
15
|
```ruby
|
46
|
-
gem 'discard'
|
16
|
+
gem 'discard', '~> 1.0'
|
47
17
|
```
|
48
18
|
|
49
19
|
And then execute:
|
@@ -67,21 +37,23 @@ end
|
|
67
37
|
class AddDiscardToPosts < ActiveRecord::Migration[5.0]
|
68
38
|
def up
|
69
39
|
add_column :posts, :discarded_at, :datetime
|
40
|
+
add_index :posts, :discarded_at
|
70
41
|
end
|
71
42
|
end
|
72
43
|
```
|
73
44
|
|
74
45
|
|
75
46
|
**Discard a record**
|
47
|
+
|
76
48
|
```
|
77
49
|
Post.all # => [#<Post id: 1, ...>]
|
78
50
|
Post.kept # => [#<Post id: 1, ...>]
|
79
51
|
Post.discarded # => []
|
80
52
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
53
|
+
post = Post.first # => #<Post id: 1, ...>
|
54
|
+
post.discard # => true
|
55
|
+
post.discarded? # => true
|
56
|
+
post.discarded_at # => 2017-04-18 18:49:49 -0700
|
85
57
|
|
86
58
|
Post.all # => [#<Post id: 1, ...>]
|
87
59
|
Post.kept # => []
|
@@ -99,6 +71,23 @@ def destroy
|
|
99
71
|
end
|
100
72
|
```
|
101
73
|
|
74
|
+
|
75
|
+
**Undiscard a record**
|
76
|
+
|
77
|
+
```
|
78
|
+
post = Post.first # => #<Post id: 1, ...>
|
79
|
+
post.undiscard # => true
|
80
|
+
```
|
81
|
+
|
82
|
+
***From a controller***
|
83
|
+
|
84
|
+
```
|
85
|
+
def update
|
86
|
+
@post.undiscard
|
87
|
+
redirect_to users_url, notice: "Post undiscarded"
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
102
91
|
**Working with associations**
|
103
92
|
|
104
93
|
Under paranoia, soft deleting a record will destroy any `dependent: :destroy`
|
@@ -172,12 +161,75 @@ class Post < ActiveRecord::Base
|
|
172
161
|
end
|
173
162
|
```
|
174
163
|
|
164
|
+
**Callbacks**
|
165
|
+
|
166
|
+
Callbacks can be run before, after, or around the discard and undiscard operations.
|
167
|
+
A likely use is discarding or deleting associated records (but see "Working with associations" for an alternative).
|
168
|
+
|
169
|
+
``` ruby
|
170
|
+
class Post < ActiveRecord::Base
|
171
|
+
include Discard::Model
|
172
|
+
|
173
|
+
has_many :comments
|
174
|
+
|
175
|
+
after_discard do
|
176
|
+
comments.discard_all
|
177
|
+
end
|
178
|
+
|
179
|
+
after_undiscard do
|
180
|
+
comments.undiscard_all
|
181
|
+
end
|
182
|
+
end
|
183
|
+
```
|
184
|
+
|
185
|
+
**Working with Devise**
|
186
|
+
|
187
|
+
A common use case is to apply discard to a User record. Even though a user has been discarded they can still login and continue their session.
|
188
|
+
If you are using Devise and wish for discarded users to be unable to login and stop their session you can override Devise's method.
|
189
|
+
|
190
|
+
```
|
191
|
+
class User < ActiveRecord::Base
|
192
|
+
def active_for_authentication?
|
193
|
+
super && !discarded_at
|
194
|
+
end
|
195
|
+
end
|
196
|
+
```
|
197
|
+
|
175
198
|
## Non-features
|
176
199
|
|
177
|
-
* Restoring records (this will probably be added)
|
178
|
-
* Discarding dependent records (this will likely be added)
|
179
|
-
* Callbacks (this will probably be added)
|
180
200
|
* Special handling of AR counter cache columns - The counter cache counts the total number of records, both kept and discarded.
|
201
|
+
* Recursive discards (like AR's dependent: destroy) - This can be avoided using queries (See "Working with associations") or emulated using callbacks.
|
202
|
+
* Recursive restores - This concept is fundamentally broken, but not necessary if the recursive discards are avoided.
|
203
|
+
|
204
|
+
## Why not paranoia or acts_as_paranoid?
|
205
|
+
|
206
|
+
I've worked with and have helped maintain
|
207
|
+
[paranoia](https://github.com/rubysherpas/paranoia) for a while. I'm convinced
|
208
|
+
it does the wrong thing for most cases.
|
209
|
+
|
210
|
+
Paranoia and
|
211
|
+
[acts_as_paranoid](https://github.com/ActsAsParanoid/acts_as_paranoid) both
|
212
|
+
attempt to emulate deletes by setting a column and adding a default scope on the
|
213
|
+
model. This requires some ActiveRecord hackery, and leads to some surprising
|
214
|
+
and awkward behaviour.
|
215
|
+
|
216
|
+
* A default scope is added to hide soft-deleted records, which necessitates
|
217
|
+
adding `.with_deleted` to associations or anywhere soft-deleted records
|
218
|
+
should be found. :disappointed:
|
219
|
+
* Adding `belongs_to :child, -> { with_deleted }` helps, but doesn't work for
|
220
|
+
joins and eager-loading.
|
221
|
+
* `delete` is overridden (`really_delete` will actually delete the record) :unamused:
|
222
|
+
* `destroy` is overridden (`really_destroy` will actually delete the record) :pensive:
|
223
|
+
* `dependent: :destroy` associations are deleted when performing soft-destroys :scream:
|
224
|
+
* requiring any dependent records to also be `acts_as_paranoid` to avoid losing data. :grimacing:
|
225
|
+
|
226
|
+
There are some use cases where these behaviours make sense: if you really did
|
227
|
+
want to _almost_ delete the record. More often developers are just looking to
|
228
|
+
hide some records, or mark them as inactive.
|
229
|
+
|
230
|
+
Discard takes a different approach. It doesn't override any ActiveRecord
|
231
|
+
methods and instead simply provides convenience methods and scopes for
|
232
|
+
discarding (hiding), restoring, and querying records.
|
181
233
|
|
182
234
|
## Development
|
183
235
|
|
data/lib/discard/model.rb
CHANGED
@@ -12,18 +12,24 @@ module Discard
|
|
12
12
|
scope :with_discarded, ->{ unscope(where: discard_column) }
|
13
13
|
|
14
14
|
define_model_callbacks :discard
|
15
|
+
define_model_callbacks :undiscard
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
|
+
module ClassMethods
|
18
19
|
def discard_all
|
19
20
|
all.each(&:discard)
|
20
21
|
end
|
22
|
+
def undiscard_all
|
23
|
+
all.each(&:undiscard)
|
24
|
+
end
|
21
25
|
end
|
22
26
|
|
27
|
+
# @return [true,false] true if this record has been discarded, otherwise false
|
23
28
|
def discarded?
|
24
29
|
!!self[self.class.discard_column]
|
25
30
|
end
|
26
31
|
|
32
|
+
# @return [true,false] true if successful, otherwise false
|
27
33
|
def discard
|
28
34
|
unless discarded?
|
29
35
|
with_transaction_returning_status do
|
@@ -35,9 +41,16 @@ module Discard
|
|
35
41
|
end
|
36
42
|
end
|
37
43
|
|
44
|
+
# @return [true,false] true if successful, otherwise false
|
38
45
|
def undiscard
|
39
|
-
|
40
|
-
|
46
|
+
if discarded?
|
47
|
+
with_transaction_returning_status do
|
48
|
+
run_callbacks(:undiscard) do
|
49
|
+
self[self.class.discard_column] = nil
|
50
|
+
save
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
41
54
|
end
|
42
55
|
end
|
43
56
|
end
|
data/lib/discard/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: discard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Hawthorn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -156,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
156
|
version: '0'
|
157
157
|
requirements: []
|
158
158
|
rubyforge_project:
|
159
|
-
rubygems_version: 2.6
|
159
|
+
rubygems_version: 2.7.6
|
160
160
|
signing_key:
|
161
161
|
specification_version: 4
|
162
162
|
summary: ActiveRecord soft-deletes done right
|