discard 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug-report.md +24 -0
- data/.github/ISSUE_TEMPLATE/feature-proposal.md +10 -0
- data/.github/workflows/test.yml +30 -0
- data/.travis.yml +23 -9
- data/.yardopts +8 -0
- data/CHANGELOG.md +28 -0
- data/Gemfile +4 -0
- data/README.md +57 -19
- data/Rakefile +6 -7
- data/discard.gemspec +4 -3
- data/lib/discard/errors.rb +29 -0
- data/lib/discard/model.rb +133 -20
- data/lib/discard/version.rb +4 -1
- data/lib/discard.rb +3 -0
- metadata +15 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1aa5617487d7e2fed08d3afbe5e88e92aaef5371c1678a7f3c4acf532341ab56
|
4
|
+
data.tar.gz: 4f4da23a43a04274325db950a05bbfb3ff478430bea166c5c9d941fb2181769e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96650925ee2f6dd7c348059f17320decf4f26e6b4c942d046440d99bc23307059f48e2fc5792389bafc6cfa0594ff1382c671cc0f4e6ad5c312d83e964872a61
|
7
|
+
data.tar.gz: 2299ad7c8cdd56eddf50497351e2a654732aa72caca5d319cf6218185323a7cf9769113d0f62185ae7927acbbbeb4bec98b4963e5062590aadcc379b5581ec4a
|
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
name: Bug Report
|
3
|
+
about: Is Discard not working correctly for you? Let us know!
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
**Describe the bug**
|
11
|
+
A clear and concise description of what the bug is.
|
12
|
+
|
13
|
+
**To Reproduce**
|
14
|
+
Steps to reproduce the behavior:
|
15
|
+
1. Go to '...'
|
16
|
+
2. Click on '....'
|
17
|
+
3. Scroll down to '....'
|
18
|
+
4. See error
|
19
|
+
|
20
|
+
**Expected behavior**
|
21
|
+
A clear and concise description of what you expected to happen.
|
22
|
+
|
23
|
+
**Additional context**
|
24
|
+
Please tells us your Rails and Ruby versions, and anything else that might be helpful about the environment you encountered the issue.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
---
|
2
|
+
name: Feature Proposal
|
3
|
+
about: Discard is feature-complete, but we're happy to hear you out!
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
**Discard is feature-complete, but if you have an idea for a feature that will benefit all discard users and that won't offer a significant maintenance burden, we're happy to listen. Explain it as best you can and we'll let you know if it's something we'd like to have or if it's something that might be a better off as an extension or fork.**
|
@@ -0,0 +1,30 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
pull_request:
|
8
|
+
branches:
|
9
|
+
- master
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
build:
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
name: Test on Rails ${{ matrix.rails_version }}
|
15
|
+
strategy:
|
16
|
+
matrix:
|
17
|
+
rails_version:
|
18
|
+
- ~> 5.1.0
|
19
|
+
- ~> 5.2.0
|
20
|
+
- ~> 6.0.0
|
21
|
+
container: docker://ruby
|
22
|
+
steps:
|
23
|
+
- uses: actions/checkout@v1
|
24
|
+
- name: Build and test
|
25
|
+
run: |
|
26
|
+
gem install bundler
|
27
|
+
bundle install --jobs 4 --retry 3
|
28
|
+
bundle exec rake
|
29
|
+
env:
|
30
|
+
RAILS_VERSION: ${{ matrix.rails_version }}
|
data/.travis.yml
CHANGED
@@ -1,14 +1,28 @@
|
|
1
|
-
sudo: false
|
2
1
|
language: ruby
|
2
|
+
cache: bundler
|
3
3
|
rvm:
|
4
|
-
- 2.2
|
5
|
-
- 2.3
|
6
|
-
- 2.4
|
7
|
-
- 2.5
|
4
|
+
- 2.2
|
5
|
+
- 2.3
|
6
|
+
- 2.4
|
7
|
+
- 2.5
|
8
|
+
- 2.6
|
9
|
+
- 2.7
|
8
10
|
env:
|
9
11
|
matrix:
|
10
|
-
- RAILS_VERSION='~> 4.2.0'
|
11
|
-
- RAILS_VERSION='~> 5.0.0'
|
12
|
+
- RAILS_VERSION='~> 4.2.0' SQLITE_VERSION='~> 1.3.6'
|
13
|
+
- RAILS_VERSION='~> 5.0.0' SQLITE_VERSION='~> 1.3.6'
|
12
14
|
- RAILS_VERSION='~> 5.1.0'
|
13
|
-
- RAILS_VERSION='~> 5.2.
|
14
|
-
|
15
|
+
- RAILS_VERSION='~> 5.2.0'
|
16
|
+
- RAILS_VERSION='~> 6.0.0'
|
17
|
+
|
18
|
+
matrix:
|
19
|
+
exclude:
|
20
|
+
- rvm: 2.2
|
21
|
+
env: RAILS_VERSION='~> 6.0.0'
|
22
|
+
- rvm: 2.3
|
23
|
+
env: RAILS_VERSION='~> 6.0.0'
|
24
|
+
- rvm: 2.4
|
25
|
+
env: RAILS_VERSION='~> 6.0.0'
|
26
|
+
# Rails 4.2 uses BigDecimal.new, which Ruby 2.7 removed
|
27
|
+
- rvm: 2.7
|
28
|
+
env: RAILS_VERSION='~> 4.2.0' SQLITE_VERSION='~> 1.3.6'
|
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
### Unreleased
|
2
|
+
|
3
|
+
* Add `discard_all!` and `undiscard_all!`
|
4
|
+
* Add `undiscarded?` and `kept?` to match the scopes of the same names
|
5
|
+
|
6
|
+
### Version 1.1.0
|
7
|
+
Release date: 2019-05-03
|
8
|
+
|
9
|
+
* Support for ActiveRecord 6
|
10
|
+
* `discard_all` and `undiscard_all` now return affected records
|
11
|
+
* Add `discard!` and `undiscard!`
|
12
|
+
|
13
|
+
### Version 1.0.0
|
14
|
+
Release date: 2018-03-16
|
15
|
+
|
16
|
+
* Add undiscard callbacks and `.undiscard_all`
|
17
|
+
|
18
|
+
### Version 0.2.0
|
19
|
+
Release date: 2017-11-22
|
20
|
+
|
21
|
+
* Add `.discard_all`
|
22
|
+
* Add `undiscarded` scope
|
23
|
+
* Add callbacks
|
24
|
+
|
25
|
+
### Version 0.1.0
|
26
|
+
Release date: 2017-04-28
|
27
|
+
|
28
|
+
* Initial version!
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -13,7 +13,7 @@ A simple ActiveRecord mixin to add conventions for flagging records as discarded
|
|
13
13
|
Add this line to your application's Gemfile:
|
14
14
|
|
15
15
|
```ruby
|
16
|
-
gem 'discard', '~> 1.
|
16
|
+
gem 'discard', '~> 1.2'
|
17
17
|
```
|
18
18
|
|
19
19
|
And then execute:
|
@@ -32,10 +32,15 @@ class Post < ActiveRecord::Base
|
|
32
32
|
end
|
33
33
|
```
|
34
34
|
|
35
|
+
You can either generate a migration using:
|
36
|
+
```
|
37
|
+
rails generate migration add_discarded_at_to_posts discarded_at:datetime:index
|
38
|
+
```
|
35
39
|
|
40
|
+
or create one yourself like the one below:
|
36
41
|
``` ruby
|
37
42
|
class AddDiscardToPosts < ActiveRecord::Migration[5.0]
|
38
|
-
def
|
43
|
+
def change
|
39
44
|
add_column :posts, :discarded_at, :datetime
|
40
45
|
add_index :posts, :discarded_at
|
41
46
|
end
|
@@ -43,16 +48,19 @@ end
|
|
43
48
|
```
|
44
49
|
|
45
50
|
|
46
|
-
|
51
|
+
#### Discard a record
|
47
52
|
|
48
|
-
```
|
53
|
+
```ruby
|
49
54
|
Post.all # => [#<Post id: 1, ...>]
|
50
55
|
Post.kept # => [#<Post id: 1, ...>]
|
51
56
|
Post.discarded # => []
|
52
57
|
|
53
58
|
post = Post.first # => #<Post id: 1, ...>
|
54
59
|
post.discard # => true
|
60
|
+
post.discard! # => Discard::RecordNotDiscarded: Failed to discard the record
|
55
61
|
post.discarded? # => true
|
62
|
+
post.undiscarded? # => false
|
63
|
+
post.kept? # => false
|
56
64
|
post.discarded_at # => 2017-04-18 18:49:49 -0700
|
57
65
|
|
58
66
|
Post.all # => [#<Post id: 1, ...>]
|
@@ -60,7 +68,7 @@ Post.kept # => []
|
|
60
68
|
Post.discarded # => [#<Post id: 1, ...>]
|
61
69
|
```
|
62
70
|
|
63
|
-
|
71
|
+
***From a controller***
|
64
72
|
|
65
73
|
Controller actions need a small modification to discard records instead of deleting them. Just replace `destroy` with `discard`.
|
66
74
|
|
@@ -72,23 +80,25 @@ end
|
|
72
80
|
```
|
73
81
|
|
74
82
|
|
75
|
-
|
83
|
+
#### Undiscard a record
|
76
84
|
|
77
|
-
```
|
85
|
+
```ruby
|
78
86
|
post = Post.first # => #<Post id: 1, ...>
|
79
87
|
post.undiscard # => true
|
88
|
+
post.undiscard! # => Discard::RecordNotUndiscarded: Failed to undiscard the record
|
89
|
+
post.discarded_at # => nil
|
80
90
|
```
|
81
91
|
|
82
92
|
***From a controller***
|
83
93
|
|
84
|
-
```
|
94
|
+
```ruby
|
85
95
|
def update
|
86
96
|
@post.undiscard
|
87
97
|
redirect_to users_url, notice: "Post undiscarded"
|
88
98
|
end
|
89
99
|
```
|
90
100
|
|
91
|
-
|
101
|
+
#### Working with associations
|
92
102
|
|
93
103
|
Under paranoia, soft deleting a record will destroy any `dependent: :destroy`
|
94
104
|
associations. Probably not what you want! This leads to all dependent records
|
@@ -114,10 +124,14 @@ discarded. Just override the `kept` scope on the Comment model.
|
|
114
124
|
|
115
125
|
``` ruby
|
116
126
|
class Comment < ActiveRecord::Base
|
117
|
-
|
127
|
+
belongs_to :post
|
118
128
|
|
119
129
|
include Discard::Model
|
120
|
-
scope :kept, -> { undiscarded.joins(:
|
130
|
+
scope :kept, -> { undiscarded.joins(:post).merge(Post.kept) }
|
131
|
+
|
132
|
+
def kept?
|
133
|
+
undiscarded? && post.kept?
|
134
|
+
end
|
121
135
|
end
|
122
136
|
|
123
137
|
Comment.kept
|
@@ -133,7 +147,7 @@ SQL databases are very good at this, and performance should not be an issue.
|
|
133
147
|
In both of these cases restoring either of these records will do right thing!
|
134
148
|
|
135
149
|
|
136
|
-
|
150
|
+
#### Default scope
|
137
151
|
|
138
152
|
It's usually undesirable to add a default scope. It will take more effort to
|
139
153
|
work around and will cause more headaches. If you know you need a default scope, it's easy to add yourself ❤.
|
@@ -149,7 +163,7 @@ Post.with_discarded # All Posts
|
|
149
163
|
Post.with_discarded.discarded # Only discarded posts
|
150
164
|
```
|
151
165
|
|
152
|
-
|
166
|
+
#### Custom column
|
153
167
|
|
154
168
|
If you're migrating from paranoia, you might want to continue using the same
|
155
169
|
column.
|
@@ -161,12 +175,16 @@ class Post < ActiveRecord::Base
|
|
161
175
|
end
|
162
176
|
```
|
163
177
|
|
164
|
-
|
178
|
+
#### Callbacks
|
165
179
|
|
166
180
|
Callbacks can be run before, after, or around the discard and undiscard operations.
|
167
181
|
A likely use is discarding or deleting associated records (but see "Working with associations" for an alternative).
|
168
182
|
|
169
183
|
``` ruby
|
184
|
+
class Comment < ActiveRecord::Base
|
185
|
+
include Discard::Model
|
186
|
+
end
|
187
|
+
|
170
188
|
class Post < ActiveRecord::Base
|
171
189
|
include Discard::Model
|
172
190
|
|
@@ -182,15 +200,25 @@ class Post < ActiveRecord::Base
|
|
182
200
|
end
|
183
201
|
```
|
184
202
|
|
185
|
-
|
203
|
+
*Warning:* Please note that callbacks for save and update are run when discarding/undiscarding a record
|
204
|
+
|
205
|
+
|
206
|
+
#### Performance tuning
|
207
|
+
`discard_all` and `undiscard_all` is intended to behave like `destroy_all` which has callbacks, validations, and does one query per record. If performance is a big concern, you may consider replacing it with:
|
208
|
+
|
209
|
+
`scope.update_all(discarded_at: Time.current)`
|
210
|
+
or
|
211
|
+
`scope.update_all(discarded_at: nil)`
|
212
|
+
|
213
|
+
#### Working with Devise
|
186
214
|
|
187
215
|
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
216
|
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
217
|
|
190
|
-
```
|
218
|
+
```ruby
|
191
219
|
class User < ActiveRecord::Base
|
192
220
|
def active_for_authentication?
|
193
|
-
super && !
|
221
|
+
super && !discarded?
|
194
222
|
end
|
195
223
|
end
|
196
224
|
```
|
@@ -201,6 +229,12 @@ end
|
|
201
229
|
* Recursive discards (like AR's dependent: destroy) - This can be avoided using queries (See "Working with associations") or emulated using callbacks.
|
202
230
|
* Recursive restores - This concept is fundamentally broken, but not necessary if the recursive discards are avoided.
|
203
231
|
|
232
|
+
## Extensions
|
233
|
+
|
234
|
+
Discard provides the smallest subset of soft-deletion features that we think are useful to all users of the gem. We welcome the addition of gems that work with Discard to provide additional features.
|
235
|
+
|
236
|
+
- [discard-rails-observers](https://github.com/pelargir/discard-rails-observers) integrates discard with the [rails-observers gem](https://github.com/rails/rails-observers)
|
237
|
+
|
204
238
|
## Why not paranoia or acts_as_paranoid?
|
205
239
|
|
206
240
|
I've worked with and have helped maintain
|
@@ -217,7 +251,7 @@ and awkward behaviour.
|
|
217
251
|
adding `.with_deleted` to associations or anywhere soft-deleted records
|
218
252
|
should be found. :disappointed:
|
219
253
|
* Adding `belongs_to :child, -> { with_deleted }` helps, but doesn't work for
|
220
|
-
joins and eager-loading.
|
254
|
+
joins and eager-loading [before Rails 5.2](https://github.com/rubysherpas/paranoia/issues/355)
|
221
255
|
* `delete` is overridden (`really_delete` will actually delete the record) :unamused:
|
222
256
|
* `destroy` is overridden (`really_destroy` will actually delete the record) :pensive:
|
223
257
|
* `dependent: :destroy` associations are deleted when performing soft-destroys :scream:
|
@@ -237,7 +271,11 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
237
271
|
|
238
272
|
## Contributing
|
239
273
|
|
240
|
-
|
274
|
+
Please consider filing an issue with the details of any features you'd like to see before implementing them. Discard is feature-complete and we are only interested in adding additional features that won't require substantial maintenance burden and that will benefit all users of the gem. We encourage anyone that needs additional or different behaviour to either create their own gem that builds off of discard or implement a new package with the different behaviour.
|
275
|
+
|
276
|
+
Discard is very simple and we like it that way. Creating your own clone or fork with slightly different behaviour may not be that much work!
|
277
|
+
|
278
|
+
If you find a bug in discard, please report it! We try to keep up with any issues and keep the gem running smoothly for everyone! You can report issues [here](https://github.com/jhawthorn/discard/issues).
|
241
279
|
|
242
280
|
## License
|
243
281
|
|
data/Rakefile
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rspec/core/rake_task'
|
2
4
|
|
3
|
-
|
4
|
-
require 'rspec/core/rake_task'
|
5
|
-
RSpec::Core::RakeTask.new(:spec)
|
6
|
-
rescue LoadError
|
7
|
-
end
|
5
|
+
RSpec::Core::RakeTask.new(:rspec)
|
8
6
|
|
9
|
-
|
7
|
+
desc 'Run the test suite'
|
8
|
+
task default: :rspec
|
data/discard.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'discard/version'
|
@@ -21,8 +22,8 @@ Gem::Specification.new do |spec|
|
|
21
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
23
|
spec.require_paths = ["lib"]
|
23
24
|
|
24
|
-
spec.add_dependency "activerecord",
|
25
|
-
spec.add_development_dependency "bundler"
|
25
|
+
spec.add_dependency "activerecord", ">= 4.2", "< 7"
|
26
|
+
spec.add_development_dependency "bundler"
|
26
27
|
spec.add_development_dependency "rake", "~> 10.0"
|
27
28
|
spec.add_development_dependency "rspec", "~> 3.5.0"
|
28
29
|
spec.add_development_dependency "database_cleaner", "~> 1.5"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Discard
|
4
|
+
# = Discard Errors
|
5
|
+
#
|
6
|
+
# Generic exception class.
|
7
|
+
class DiscardError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
# Raised by {Discard::Model#discard!}
|
11
|
+
class RecordNotDiscarded < DiscardError
|
12
|
+
attr_reader :record
|
13
|
+
|
14
|
+
def initialize(message = nil, record = nil)
|
15
|
+
@record = record
|
16
|
+
super(message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Raised by {Discard::Model#undiscard!}
|
21
|
+
class RecordNotUndiscarded < DiscardError
|
22
|
+
attr_reader :record
|
23
|
+
|
24
|
+
def initialize(message = nil, record = nil)
|
25
|
+
@record = record
|
26
|
+
super(message)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/discard/model.rb
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Discard
|
4
|
+
# Handles soft deletes of records.
|
5
|
+
#
|
6
|
+
# Options:
|
7
|
+
#
|
8
|
+
# - :discard_column - The columns used to track soft delete, defaults to `:discarded_at`.
|
2
9
|
module Model
|
3
10
|
extend ActiveSupport::Concern
|
4
11
|
|
@@ -15,42 +22,148 @@ module Discard
|
|
15
22
|
define_model_callbacks :undiscard
|
16
23
|
end
|
17
24
|
|
25
|
+
# :nodoc:
|
18
26
|
module ClassMethods
|
27
|
+
# Discards the records by instantiating each
|
28
|
+
# record and calling its {#discard} method.
|
29
|
+
# Each object's callbacks are executed.
|
30
|
+
# Returns the collection of objects that were discarded.
|
31
|
+
#
|
32
|
+
# Note: Instantiation, callback execution, and update of each
|
33
|
+
# record can be time consuming when you're discarding many records at
|
34
|
+
# once. It generates at least one SQL +UPDATE+ query per record (or
|
35
|
+
# possibly more, to enforce your callbacks). If you want to discard many
|
36
|
+
# rows quickly, without concern for their associations or callbacks, use
|
37
|
+
# #update_all(discarded_at: Time.current) instead.
|
38
|
+
#
|
39
|
+
# ==== Examples
|
40
|
+
#
|
41
|
+
# Person.where(age: 0..18).discard_all
|
19
42
|
def discard_all
|
20
|
-
|
43
|
+
kept.each(&:discard)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Discards the records by instantiating each
|
47
|
+
# record and calling its {#discard!} method.
|
48
|
+
# Each object's callbacks are executed.
|
49
|
+
# Returns the collection of objects that were discarded.
|
50
|
+
#
|
51
|
+
# Note: Instantiation, callback execution, and update of each
|
52
|
+
# record can be time consuming when you're discarding many records at
|
53
|
+
# once. It generates at least one SQL +UPDATE+ query per record (or
|
54
|
+
# possibly more, to enforce your callbacks). If you want to discard many
|
55
|
+
# rows quickly, without concern for their associations or callbacks, use
|
56
|
+
# #update_all!(discarded_at: Time.current) instead.
|
57
|
+
#
|
58
|
+
# ==== Examples
|
59
|
+
#
|
60
|
+
# Person.where(age: 0..18).discard_all!
|
61
|
+
def discard_all!
|
62
|
+
kept.each(&:discard!)
|
21
63
|
end
|
64
|
+
|
65
|
+
# Undiscards the records by instantiating each
|
66
|
+
# record and calling its {#undiscard} method.
|
67
|
+
# Each object's callbacks are executed.
|
68
|
+
# Returns the collection of objects that were undiscarded.
|
69
|
+
#
|
70
|
+
# Note: Instantiation, callback execution, and update of each
|
71
|
+
# record can be time consuming when you're undiscarding many records at
|
72
|
+
# once. It generates at least one SQL +UPDATE+ query per record (or
|
73
|
+
# possibly more, to enforce your callbacks). If you want to undiscard many
|
74
|
+
# rows quickly, without concern for their associations or callbacks, use
|
75
|
+
# #update_all(discarded_at: nil) instead.
|
76
|
+
#
|
77
|
+
# ==== Examples
|
78
|
+
#
|
79
|
+
# Person.where(age: 0..18).undiscard_all
|
22
80
|
def undiscard_all
|
23
|
-
|
81
|
+
discarded.each(&:undiscard)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Undiscards the records by instantiating each
|
85
|
+
# record and calling its {#undiscard!} method.
|
86
|
+
# Each object's callbacks are executed.
|
87
|
+
# Returns the collection of objects that were undiscarded.
|
88
|
+
#
|
89
|
+
# Note: Instantiation, callback execution, and update of each
|
90
|
+
# record can be time consuming when you're undiscarding many records at
|
91
|
+
# once. It generates at least one SQL +UPDATE+ query per record (or
|
92
|
+
# possibly more, to enforce your callbacks). If you want to undiscard many
|
93
|
+
# rows quickly, without concern for their associations or callbacks, use
|
94
|
+
# #update_all!(discarded_at: nil) instead.
|
95
|
+
#
|
96
|
+
# ==== Examples
|
97
|
+
#
|
98
|
+
# Person.where(age: 0..18).undiscard_all!
|
99
|
+
def undiscard_all!
|
100
|
+
discarded.each(&:undiscard!)
|
24
101
|
end
|
25
102
|
end
|
26
103
|
|
27
|
-
# @return [
|
104
|
+
# @return [Boolean] true if this record has been discarded, otherwise false
|
28
105
|
def discarded?
|
29
|
-
|
106
|
+
self[self.class.discard_column].present?
|
107
|
+
end
|
108
|
+
|
109
|
+
# @return [Boolean] false if this record has been discarded, otherwise true
|
110
|
+
def undiscarded?
|
111
|
+
!discarded?
|
30
112
|
end
|
113
|
+
alias kept? undiscarded?
|
31
114
|
|
32
|
-
#
|
115
|
+
# Discard the record in the database
|
116
|
+
#
|
117
|
+
# @return [Boolean] true if successful, otherwise false
|
33
118
|
def discard
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
self[self.class.discard_column] = Time.current
|
38
|
-
save
|
39
|
-
end
|
40
|
-
end
|
119
|
+
return false if discarded?
|
120
|
+
run_callbacks(:discard) do
|
121
|
+
update_attribute(self.class.discard_column, Time.current)
|
41
122
|
end
|
42
123
|
end
|
43
124
|
|
44
|
-
#
|
125
|
+
# Discard the record in the database
|
126
|
+
#
|
127
|
+
# There's a series of callbacks associated with #discard!. If the
|
128
|
+
# <tt>before_discard</tt> callback throws +:abort+ the action is cancelled
|
129
|
+
# and #discard! raises {Discard::RecordNotDiscarded}.
|
130
|
+
#
|
131
|
+
# @return [Boolean] true if successful
|
132
|
+
# @raise {Discard::RecordNotDiscarded}
|
133
|
+
def discard!
|
134
|
+
discard || _raise_record_not_discarded
|
135
|
+
end
|
136
|
+
|
137
|
+
# Undiscard the record in the database
|
138
|
+
#
|
139
|
+
# @return [Boolean] true if successful, otherwise false
|
45
140
|
def undiscard
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
self[self.class.discard_column] = nil
|
50
|
-
save
|
51
|
-
end
|
52
|
-
end
|
141
|
+
return unless discarded?
|
142
|
+
run_callbacks(:undiscard) do
|
143
|
+
update_attribute(self.class.discard_column, nil)
|
53
144
|
end
|
54
145
|
end
|
146
|
+
|
147
|
+
# Discard the record in the database
|
148
|
+
#
|
149
|
+
# There's a series of callbacks associated with #undiscard!. If the
|
150
|
+
# <tt>before_undiscard</tt> callback throws +:abort+ the action is cancelled
|
151
|
+
# and #undiscard! raises {Discard::RecordNotUndiscarded}.
|
152
|
+
#
|
153
|
+
# @return [Boolean] true if successful
|
154
|
+
# @raise {Discard::RecordNotUndiscarded}
|
155
|
+
def undiscard!
|
156
|
+
undiscard || _raise_record_not_undiscarded
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def _raise_record_not_discarded
|
162
|
+
raise ::Discard::RecordNotDiscarded.new("Failed to discard the record", self)
|
163
|
+
end
|
164
|
+
|
165
|
+
def _raise_record_not_undiscarded
|
166
|
+
raise ::Discard::RecordNotUndiscarded.new("Failed to undiscard the record", self)
|
167
|
+
end
|
55
168
|
end
|
56
169
|
end
|
data/lib/discard/version.rb
CHANGED
data/lib/discard.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: 1.
|
4
|
+
version: 1.2.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: 2020-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '4.2'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,21 +29,21 @@ dependencies:
|
|
29
29
|
version: '4.2'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: bundler
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
39
|
+
version: '0'
|
40
40
|
type: :development
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
|
-
- - "
|
44
|
+
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
46
|
+
version: '0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rake
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,9 +122,14 @@ executables: []
|
|
122
122
|
extensions: []
|
123
123
|
extra_rdoc_files: []
|
124
124
|
files:
|
125
|
+
- ".github/ISSUE_TEMPLATE/bug-report.md"
|
126
|
+
- ".github/ISSUE_TEMPLATE/feature-proposal.md"
|
127
|
+
- ".github/workflows/test.yml"
|
125
128
|
- ".gitignore"
|
126
129
|
- ".rspec"
|
127
130
|
- ".travis.yml"
|
131
|
+
- ".yardopts"
|
132
|
+
- CHANGELOG.md
|
128
133
|
- CODE_OF_CONDUCT.md
|
129
134
|
- Gemfile
|
130
135
|
- LICENSE.txt
|
@@ -134,6 +139,7 @@ files:
|
|
134
139
|
- bin/setup
|
135
140
|
- discard.gemspec
|
136
141
|
- lib/discard.rb
|
142
|
+
- lib/discard/errors.rb
|
137
143
|
- lib/discard/model.rb
|
138
144
|
- lib/discard/version.rb
|
139
145
|
homepage: https://github.com/jhawthorn/discard
|
@@ -155,8 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
161
|
- !ruby/object:Gem::Version
|
156
162
|
version: '0'
|
157
163
|
requirements: []
|
158
|
-
|
159
|
-
rubygems_version: 2.7.6
|
164
|
+
rubygems_version: 3.1.0.pre2
|
160
165
|
signing_key:
|
161
166
|
specification_version: 4
|
162
167
|
summary: ActiveRecord soft-deletes done right
|