permanent_records 1.1.0 → 2.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.
- data/LICENSE +20 -0
- data/README.markdown +61 -0
- data/Rakefile +6 -2
- data/VERSION +1 -1
- data/lib/permanent_records.rb +53 -18
- data/permanent_records.gemspec +30 -31
- data/test/test_helper.rb +0 -2
- metadata +15 -11
- data/.gitignore +0 -1
- data/README +0 -22
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Jack Danger Canty
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# PermanentRecords
|
2
|
+
|
3
|
+
[http://github.com/JackDanger/permanent_records/](http://github.com/JackDanger/permanent_records/)
|
4
|
+
|
5
|
+
This gem prevents any of your ActiveRecord data from being destroyed.
|
6
|
+
Any model that you've given a "deleted_at" datetime column will have that column set rather than let the record be deleted.
|
7
|
+
|
8
|
+
## Compatability: This gem works with Rails versions 1, 2, and 3
|
9
|
+
|
10
|
+
## Does it make a lot of sense?
|
11
|
+
|
12
|
+
Yes.
|
13
|
+
|
14
|
+
User.find(3).destroy # sets the 'deleted_at' attribute to Time.now and returns a frozen record
|
15
|
+
User.find(3).destroy(:force) # executes the real destroy method, the record will be removed from the database
|
16
|
+
User.destroy_all # soft-deletes all User records
|
17
|
+
User.delete_all # bye bye everything (no soft-deleting here)
|
18
|
+
|
19
|
+
There are also two scopes provided for easily searching deleted and not deleted records:
|
20
|
+
|
21
|
+
User.deleted.find(...) # only returns deleted records.
|
22
|
+
User.not_deleted.find(...) # only returns non-deleted records.
|
23
|
+
|
24
|
+
|
25
|
+
Note: Your normal finds will, by default, _include_ deleted records. You'll have to manually use the 'not_deleted' scope to avoid this:
|
26
|
+
|
27
|
+
User.find(1) # will find record number 1, even if it's deleted
|
28
|
+
User.not_deleted.find(1) # This is probably what you want, it doesn't find deleted records
|
29
|
+
|
30
|
+
## Is Everything Automated?
|
31
|
+
|
32
|
+
|
33
|
+
Yes. You don't have to change ANY of your code to get permanent archiving of all your data with this gem.
|
34
|
+
When you call 'destroy' on any record (or 'destroy_all' on a class or association) your records will
|
35
|
+
all have a deleted_at timestamp set on them.
|
36
|
+
|
37
|
+
|
38
|
+
## Can I easily undelete records?
|
39
|
+
|
40
|
+
Yes. All you need to do is call the 'revive' method.
|
41
|
+
|
42
|
+
|
43
|
+
User.find(3).destroy
|
44
|
+
# the user is now deleted
|
45
|
+
User.find(3).revive
|
46
|
+
# the user is back to it's original state
|
47
|
+
|
48
|
+
And if you had dependent records that were set to be destroyed along with the parent record:
|
49
|
+
|
50
|
+
class User < ActiveRecord::Base
|
51
|
+
has_many :comments, :dependent => :destroy
|
52
|
+
end
|
53
|
+
User.find(3).destory
|
54
|
+
# all the comments are destroyed as well
|
55
|
+
User.find(3).revive
|
56
|
+
# all the comments that were just destroyed are now back in pristine condition
|
57
|
+
|
58
|
+
|
59
|
+
Patches welcome, forks celebrated.
|
60
|
+
|
61
|
+
Copyright (c) 2010 Jack Danger Canty @ [http://jåck.com](http://jåck.com) of Cloops Inc., released under the MIT license
|
data/Rakefile
CHANGED
@@ -16,9 +16,13 @@ rescue LoadError
|
|
16
16
|
end
|
17
17
|
|
18
18
|
require 'rake/testtask'
|
19
|
-
|
20
|
-
|
19
|
+
Rake::TestTask.new(:test) do |test|
|
20
|
+
test.libs << 'lib' << 'test'
|
21
|
+
test.ruby_opts << '-rubygems'
|
22
|
+
test.pattern = 'test/*_test.rb'
|
23
|
+
test.verbose = true
|
21
24
|
end
|
25
|
+
task :spec => :test
|
22
26
|
|
23
27
|
task :default => :test
|
24
28
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0
|
data/lib/permanent_records.rb
CHANGED
@@ -1,16 +1,25 @@
|
|
1
1
|
module PermanentRecords
|
2
2
|
def self.included(base)
|
3
|
-
|
3
|
+
|
4
|
+
base.send :include, InstanceMethods
|
5
|
+
|
6
|
+
# Rails 3
|
7
|
+
if ActiveRecord::VERSION::MAJOR >= 3
|
8
|
+
base.scope :deleted, :conditions => 'deleted_at IS NOT NULL'
|
9
|
+
base.scope :not_deleted, :conditions => { :deleted_at => nil }
|
10
|
+
base.instance_eval { define_model_callbacks :revive }
|
11
|
+
# Rails 2.x.x
|
12
|
+
elsif base.respond_to?(:named_scope)
|
4
13
|
base.named_scope :deleted, :conditions => 'deleted_at IS NOT NULL'
|
5
14
|
base.named_scope :not_deleted, :conditions => { :deleted_at => nil }
|
15
|
+
base.instance_eval { define_callbacks :before_revive, :after_revive }
|
16
|
+
base.send :alias_method_chain, :destroy, :permanent_records
|
17
|
+
# Early Rails code
|
6
18
|
else
|
7
|
-
base.extend
|
19
|
+
base.extend EarlyRails
|
20
|
+
base.instance_eval { define_callbacks :before_revive, :after_revive }
|
8
21
|
end
|
9
|
-
base.send :include, InstanceMethods
|
10
22
|
base.instance_eval do
|
11
|
-
define_callbacks :before_revive, :after_revive
|
12
|
-
alias_method_chain :destroy, :permanent_record_force
|
13
|
-
alias_method_chain :destroy_without_callbacks, :permanent_record
|
14
23
|
before_revive :revive_destroyed_dependent_records
|
15
24
|
def is_permanent?
|
16
25
|
columns.detect {|c| 'deleted_at' == c.name}
|
@@ -18,7 +27,7 @@ module PermanentRecords
|
|
18
27
|
end
|
19
28
|
end
|
20
29
|
|
21
|
-
module
|
30
|
+
module EarlyRails
|
22
31
|
def with_deleted
|
23
32
|
with_scope :find => {:conditions => "#{quoted_table_name}.deleted_at IS NOT NULL"} do
|
24
33
|
yield
|
@@ -50,7 +59,7 @@ module PermanentRecords
|
|
50
59
|
end
|
51
60
|
end
|
52
61
|
end
|
53
|
-
|
62
|
+
|
54
63
|
module InstanceMethods
|
55
64
|
|
56
65
|
def is_permanent?
|
@@ -60,11 +69,22 @@ module PermanentRecords
|
|
60
69
|
def deleted?
|
61
70
|
deleted_at if is_permanent?
|
62
71
|
end
|
72
|
+
|
73
|
+
def destroyed?
|
74
|
+
deleted? || super
|
75
|
+
end
|
63
76
|
|
64
77
|
def revive
|
65
|
-
|
66
|
-
|
67
|
-
|
78
|
+
# Rails 3
|
79
|
+
if ActiveRecord::VERSION::MAJOR >= 3
|
80
|
+
_run_revive_callbacks do
|
81
|
+
set_deleted_at nil
|
82
|
+
end
|
83
|
+
else
|
84
|
+
run_callbacks :before_revive
|
85
|
+
set_deleted_at nil
|
86
|
+
run_callbacks :after_revive
|
87
|
+
end
|
68
88
|
self
|
69
89
|
end
|
70
90
|
|
@@ -74,17 +94,31 @@ module PermanentRecords
|
|
74
94
|
record.update_attribute(:deleted_at, value)
|
75
95
|
@attributes, @attributes_cache = record.attributes, record.attributes
|
76
96
|
end
|
77
|
-
|
78
|
-
def
|
79
|
-
|
80
|
-
|
97
|
+
|
98
|
+
def destroy(force = nil)
|
99
|
+
if ActiveRecord::VERSION::MAJOR >= 3
|
100
|
+
return super() unless is_permanent? && (:force != force)
|
101
|
+
end
|
102
|
+
destroy_with_permanent_records force
|
81
103
|
end
|
82
|
-
|
83
|
-
def
|
84
|
-
|
104
|
+
|
105
|
+
def destroy_with_permanent_records(force = nil)
|
106
|
+
if ActiveRecord::VERSION::MAJOR < 3
|
107
|
+
return destroy_without_permanent_records unless is_permanent? && (:force != force)
|
108
|
+
end
|
85
109
|
unless deleted? || new_record?
|
86
110
|
set_deleted_at Time.now
|
87
111
|
end
|
112
|
+
# Rails 3
|
113
|
+
if ActiveRecord::VERSION::MAJOR >= 3
|
114
|
+
_run_destroy_callbacks do
|
115
|
+
save
|
116
|
+
end
|
117
|
+
else
|
118
|
+
run_callbacks :before_destroy
|
119
|
+
save
|
120
|
+
run_callbacks :after_destroy
|
121
|
+
end
|
88
122
|
self
|
89
123
|
end
|
90
124
|
|
@@ -111,5 +145,6 @@ module PermanentRecords
|
|
111
145
|
end
|
112
146
|
end
|
113
147
|
end
|
148
|
+
|
114
149
|
ActiveRecord::Base.send :include, PermanentRecords
|
115
150
|
|
data/permanent_records.gemspec
CHANGED
@@ -1,58 +1,57 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{permanent_records}
|
8
|
-
s.version = "
|
8
|
+
s.version = "2.0.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jack Danger Canty"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-04-10}
|
13
13
|
s.description = %q{Never Lose Data. Rather than deleting rows this sets Record#deleted_at and gives you all the scopes you need to work with your data.}
|
14
14
|
s.email = %q{gems@6brand.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
|
-
"
|
16
|
+
"LICENSE",
|
17
|
+
"README.markdown"
|
17
18
|
]
|
18
19
|
s.files = [
|
19
20
|
".document",
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
21
|
+
"LICENSE",
|
22
|
+
"MIT-LICENSE",
|
23
|
+
"README.markdown",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"init.rb",
|
27
|
+
"install.rb",
|
28
|
+
"lib/permanent_records.rb",
|
29
|
+
"permanent_records.gemspec",
|
30
|
+
"test/database.yml",
|
31
|
+
"test/hole.rb",
|
32
|
+
"test/kitty.rb",
|
33
|
+
"test/mole.rb",
|
34
|
+
"test/muskrat.rb",
|
35
|
+
"test/permanent_records_test.rb",
|
36
|
+
"test/schema.rb",
|
37
|
+
"test/test_helper.rb",
|
38
|
+
"uninstall.rb"
|
38
39
|
]
|
39
40
|
s.homepage = %q{http://github.com/JackDanger/permanent_records}
|
40
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
41
41
|
s.require_paths = ["lib"]
|
42
|
-
s.rubygems_version = %q{1.
|
42
|
+
s.rubygems_version = %q{1.4.2}
|
43
43
|
s.summary = %q{Soft-delete your ActiveRecord records}
|
44
44
|
s.test_files = [
|
45
45
|
"test/hole.rb",
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
46
|
+
"test/kitty.rb",
|
47
|
+
"test/mole.rb",
|
48
|
+
"test/muskrat.rb",
|
49
|
+
"test/permanent_records_test.rb",
|
50
|
+
"test/schema.rb",
|
51
|
+
"test/test_helper.rb"
|
52
52
|
]
|
53
53
|
|
54
54
|
if s.respond_to? :specification_version then
|
55
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
55
|
s.specification_version = 3
|
57
56
|
|
58
57
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: permanent_records
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 15
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
|
-
-
|
7
|
-
- 1
|
7
|
+
- 2
|
8
8
|
- 0
|
9
|
-
|
9
|
+
- 0
|
10
|
+
version: 2.0.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Jack Danger Canty
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date:
|
18
|
+
date: 2011-04-30 00:00:00 -07:00
|
18
19
|
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
@@ -25,12 +26,13 @@ executables: []
|
|
25
26
|
extensions: []
|
26
27
|
|
27
28
|
extra_rdoc_files:
|
28
|
-
-
|
29
|
+
- LICENSE
|
30
|
+
- README.markdown
|
29
31
|
files:
|
30
32
|
- .document
|
31
|
-
-
|
33
|
+
- LICENSE
|
32
34
|
- MIT-LICENSE
|
33
|
-
- README
|
35
|
+
- README.markdown
|
34
36
|
- Rakefile
|
35
37
|
- VERSION
|
36
38
|
- init.rb
|
@@ -51,8 +53,8 @@ homepage: http://github.com/JackDanger/permanent_records
|
|
51
53
|
licenses: []
|
52
54
|
|
53
55
|
post_install_message:
|
54
|
-
rdoc_options:
|
55
|
-
|
56
|
+
rdoc_options: []
|
57
|
+
|
56
58
|
require_paths:
|
57
59
|
- lib
|
58
60
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -60,6 +62,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
60
62
|
requirements:
|
61
63
|
- - ">="
|
62
64
|
- !ruby/object:Gem::Version
|
65
|
+
hash: 3
|
63
66
|
segments:
|
64
67
|
- 0
|
65
68
|
version: "0"
|
@@ -68,13 +71,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
71
|
requirements:
|
69
72
|
- - ">="
|
70
73
|
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
71
75
|
segments:
|
72
76
|
- 0
|
73
77
|
version: "0"
|
74
78
|
requirements: []
|
75
79
|
|
76
80
|
rubyforge_project:
|
77
|
-
rubygems_version: 1.
|
81
|
+
rubygems_version: 1.4.2
|
78
82
|
signing_key:
|
79
83
|
specification_version: 3
|
80
84
|
summary: Soft-delete your ActiveRecord records
|
data/.gitignore
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
test/debug.log
|
data/README
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
PermanentRecords
|
2
|
-
================
|
3
|
-
|
4
|
-
This plugin prevents any of your records from being destroyed casually.
|
5
|
-
Any model with a deleted_at datetime column will have that column set rather than being deleted.
|
6
|
-
|
7
|
-
Usage
|
8
|
-
=======
|
9
|
-
|
10
|
-
User.find(3).destroy # sets the 'deleted_at' attribute to Time.now and returns a frozen record
|
11
|
-
User.find(3).destroy(:force) # executes the real destroy method, the record will be removed from the database
|
12
|
-
User.delete_all # bye bye everything
|
13
|
-
|
14
|
-
There are also two named scopes provided for easily searching deleted and not deleted records:
|
15
|
-
|
16
|
-
User.send :with_deleted { User.find(:all) } # only returns deleted records.
|
17
|
-
User.send :with_not_deleted { User.find(:all) } # you guessed it.
|
18
|
-
|
19
|
-
These are named so as to work smoothly with other scoping plugins like scope_out.
|
20
|
-
|
21
|
-
|
22
|
-
Copyright (c) 2008 Jack Danger Canty of adPickles Inc., released under the MIT license
|