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 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