permanent_records 4.2.7 → 5.0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/gempush.yml +29 -0
- data/.github/workflows/test.yml +32 -0
- data/.rubocop.yml +8 -0
- data/.rubocop_todo.yml +7 -0
- data/.travis.yml +8 -5
- data/CODE_OF_CONDUCT.md +46 -0
- data/README.md +1 -1
- data/README.rst +115 -0
- data/Rakefile +6 -2
- data/VERSION +1 -1
- data/bin/gempush-if-changed +15 -0
- data/github-actions-test.yml +1 -0
- data/lib/permanent_records.rb +33 -25
- data/lib/permanent_records/active_record_5_2.rb +40 -0
- data/permanent_records.gemspec +13 -13
- metadata +39 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b6f3ec93fa6957f43a06ddd6fd8526284505b0567bcc6660befbc1730d5285b6
|
4
|
+
data.tar.gz: 637f52efbdaa2bd89e620a89700ae600771624d7a16476ff83acfccf8fbb66c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 281c172b03285f976163ac1d1a1eda7549d88cca3174bbfeb5d8f4efc053588b146cac94b1067f161a594c2b84f7bcf1cc5be220d2b355e93403f874bad36d1f
|
7
|
+
data.tar.gz: c04175c6f7418431cd4425f441f8012048d700d70214d93e9c5f9a490bcc9f3ed3036b40635660a457e435eb5b376ab1a16f83e11260cd592aadc33b6b06f3ce
|
@@ -0,0 +1,29 @@
|
|
1
|
+
name: Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
build:
|
10
|
+
name: gem publishing
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@master
|
15
|
+
- name: Set up Ruby 2.6
|
16
|
+
uses: actions/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
ruby-version: 2.6.x
|
19
|
+
|
20
|
+
- name: Publish to RubyGems
|
21
|
+
run: |
|
22
|
+
mkdir -p $HOME/.gem
|
23
|
+
touch $HOME/.gem/credentials
|
24
|
+
chmod 0600 $HOME/.gem/credentials
|
25
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
26
|
+
bin/gempush-if-changed
|
27
|
+
env:
|
28
|
+
GEM_HOST_API_KEY: ${{secrets.RUBYGEMS_AUTH_TOKEN}}
|
29
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
name: Tests
|
2
|
+
|
3
|
+
on: push
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
ci:
|
7
|
+
name: CI
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
strategy:
|
10
|
+
matrix:
|
11
|
+
ruby:
|
12
|
+
- '2.3.x'
|
13
|
+
- '2.4.x'
|
14
|
+
- '2.5.x'
|
15
|
+
- '2.6.x'
|
16
|
+
rails:
|
17
|
+
- '5.0.7.2'
|
18
|
+
- '5.1.7'
|
19
|
+
- '5.2.3'
|
20
|
+
steps:
|
21
|
+
- name: Install system dependencies
|
22
|
+
run: sudo apt-get install -y libsqlite3-dev
|
23
|
+
- uses: actions/checkout@master
|
24
|
+
- name: Setup ruby
|
25
|
+
uses: actions/setup-ruby@v1
|
26
|
+
with:
|
27
|
+
ruby-version: ${{ matrix.ruby }}
|
28
|
+
architecture: 'x64'
|
29
|
+
- run: gem install bundler && bundle && bundle exec rake
|
30
|
+
env:
|
31
|
+
AR_TEST_VERSION: ${{ matrix.rails }}
|
32
|
+
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2019-10-15 13:32:11 +0200 using RuboCop version 0.68.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
data/.travis.yml
CHANGED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
6
|
+
|
7
|
+
## Our Standards
|
8
|
+
|
9
|
+
Examples of behavior that contributes to creating a positive environment include:
|
10
|
+
|
11
|
+
* Using welcoming and inclusive language
|
12
|
+
* Being respectful of differing viewpoints and experiences
|
13
|
+
* Gracefully accepting constructive criticism
|
14
|
+
* Focusing on what is best for the community
|
15
|
+
* Showing empathy towards other community members
|
16
|
+
|
17
|
+
Examples of unacceptable behavior by participants include:
|
18
|
+
|
19
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
20
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
21
|
+
* Public or private harassment
|
22
|
+
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
23
|
+
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
24
|
+
|
25
|
+
## Our Responsibilities
|
26
|
+
|
27
|
+
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
28
|
+
|
29
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
30
|
+
|
31
|
+
## Scope
|
32
|
+
|
33
|
+
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
34
|
+
|
35
|
+
## Enforcement
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at permanentrecords@jackcanty.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
38
|
+
|
39
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
40
|
+
|
41
|
+
## Attribution
|
42
|
+
|
43
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
44
|
+
|
45
|
+
[homepage]: http://contributor-covenant.org
|
46
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/README.md
CHANGED
data/README.rst
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
PermanentRecords (Rails 5)
|
2
|
+
=============================
|
3
|
+
|
4
|
+
http://github.com/JackDanger/permanent_records/
|
5
|
+
|
6
|
+
This gem prevents any of your ActiveRecord data from being destroyed.
|
7
|
+
Any model that you've given a "deleted\_at" datetime column will have
|
8
|
+
that column set rather than let the record be deleted.
|
9
|
+
|
10
|
+
What methods does it give me?
|
11
|
+
-----------------------------
|
12
|
+
|
13
|
+
.. code:: ruby
|
14
|
+
|
15
|
+
User.find(3).destroy # Sets the 'deleted_at' attribute to Time.now
|
16
|
+
# and returns a frozen record. If halted by a
|
17
|
+
# before_destroy callback it returns false instead
|
18
|
+
|
19
|
+
User.find(3).destroy(:force) # Executes the real destroy method, the record
|
20
|
+
# will be removed from the database.
|
21
|
+
|
22
|
+
User.destroy_all # Soft-deletes all User records.
|
23
|
+
|
24
|
+
User.delete_all # bye bye everything (no soft-deleting here)
|
25
|
+
|
26
|
+
There are also two scopes provided for easily searching deleted and not
|
27
|
+
deleted records:
|
28
|
+
|
29
|
+
.. code:: ruby
|
30
|
+
|
31
|
+
User.deleted.find(...) # Only returns deleted records.
|
32
|
+
|
33
|
+
User.not_deleted.find(...) # Only returns non-deleted records.
|
34
|
+
|
35
|
+
Note: Your normal finds will, by default, *include* deleted records.
|
36
|
+
You'll have to manually use the ``not_deleted`` scope to avoid this:
|
37
|
+
|
38
|
+
.. code:: ruby
|
39
|
+
|
40
|
+
User.find(1) # Will find record number 1, even if it's deleted.
|
41
|
+
|
42
|
+
User.not_deleted.find(1) # This is probably what you want, it doesn't find deleted records.
|
43
|
+
|
44
|
+
Can I easily undelete records?
|
45
|
+
------------------------------
|
46
|
+
|
47
|
+
Yes. All you need to do is call the 'revive' method.
|
48
|
+
|
49
|
+
.. code:: ruby
|
50
|
+
|
51
|
+
User.find(3).destroy # The user is now deleted.
|
52
|
+
|
53
|
+
User.find(3).revive # The user is back to it's original state.
|
54
|
+
|
55
|
+
And if you had dependent records that were set to be destroyed along
|
56
|
+
with the parent record:
|
57
|
+
|
58
|
+
.. code:: ruby
|
59
|
+
|
60
|
+
class User < ActiveRecord::Base
|
61
|
+
has_many :comments, :dependent => :destroy
|
62
|
+
end
|
63
|
+
|
64
|
+
User.find(3).destroy # All the comments are destroyed as well.
|
65
|
+
|
66
|
+
User.find(3).revive # All the comments that were just destroyed
|
67
|
+
# are now back in pristine condition.
|
68
|
+
|
69
|
+
Forcing deletion works the same way: if you hard delete a record, its
|
70
|
+
dependent records will also be hard deleted.
|
71
|
+
|
72
|
+
Can I use default scopes?
|
73
|
+
-------------------------
|
74
|
+
|
75
|
+
.. code:: ruby
|
76
|
+
|
77
|
+
default_scope where(:deleted_at => nil)
|
78
|
+
|
79
|
+
If you use such a default scope, you will need to simulate the
|
80
|
+
``deleted`` scope with a method
|
81
|
+
|
82
|
+
.. code:: ruby
|
83
|
+
|
84
|
+
def self.deleted
|
85
|
+
self.unscoped.where('deleted_at IS NOT NULL')
|
86
|
+
end
|
87
|
+
|
88
|
+
Is Everything Automated?
|
89
|
+
------------------------
|
90
|
+
|
91
|
+
Yes. You don't have to change ANY of your code to get permanent
|
92
|
+
archiving of all your data with this gem. When you call ``destroy`` on
|
93
|
+
any record (or ``destroy_all`` on a class or association) your records
|
94
|
+
will all have a deleted\_at timestamp set on them.
|
95
|
+
|
96
|
+
Upgrading from 3.x
|
97
|
+
------------------
|
98
|
+
|
99
|
+
The behaviour of the ``destroy`` method has been updated so that it now
|
100
|
+
returns ``false`` when halted by a before\_destroy callback. This is in
|
101
|
+
line with behaviour of ActiveRecord. For more information see
|
102
|
+
`#47 <https://github.com/JackDanger/permanent_records/issues/47>`__.
|
103
|
+
|
104
|
+
Productionizing
|
105
|
+
---------------
|
106
|
+
|
107
|
+
If you operate a system where destroying or reviving a record takes more
|
108
|
+
than about 3 seconds then you'll want to customize
|
109
|
+
``PermanentRecords.dependent_record_window = 10.seconds`` or some other
|
110
|
+
value that works for you.
|
111
|
+
|
112
|
+
Patches welcome, forks celebrated.
|
113
|
+
|
114
|
+
Copyright 2015 Jack Danger Canty @ https://jdanger.com released under
|
115
|
+
the MIT license
|
data/Rakefile
CHANGED
@@ -33,7 +33,11 @@ RSpec::Core::RakeTask.new(:rspec) do |t|
|
|
33
33
|
t.rspec_opts = '-f d -c'
|
34
34
|
end
|
35
35
|
|
36
|
-
task
|
36
|
+
task :pandoc do
|
37
|
+
system('pandoc -s -r markdown -w rst README.md -o README.rst')
|
38
|
+
end
|
39
|
+
|
40
|
+
task publish: %i[pandoc rubocop rspec] do
|
37
41
|
# Ensure the gem builds
|
38
42
|
system('gem build permanent_records.gemspec') &&
|
39
43
|
# And we didn't leave anything (aside from the gem) uncommitted
|
@@ -42,4 +46,4 @@ task publish: [:rubocop, :rspec] do
|
|
42
46
|
system("gem push permanent_records-#{version}.gem")
|
43
47
|
end
|
44
48
|
|
45
|
-
task default: [
|
49
|
+
task default: %i[rspec rubocop]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
5.0.0.1
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -x
|
4
|
+
if git diff --name-only HEAD..HEAD^ | egrep -q '^VERSION$'; then
|
5
|
+
# The VERSION file changed in the last commit, build the gem and push
|
6
|
+
gem build *.gemspec
|
7
|
+
gem push *.gem
|
8
|
+
|
9
|
+
# We set the GITHUB_TOKEN variable from the repo's 'Secrets' admin panel.
|
10
|
+
git remote set-url --push origin https://JackDanger:${GITHUB_TOKEN}@github.com/JackDanger/permanent_records.git
|
11
|
+
|
12
|
+
version=$(cat VERSION)
|
13
|
+
git tag ${version}
|
14
|
+
git push origin ${version}
|
15
|
+
fi
|
@@ -0,0 +1 @@
|
|
1
|
+
.github/workflows/test.yml
|
data/lib/permanent_records.rb
CHANGED
@@ -22,7 +22,7 @@ module PermanentRecords
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def is_permanent? # rubocop:disable
|
25
|
+
def is_permanent? # rubocop:disable Naming/PredicateName
|
26
26
|
respond_to?(:deleted_at)
|
27
27
|
end
|
28
28
|
|
@@ -51,7 +51,7 @@ module PermanentRecords
|
|
51
51
|
if !is_permanent? || PermanentRecords.should_force_destroy?(force)
|
52
52
|
permanently_delete_records_after { super() }
|
53
53
|
else
|
54
|
-
destroy_with_permanent_records
|
54
|
+
destroy_with_permanent_records(force)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -68,7 +68,7 @@ module PermanentRecords
|
|
68
68
|
set_deleted_at(nil, validate)
|
69
69
|
# increment all associated counters for counter cache
|
70
70
|
each_counter_cache do |assoc_class, counter_cache_column, assoc_id|
|
71
|
-
assoc_class.increment_counter
|
71
|
+
assoc_class.increment_counter(counter_cache_column, assoc_id)
|
72
72
|
end
|
73
73
|
true
|
74
74
|
end
|
@@ -76,13 +76,14 @@ module PermanentRecords
|
|
76
76
|
]
|
77
77
|
end
|
78
78
|
|
79
|
-
def get_deleted_record # rubocop:disable
|
79
|
+
def get_deleted_record # rubocop:disable Naming/AccessorMethodName
|
80
80
|
self.class.unscoped.find(id)
|
81
81
|
end
|
82
82
|
|
83
83
|
# rubocop:disable Metrics/MethodLength
|
84
84
|
def set_deleted_at(value, force = nil)
|
85
85
|
return self unless is_permanent?
|
86
|
+
|
86
87
|
record = get_deleted_record
|
87
88
|
record.deleted_at = value
|
88
89
|
begin
|
@@ -97,7 +98,7 @@ module PermanentRecords
|
|
97
98
|
end
|
98
99
|
|
99
100
|
@attributes = record.instance_variable_get('@attributes')
|
100
|
-
rescue => e
|
101
|
+
rescue StandardError => e
|
101
102
|
# trigger dependent record destruction (they were revived before this
|
102
103
|
# record, which cannot be revived due to validations)
|
103
104
|
record.destroy
|
@@ -105,20 +106,21 @@ module PermanentRecords
|
|
105
106
|
end
|
106
107
|
end
|
107
108
|
|
109
|
+
# rubocop:enable Metrics/MethodLength
|
110
|
+
|
108
111
|
def each_counter_cache
|
109
112
|
_reflections.each do |name, reflection|
|
110
|
-
association = send(name.to_sym)
|
113
|
+
association = respond_to?(name.to_sym) ? send(name.to_sym) : nil
|
111
114
|
next if association.nil?
|
112
115
|
next unless reflection.belongs_to? && reflection.counter_cache_column
|
113
116
|
|
114
117
|
associated_class = association.class
|
115
118
|
|
116
|
-
yield(associated_class,
|
117
|
-
reflection.counter_cache_column,
|
118
|
-
send(reflection.foreign_key))
|
119
|
+
yield(associated_class, reflection.counter_cache_column, send(reflection.foreign_key))
|
119
120
|
end
|
120
121
|
end
|
121
122
|
|
123
|
+
# rubocop:disable Metrics/MethodLength
|
122
124
|
def destroy_with_permanent_records(force = nil)
|
123
125
|
run_callbacks(:destroy) do
|
124
126
|
if deleted? || new_record?
|
@@ -127,29 +129,28 @@ module PermanentRecords
|
|
127
129
|
set_deleted_at(Time.now, force)
|
128
130
|
# decrement all associated counters for counter cache
|
129
131
|
each_counter_cache do |assoc_class, counter_cache_column, assoc_id|
|
130
|
-
assoc_class.decrement_counter
|
132
|
+
assoc_class.decrement_counter(counter_cache_column, assoc_id)
|
131
133
|
end
|
132
134
|
end
|
133
135
|
true
|
134
136
|
end
|
135
137
|
deleted? ? self : false
|
136
138
|
end
|
139
|
+
# rubocop:enable Metrics/MethodLength
|
137
140
|
|
138
141
|
def add_record_window(_request, name, reflection)
|
139
142
|
send(name).unscope(where: :deleted_at).where(
|
140
143
|
[
|
141
|
-
"#{reflection.quoted_table_name}.deleted_at > ?" \
|
144
|
+
"#{reflection.klass.quoted_table_name}.deleted_at > ?" \
|
142
145
|
' AND ' \
|
143
|
-
"#{reflection.quoted_table_name}.deleted_at < ?",
|
146
|
+
"#{reflection.klass.quoted_table_name}.deleted_at < ?",
|
144
147
|
deleted_at - PermanentRecords.dependent_record_window,
|
145
148
|
deleted_at + PermanentRecords.dependent_record_window
|
146
149
|
]
|
147
150
|
)
|
148
151
|
end
|
149
152
|
|
150
|
-
# TODO: Feel free to refactor this without polluting the ActiveRecord
|
151
|
-
# namespace.
|
152
|
-
# rubocop:disable Metrics/AbcSize
|
153
|
+
# TODO: Feel free to refactor this without polluting the ActiveRecord namespace.
|
153
154
|
def revive_destroyed_dependent_records(force = nil)
|
154
155
|
destroyed_dependent_relations.each do |relation|
|
155
156
|
relation.to_a.each { |destroyed_dependent_record| destroyed_dependent_record.try(:revive, force) }
|
@@ -157,21 +158,22 @@ module PermanentRecords
|
|
157
158
|
reload
|
158
159
|
end
|
159
160
|
|
161
|
+
# rubocop:disable Metrics/MethodLength
|
160
162
|
def destroyed_dependent_relations
|
161
163
|
PermanentRecords.dependent_permanent_reflections(self.class).map do |name, relation|
|
162
|
-
|
163
|
-
|
164
|
-
when :many
|
164
|
+
case relation.macro.to_sym
|
165
|
+
when :has_many
|
165
166
|
if deleted_at
|
166
167
|
add_record_window(send(name), name, relation)
|
167
168
|
else
|
168
169
|
send(name).unscope(where: :deleted_at)
|
169
170
|
end
|
170
|
-
when :
|
171
|
+
when :has_one, :belongs_to
|
171
172
|
self.class.unscoped { Array(send(name)) }
|
172
173
|
end
|
173
174
|
end
|
174
175
|
end
|
176
|
+
# rubocop:enable Metrics/MethodLength
|
175
177
|
|
176
178
|
def attempt_notifying_observers(callback)
|
177
179
|
notify_observers(callback)
|
@@ -187,6 +189,7 @@ module PermanentRecords
|
|
187
189
|
.reduce({}) do |records, (key, _)|
|
188
190
|
found = Array(send(key)).compact
|
189
191
|
next records if found.empty?
|
192
|
+
|
190
193
|
records.update found.first.class => found.map(&:id)
|
191
194
|
end
|
192
195
|
end
|
@@ -211,6 +214,7 @@ module PermanentRecords
|
|
211
214
|
ids.each do |id|
|
212
215
|
record = klass.unscoped.where(klass.primary_key => id).first
|
213
216
|
next unless record
|
217
|
+
|
214
218
|
record.deleted_at = nil
|
215
219
|
record.destroy(:force)
|
216
220
|
end
|
@@ -231,8 +235,8 @@ module PermanentRecords
|
|
231
235
|
|
232
236
|
# Included into ActiveRecord for all models
|
233
237
|
module IsPermanent
|
234
|
-
def is_permanent? # rubocop:disable
|
235
|
-
columns.detect { |c| 'deleted_at'
|
238
|
+
def is_permanent? # rubocop:disable Naming/PredicateName
|
239
|
+
columns.detect { |c| c.name == 'deleted_at' }
|
236
240
|
end
|
237
241
|
end
|
238
242
|
|
@@ -240,16 +244,16 @@ module PermanentRecords
|
|
240
244
|
if force.is_a?(Hash)
|
241
245
|
force[:force]
|
242
246
|
else
|
243
|
-
|
247
|
+
force == :force
|
244
248
|
end
|
245
249
|
end
|
246
250
|
|
247
251
|
def self.should_revive_parent_first?(order)
|
248
|
-
order.is_a?(Hash) &&
|
252
|
+
order.is_a?(Hash) && order[:reverse] == true
|
249
253
|
end
|
250
254
|
|
251
255
|
def self.should_ignore_validations?(force)
|
252
|
-
force.is_a?(Hash) &&
|
256
|
+
force.is_a?(Hash) && force[:validate] == false
|
253
257
|
end
|
254
258
|
|
255
259
|
def self.dependent_record_window
|
@@ -275,5 +279,9 @@ module PermanentRecords
|
|
275
279
|
end
|
276
280
|
|
277
281
|
ActiveSupport.on_load(:active_record) do
|
278
|
-
ActiveRecord::Base.send
|
282
|
+
ActiveRecord::Base.send(:include, PermanentRecords::ActiveRecord)
|
283
|
+
|
284
|
+
if [ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR] == [5, 2] || ActiveRecord::VERSION::MAJOR > 5
|
285
|
+
require 'permanent_records/active_record_5_2'
|
286
|
+
end
|
279
287
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# rubocop:disable Metrics/AbcSize
|
2
|
+
# Support destroy for rails belongs_to assocations.
|
3
|
+
module HandlePermanentRecordsDestroyedInBelongsToAssociation
|
4
|
+
def handle_dependency
|
5
|
+
return unless load_target
|
6
|
+
|
7
|
+
case options[:dependent]
|
8
|
+
when :destroy
|
9
|
+
target.destroy
|
10
|
+
raise ActiveRecord::Rollback if target.respond_to?(:deleted?) && !target.deleted?
|
11
|
+
else
|
12
|
+
target.send(options[:dependent])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# rubocop:disable Metrics/MethodLength
|
18
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
19
|
+
# Support destroy for rails 5.2. has_on associations.
|
20
|
+
module HandlePermanentRecordsDestroyedInHasOneAssociation
|
21
|
+
def delete(method = options[:dependent])
|
22
|
+
return unless load_target
|
23
|
+
|
24
|
+
case method
|
25
|
+
when :delete
|
26
|
+
target.delete
|
27
|
+
when :destroy
|
28
|
+
target.destroyed_by_association = reflection
|
29
|
+
target.destroy
|
30
|
+
throw(:abort) if target.respond_to?(:deleted?) && !target.deleted?
|
31
|
+
when :nullify
|
32
|
+
target.update_columns(reflection.foreign_key => nil) if target.persisted?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
37
|
+
# rubocop:enable Metrics/MethodLength
|
38
|
+
# rubocop:enable Metrics/AbcSize
|
39
|
+
ActiveRecord::Associations::BelongsToAssociation.prepend(HandlePermanentRecordsDestroyedInBelongsToAssociation)
|
40
|
+
ActiveRecord::Associations::HasOneAssociation.prepend(HandlePermanentRecordsDestroyedInHasOneAssociation)
|
data/permanent_records.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
Gem::Specification.new do |s|
|
3
2
|
s.name = 'permanent_records'
|
4
3
|
s.version = File.read('VERSION')
|
@@ -8,10 +7,10 @@ Gem::Specification.new do |s|
|
|
8
7
|
'Trond Arve Nordheim', 'Josh Teneycke', 'Maximilian Herold',
|
9
8
|
'Hugh Evans', 'Sergey Gnuskov', 'aq', 'Joel AZEMAR']
|
10
9
|
s.summary = 'Soft-delete your ActiveRecord records'
|
11
|
-
s.description = <<-
|
12
|
-
Never Lose Data. Rather than deleting rows this sets Record#deleted_at and
|
13
|
-
gives you all the scopes you need to work with your data.
|
14
|
-
|
10
|
+
s.description = <<-DESCRIPTION
|
11
|
+
Never Lose Data. Rather than deleting rows this sets Record#deleted_at and
|
12
|
+
gives you all the scopes you need to work with your data.
|
13
|
+
DESCRIPTION
|
15
14
|
s.email = 'github@jackcanty.com'
|
16
15
|
s.extra_rdoc_files = [
|
17
16
|
'LICENSE',
|
@@ -27,12 +26,13 @@ EOS
|
|
27
26
|
ver = ENV['AR_TEST_VERSION']
|
28
27
|
ver = ver.dup.chomp if ver
|
29
28
|
|
30
|
-
s.add_runtime_dependency
|
31
|
-
s.add_runtime_dependency
|
32
|
-
s.add_development_dependency
|
33
|
-
s.add_development_dependency
|
34
|
-
s.add_development_dependency
|
35
|
-
s.add_development_dependency
|
36
|
-
s.add_development_dependency
|
37
|
-
s.add_development_dependency
|
29
|
+
s.add_runtime_dependency 'activerecord', ver || '>= 5.0.0'
|
30
|
+
s.add_runtime_dependency 'activesupport', ver || '>= 5.0.0'
|
31
|
+
s.add_development_dependency 'database_cleaner', '>= 1.5.1'
|
32
|
+
s.add_development_dependency 'pry-byebug'
|
33
|
+
s.add_development_dependency 'rake' # For Travis-ci
|
34
|
+
s.add_development_dependency 'rspec', '>= 3.5.0'
|
35
|
+
s.add_development_dependency 'rubocop', '~> 0.68.0' # freeze to ensure ruby 2.2 compatibility
|
36
|
+
s.add_development_dependency 'rubocop-performance'
|
37
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.13' # freeze to ensure specs are working
|
38
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: permanent_records
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jack Danger Canty
|
@@ -17,7 +17,7 @@ authors:
|
|
17
17
|
autorequire:
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
|
-
date:
|
20
|
+
date: 2019-10-16 00:00:00.000000000 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: activerecord
|
@@ -25,28 +25,28 @@ dependencies:
|
|
25
25
|
requirements:
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version:
|
28
|
+
version: 5.0.0
|
29
29
|
type: :runtime
|
30
30
|
prerelease: false
|
31
31
|
version_requirements: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
33
|
- - ">="
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version:
|
35
|
+
version: 5.0.0
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: activesupport
|
38
38
|
requirement: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
40
|
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version:
|
42
|
+
version: 5.0.0
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
49
|
+
version: 5.0.0
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: database_cleaner
|
52
52
|
requirement: !ruby/object:Gem::Requirement
|
@@ -93,32 +93,32 @@ dependencies:
|
|
93
93
|
name: rspec
|
94
94
|
requirement: !ruby/object:Gem::Requirement
|
95
95
|
requirements:
|
96
|
-
- - "
|
96
|
+
- - ">="
|
97
97
|
- !ruby/object:Gem::Version
|
98
98
|
version: 3.5.0
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
101
|
version_requirements: !ruby/object:Gem::Requirement
|
102
102
|
requirements:
|
103
|
-
- - "
|
103
|
+
- - ">="
|
104
104
|
- !ruby/object:Gem::Version
|
105
105
|
version: 3.5.0
|
106
106
|
- !ruby/object:Gem::Dependency
|
107
107
|
name: rubocop
|
108
108
|
requirement: !ruby/object:Gem::Requirement
|
109
109
|
requirements:
|
110
|
-
- -
|
110
|
+
- - "~>"
|
111
111
|
- !ruby/object:Gem::Version
|
112
|
-
version: 0.
|
112
|
+
version: 0.68.0
|
113
113
|
type: :development
|
114
114
|
prerelease: false
|
115
115
|
version_requirements: !ruby/object:Gem::Requirement
|
116
116
|
requirements:
|
117
|
-
- -
|
117
|
+
- - "~>"
|
118
118
|
- !ruby/object:Gem::Version
|
119
|
-
version: 0.
|
119
|
+
version: 0.68.0
|
120
120
|
- !ruby/object:Gem::Dependency
|
121
|
-
name:
|
121
|
+
name: rubocop-performance
|
122
122
|
requirement: !ruby/object:Gem::Requirement
|
123
123
|
requirements:
|
124
124
|
- - ">="
|
@@ -131,9 +131,23 @@ dependencies:
|
|
131
131
|
- - ">="
|
132
132
|
- !ruby/object:Gem::Version
|
133
133
|
version: '0'
|
134
|
-
|
135
|
-
|
136
|
-
|
134
|
+
- !ruby/object:Gem::Dependency
|
135
|
+
name: sqlite3
|
136
|
+
requirement: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - "~>"
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: 1.3.13
|
141
|
+
type: :development
|
142
|
+
prerelease: false
|
143
|
+
version_requirements: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - "~>"
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: 1.3.13
|
148
|
+
description: |2
|
149
|
+
Never Lose Data. Rather than deleting rows this sets Record#deleted_at and
|
150
|
+
gives you all the scopes you need to work with your data.
|
137
151
|
email: github@jackcanty.com
|
138
152
|
executables: []
|
139
153
|
extensions: []
|
@@ -142,18 +156,26 @@ extra_rdoc_files:
|
|
142
156
|
- README.md
|
143
157
|
files:
|
144
158
|
- ".document"
|
159
|
+
- ".github/workflows/gempush.yml"
|
160
|
+
- ".github/workflows/test.yml"
|
145
161
|
- ".gitignore"
|
146
162
|
- ".rubocop.yml"
|
163
|
+
- ".rubocop_todo.yml"
|
147
164
|
- ".travis.yml"
|
165
|
+
- CODE_OF_CONDUCT.md
|
148
166
|
- CONTRIBUTORS.md
|
149
167
|
- Gemfile
|
150
168
|
- LICENSE
|
151
169
|
- README.md
|
170
|
+
- README.rst
|
152
171
|
- Rakefile
|
153
172
|
- VERSION
|
173
|
+
- bin/gempush-if-changed
|
154
174
|
- bin/rspec
|
155
175
|
- ci
|
176
|
+
- github-actions-test.yml
|
156
177
|
- lib/permanent_records.rb
|
178
|
+
- lib/permanent_records/active_record_5_2.rb
|
157
179
|
- permanent_records.gemspec
|
158
180
|
homepage: https://github.com/JackDanger/permanent_records
|
159
181
|
licenses:
|
@@ -174,10 +196,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
174
196
|
- !ruby/object:Gem::Version
|
175
197
|
version: '0'
|
176
198
|
requirements: []
|
177
|
-
|
178
|
-
rubygems_version: 2.5.1
|
199
|
+
rubygems_version: 3.0.3
|
179
200
|
signing_key:
|
180
201
|
specification_version: 4
|
181
202
|
summary: Soft-delete your ActiveRecord records
|
182
203
|
test_files: []
|
183
|
-
has_rdoc:
|