discard 0.2.0 → 1.0.0

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
- SHA1:
3
- metadata.gz: e3d4174c8881bc3bf1fa453aafb3d966d8361292
4
- data.tar.gz: 858b1edbe5d9c09144239a13cc3ca662f1485547
2
+ SHA256:
3
+ metadata.gz: 99f47416f1c4bdc6ed76c7814e6f1b88baea019acf8d38abbbbf709d42db0efa
4
+ data.tar.gz: c6699d73d311300e8cdeecd1cb2498c3b25197a10292f28993abc237ad1abd5f
5
5
  SHA512:
6
- metadata.gz: 1246d6187b35af15ceb8d5e8a1b914e09a45ba0380d833ca638305336d3075e67f60edc67fad55c49e994b0ab9e9f60b3d9a916acc837d3416b3b89ec56e2bcd
7
- data.tar.gz: 1d098bf07dcefdd3d338b0a4a73b206dfd96e5c39b8abbabb17cd749970ff9c54efd3d35fe7f6f363f8c35b076b7e54f278f1f3cbb43de7330da0a363671f2f5
6
+ metadata.gz: ebd11402b212e931423a98484b598675eac16ef4eb878a701fd1479da488bd503058d0679053be16b43bab4e651b50cd512c6d14f19d131dae02fbcbc3396c78
7
+ data.tar.gz: f5baab64f5a951f1c55c73615490587d44291296645c4e4317c6918dcdc52675c3fa1856f86db03de2341518d9836ab2ad7e011d914599ebbc27d425406f5ccf
@@ -1,12 +1,14 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.2.7
5
- - 2.3.4
6
- - 2.4.1
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.x'
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
- @post = Post.first # => #<Post id: 1, ...>
82
- @post.discard!
83
- @post.discarded? # => true
84
- @post.discarded_at # => 2017-04-18 18:49:49 -0700
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
 
@@ -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
- class_methods do
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
- self[self.class.discard_column] = nil
40
- save
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
@@ -1,3 +1,3 @@
1
1
  module Discard
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.0"
3
3
  end
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.2.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: 2017-11-22 00:00:00.000000000 Z
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.11
159
+ rubygems_version: 2.7.6
160
160
  signing_key:
161
161
  specification_version: 4
162
162
  summary: ActiveRecord soft-deletes done right