paranoia 1.3.4 → 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.
- checksums.yaml +4 -4
- data/Gemfile +1 -10
- data/README.md +5 -102
- data/lib/paranoia.rb +16 -137
- data/lib/paranoia/version.rb +1 -1
- data/paranoia.gemspec +16 -15
- data/test/paranoia_test.rb +12 -295
- metadata +29 -17
- data/.travis.yml +0 -7
- data/lib/paranoia/rspec.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e9ddf3be1c331ce833d233557bdf81876c68768
|
4
|
+
data.tar.gz: 8fb6cc8d861471436bbddda7331923395650eadb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 086ef0efc989048c0c41c1f00127664cfedf49a4c356e3315f1e87bf7b5d4bdd48bf1d299580d31126e8fc54de84ca231318511c199ec1c4be502068a44dc060
|
7
|
+
data.tar.gz: ce2574eaf67cf0d570e7139f3ea5f3bd09090449f55d577f955182661cc6204b62a7188d24dbf44422ca423ed6da126e654a6bd5bf1a005ab978f33e0a092c48
|
data/Gemfile
CHANGED
@@ -1,13 +1,4 @@
|
|
1
|
-
source
|
2
|
-
|
3
|
-
gem 'sqlite3', :platforms => [:ruby]
|
4
|
-
gem 'activerecord-jdbcsqlite3-adapter', :platforms => [:jruby]
|
5
|
-
|
6
|
-
platforms :rbx do
|
7
|
-
gem 'rubysl', '~> 2.0'
|
8
|
-
gem 'rubysl-test-unit'
|
9
|
-
gem 'rubinius-developer_tools'
|
10
|
-
end
|
1
|
+
source :gemcutter
|
11
2
|
|
12
3
|
# Specify your gem's dependencies in paranoia.gemspec
|
13
4
|
gemspec
|
data/README.md
CHANGED
@@ -4,30 +4,12 @@ Paranoia is a re-implementation of [acts\_as\_paranoid](http://github.com/techno
|
|
4
4
|
|
5
5
|
You would use either plugin / gem if you wished that when you called `destroy` on an Active Record object that it didn't actually destroy it, but just "hid" the record. Paranoia does this by setting a `deleted_at` field to the current time when you `destroy` a record, and hides it by scoping all queries on your model to only include records which do not have a `deleted_at` field.
|
6
6
|
|
7
|
-
If you wish to actually destroy an object you may call `really_destroy!`. **WARNING**: This will also *really destroy* all `dependent: destroy` records, so please aim this method away from face when using.**
|
8
|
-
|
9
|
-
If a record has `has_many` associations defined AND those associations have `dependent: :destroy` set on them, then they will also be soft-deleted if ``acts_as_paranoid`` is set, otherwise the normal destroy will be called.
|
10
|
-
|
11
7
|
## Installation & Usage
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
```ruby
|
16
|
-
gem 'paranoia', '~> 1.0'
|
17
|
-
```
|
18
|
-
|
19
|
-
For Rails 4, please use version 2 of Paranoia:
|
20
|
-
|
21
|
-
```ruby
|
22
|
-
gem 'paranoia', '~> 2.0'
|
23
|
-
```
|
24
|
-
|
25
|
-
Of course you can install this from GitHub as well:
|
9
|
+
Put this in your Gemfile:
|
26
10
|
|
27
11
|
```ruby
|
28
|
-
gem 'paranoia'
|
29
|
-
# or
|
30
|
-
gem 'paranoia', :github => 'radar/paranoia', :branch => 'rails4'
|
12
|
+
gem 'paranoia'
|
31
13
|
```
|
32
14
|
|
33
15
|
Then run:
|
@@ -43,7 +25,7 @@ Updating is as simple as `bundle update paranoia`.
|
|
43
25
|
Run:
|
44
26
|
|
45
27
|
```shell
|
46
|
-
rails generate migration AddDeletedAtToClients deleted_at:datetime
|
28
|
+
rails generate migration AddDeletedAtToClients deleted_at:datetime
|
47
29
|
```
|
48
30
|
|
49
31
|
and now you have a migration
|
@@ -52,7 +34,6 @@ and now you have a migration
|
|
52
34
|
class AddDeletedAtToClients < ActiveRecord::Migration
|
53
35
|
def change
|
54
36
|
add_column :clients, :deleted_at, :datetime
|
55
|
-
add_index :clients, :deleted_at
|
56
37
|
end
|
57
38
|
end
|
58
39
|
```
|
@@ -69,23 +50,9 @@ class Client < ActiveRecord::Base
|
|
69
50
|
end
|
70
51
|
```
|
71
52
|
|
72
|
-
Hey presto, it's there!
|
73
|
-
|
74
|
-
|
75
|
-
```
|
76
|
-
>> client.deleted_at => nil
|
77
|
-
>> client.destroy => client
|
78
|
-
>> client.deleted_at => [current timestamp]
|
79
|
-
```
|
53
|
+
Hey presto, it's there!
|
80
54
|
|
81
|
-
If you
|
82
|
-
|
83
|
-
```
|
84
|
-
>> client.deleted_at => nil
|
85
|
-
>> client.destroy! => client
|
86
|
-
```
|
87
|
-
|
88
|
-
If you want a method to be called on destroy, simply provide a `before_destroy` callback:
|
55
|
+
If you want a method to be called on destroy, simply provide a _before\_destroy_ callback:
|
89
56
|
|
90
57
|
```ruby
|
91
58
|
class Client < ActiveRecord::Base
|
@@ -101,70 +68,6 @@ class Client < ActiveRecord::Base
|
|
101
68
|
end
|
102
69
|
```
|
103
70
|
|
104
|
-
If you want to use a column other than `deleted_at`, you can pass it as an option:
|
105
|
-
|
106
|
-
```ruby
|
107
|
-
class Client < ActiveRecord::Base
|
108
|
-
acts_as_paranoid column: :destroyed_at
|
109
|
-
|
110
|
-
...
|
111
|
-
end
|
112
|
-
```
|
113
|
-
|
114
|
-
If you want to access soft-deleted associations, override the getter method:
|
115
|
-
|
116
|
-
```ruby
|
117
|
-
def product
|
118
|
-
Product.unscoped { super }
|
119
|
-
end
|
120
|
-
```
|
121
|
-
|
122
|
-
If you want to find all records, even those which are deleted:
|
123
|
-
|
124
|
-
```ruby
|
125
|
-
Client.with_deleted
|
126
|
-
```
|
127
|
-
|
128
|
-
If you want to find only the deleted records:
|
129
|
-
|
130
|
-
```ruby
|
131
|
-
Client.only_deleted
|
132
|
-
```
|
133
|
-
|
134
|
-
If you want to check if a record is soft-deleted:
|
135
|
-
|
136
|
-
```ruby
|
137
|
-
client.destroyed?
|
138
|
-
```
|
139
|
-
|
140
|
-
If you want to restore a record:
|
141
|
-
|
142
|
-
```ruby
|
143
|
-
Client.restore(id)
|
144
|
-
```
|
145
|
-
|
146
|
-
If you want to restore a whole bunch of records:
|
147
|
-
|
148
|
-
```ruby
|
149
|
-
Client.restore([id1, id2, ..., idN])
|
150
|
-
```
|
151
|
-
|
152
|
-
If you want to restore a record and their dependently destroyed associated records:
|
153
|
-
|
154
|
-
```ruby
|
155
|
-
Client.restore(id, :recursive => true)
|
156
|
-
```
|
157
|
-
|
158
|
-
If you want callbacks to trigger before a restore:
|
159
|
-
|
160
|
-
```ruby
|
161
|
-
before_restore :callback_name_goes_here
|
162
|
-
```
|
163
|
-
|
164
|
-
For more information, please look at the tests.
|
165
|
-
|
166
|
-
## Acts As Paranoid Migration
|
167
|
-
|
168
71
|
You can replace the older acts_as_paranoid methods as follows:
|
169
72
|
|
170
73
|
| Old Syntax | New Syntax |
|
data/lib/paranoia.rb
CHANGED
@@ -1,162 +1,49 @@
|
|
1
|
-
require 'active_record' unless defined? ActiveRecord
|
2
|
-
|
3
1
|
module Paranoia
|
4
2
|
def self.included(klazz)
|
5
3
|
klazz.extend Query
|
6
|
-
klazz.extend Callbacks
|
7
4
|
end
|
8
5
|
|
9
6
|
module Query
|
10
|
-
def paranoid?
|
11
|
-
true
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
|
-
def with_deleted
|
16
|
-
scoped.tap { |x| x.default_scoped = false }
|
17
|
-
end
|
7
|
+
def paranoid? ; true ; end
|
18
8
|
|
19
9
|
def only_deleted
|
20
|
-
|
21
|
-
end
|
22
|
-
alias :deleted :only_deleted
|
23
|
-
|
24
|
-
def restore(id, opts = {})
|
25
|
-
if id.is_a?(Array)
|
26
|
-
id.map { |one_id| restore(one_id, opts) }
|
27
|
-
else
|
28
|
-
only_deleted.find(id).restore!(opts)
|
29
|
-
end
|
10
|
+
all.tap { |x| x.default_scoped = false }.where.not(deleted_at: nil)
|
30
11
|
end
|
31
|
-
end
|
32
12
|
|
33
|
-
|
34
|
-
|
35
|
-
klazz.define_callbacks :restore
|
36
|
-
|
37
|
-
klazz.define_singleton_method("before_restore") do |*args, &block|
|
38
|
-
set_callback(:restore, :before, *args, &block)
|
39
|
-
end
|
40
|
-
|
41
|
-
klazz.define_singleton_method("around_restore") do |*args, &block|
|
42
|
-
set_callback(:restore, :around, *args, &block)
|
43
|
-
end
|
44
|
-
|
45
|
-
klazz.define_singleton_method("after_restore") do |*args, &block|
|
46
|
-
set_callback(:restore, :after, *args, &block)
|
47
|
-
end
|
13
|
+
def with_deleted
|
14
|
+
all.tap { |x| x.default_scoped = false }
|
48
15
|
end
|
49
16
|
end
|
50
17
|
|
51
18
|
def destroy
|
52
|
-
|
53
|
-
callbacks_result ? self : false
|
19
|
+
run_callbacks(:destroy) { delete }
|
54
20
|
end
|
55
21
|
|
56
22
|
def delete
|
57
|
-
return if new_record?
|
58
|
-
|
23
|
+
return if new_record? or destroyed?
|
24
|
+
update_column :deleted_at, Time.now
|
59
25
|
end
|
60
26
|
|
61
|
-
def restore!
|
62
|
-
|
63
|
-
run_callbacks(:restore) do
|
64
|
-
update_column paranoia_column, nil
|
65
|
-
restore_associated_records if opts[:recursive]
|
66
|
-
end
|
67
|
-
end
|
27
|
+
def restore!
|
28
|
+
update_column :deleted_at, nil
|
68
29
|
end
|
69
|
-
alias :restore :restore!
|
70
30
|
|
71
31
|
def destroyed?
|
72
|
-
|
32
|
+
!self.deleted_at.nil?
|
73
33
|
end
|
74
|
-
|
75
34
|
alias :deleted? :destroyed?
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
# touch paranoia column.
|
80
|
-
# insert time to paranoia column.
|
81
|
-
# @param with_transaction [Boolean] exec with ActiveRecord Transactions.
|
82
|
-
def touch_paranoia_column(with_transaction=false)
|
83
|
-
# This method is (potentially) called from really_destroy
|
84
|
-
# The object the method is being called on may be frozen
|
85
|
-
# Let's not touch it if it's frozen.
|
86
|
-
unless self.frozen?
|
87
|
-
if with_transaction
|
88
|
-
with_transaction_returning_status { touch(paranoia_column) }
|
89
|
-
else
|
90
|
-
touch(paranoia_column)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
# restore associated records that have been soft deleted when
|
96
|
-
# we called #destroy
|
97
|
-
def restore_associated_records
|
98
|
-
destroyed_associations = self.class.reflect_on_all_associations.select do |association|
|
99
|
-
association.options[:dependent] == :destroy
|
100
|
-
end
|
101
|
-
|
102
|
-
destroyed_associations.each do |association|
|
103
|
-
association_data = send(association.name)
|
104
|
-
|
105
|
-
unless association_data.nil?
|
106
|
-
if association_data.paranoid?
|
107
|
-
if association.collection?
|
108
|
-
association_data.only_deleted.each { |record| record.restore(:recursive => true) }
|
109
|
-
else
|
110
|
-
association_data.restore(:recursive => true)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
35
|
end
|
117
36
|
|
118
37
|
class ActiveRecord::Base
|
119
|
-
def self.acts_as_paranoid
|
120
|
-
alias :
|
121
|
-
alias :
|
122
|
-
alias :destroy! :ar_destroy
|
123
|
-
alias :delete! :delete
|
124
|
-
def really_destroy!
|
125
|
-
dependent_reflections = self.reflections.select do |name, reflection|
|
126
|
-
reflection.options[:dependent] == :destroy
|
127
|
-
end
|
128
|
-
if dependent_reflections.any?
|
129
|
-
dependent_reflections.each do |name, _|
|
130
|
-
associated_records = self.send(name)
|
131
|
-
# Paranoid models will have this method, non-paranoid models will not
|
132
|
-
associated_records = associated_records.with_deleted if associated_records.respond_to?(:with_deleted)
|
133
|
-
associated_records.each(&:really_destroy!)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
destroy!
|
137
|
-
end
|
138
|
-
|
38
|
+
def self.acts_as_paranoid
|
39
|
+
alias :destroy! :destroy
|
40
|
+
alias :delete! :delete
|
139
41
|
include Paranoia
|
140
|
-
|
141
|
-
|
142
|
-
self.paranoia_column = options[:column] || :deleted_at
|
143
|
-
default_scope { where(self.quoted_table_name + ".#{paranoia_column} IS NULL") }
|
144
|
-
|
145
|
-
before_restore {
|
146
|
-
self.class.notify_observers(:before_restore, self) if self.class.respond_to?(:notify_observers)
|
147
|
-
}
|
148
|
-
after_restore {
|
149
|
-
self.class.notify_observers(:after_restore, self) if self.class.respond_to?(:notify_observers)
|
150
|
-
}
|
42
|
+
default_scope { where(:deleted_at => nil) }
|
151
43
|
end
|
152
44
|
|
153
|
-
def self.paranoid?
|
154
|
-
|
155
|
-
end
|
156
|
-
|
157
|
-
def paranoid?
|
158
|
-
self.class.paranoid?
|
159
|
-
end
|
45
|
+
def self.paranoid? ; false ; end
|
46
|
+
def paranoid? ; self.class.paranoid? ; end
|
160
47
|
|
161
48
|
# Override the persisted method to allow for the paranoia gem.
|
162
49
|
# If a paranoid record is selected, then we only want to check
|
@@ -164,12 +51,4 @@ class ActiveRecord::Base
|
|
164
51
|
def persisted?
|
165
52
|
paranoid? ? !new_record? : super
|
166
53
|
end
|
167
|
-
|
168
|
-
private
|
169
|
-
|
170
|
-
def paranoia_column
|
171
|
-
self.class.paranoia_column
|
172
|
-
end
|
173
54
|
end
|
174
|
-
|
175
|
-
require 'paranoia/rspec' if defined? RSpec
|
data/lib/paranoia/version.rb
CHANGED
data/paranoia.gemspec
CHANGED
@@ -1,25 +1,26 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
require File.expand_path(
|
2
|
+
require File.expand_path("../lib/paranoia/version", __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
|
-
s.name
|
6
|
-
s.version
|
7
|
-
s.platform
|
8
|
-
s.authors
|
9
|
-
s.email
|
10
|
-
s.homepage
|
11
|
-
s.summary
|
5
|
+
s.name = "paranoia"
|
6
|
+
s.version = Paranoia::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["radarlistener@gmail.com"]
|
9
|
+
s.email = []
|
10
|
+
s.homepage = "http://rubygems.org/gems/paranoia"
|
11
|
+
s.summary = "Paranoia is a re-implementation of acts_as_paranoid for Rails 3, using much, much, much less code."
|
12
12
|
s.description = "Paranoia is a re-implementation of acts_as_paranoid for Rails 3, using much, much, much less code. You would use either plugin / gem if you wished that when you called destroy on an Active Record object that it didn't actually destroy it, but just \"hid\" the record. Paranoia does this by setting a deleted_at field to the current time when you destroy a record, and hides it by scoping all queries on your model to only include records which do not have a deleted_at field."
|
13
13
|
|
14
|
-
s.required_rubygems_version =
|
15
|
-
s.rubyforge_project
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "paranoia"
|
16
16
|
|
17
|
-
s.add_dependency
|
17
|
+
s.add_dependency "activerecord", "~> 4.0"
|
18
18
|
|
19
|
-
s.add_development_dependency
|
20
|
-
s.add_development_dependency
|
19
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
20
|
+
s.add_development_dependency "sqlite3"
|
21
|
+
s.add_development_dependency "rake", "0.8.7"
|
21
22
|
|
22
|
-
s.files
|
23
|
-
s.executables
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
24
25
|
s.require_path = 'lib'
|
25
26
|
end
|
data/test/paranoia_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
require 'active_record'
|
3
|
-
require File.expand_path(File.dirname(__FILE__) +
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + "/../lib/paranoia")
|
4
4
|
|
5
5
|
DB_FILE = 'tmp/test_db'
|
6
6
|
|
@@ -10,17 +10,13 @@ FileUtils.rm_f DB_FILE
|
|
10
10
|
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => DB_FILE
|
11
11
|
ActiveRecord::Base.connection.execute 'CREATE TABLE parent_models (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)'
|
12
12
|
ActiveRecord::Base.connection.execute 'CREATE TABLE paranoid_models (id INTEGER NOT NULL PRIMARY KEY, parent_model_id INTEGER, deleted_at DATETIME)'
|
13
|
-
ActiveRecord::Base.connection.execute 'CREATE TABLE paranoid_model_with_belongs (id INTEGER NOT NULL PRIMARY KEY, parent_model_id INTEGER, deleted_at DATETIME, paranoid_model_with_has_one_id INTEGER)'
|
14
13
|
ActiveRecord::Base.connection.execute 'CREATE TABLE featureful_models (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME, name VARCHAR(32))'
|
15
14
|
ActiveRecord::Base.connection.execute 'CREATE TABLE plain_models (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)'
|
16
15
|
ActiveRecord::Base.connection.execute 'CREATE TABLE callback_models (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)'
|
17
|
-
ActiveRecord::Base.connection.execute 'CREATE TABLE fail_callback_models (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)'
|
18
16
|
ActiveRecord::Base.connection.execute 'CREATE TABLE related_models (id INTEGER NOT NULL PRIMARY KEY, parent_model_id INTEGER NOT NULL, deleted_at DATETIME)'
|
19
17
|
ActiveRecord::Base.connection.execute 'CREATE TABLE employers (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)'
|
20
18
|
ActiveRecord::Base.connection.execute 'CREATE TABLE employees (id INTEGER NOT NULL PRIMARY KEY, deleted_at DATETIME)'
|
21
19
|
ActiveRecord::Base.connection.execute 'CREATE TABLE jobs (id INTEGER NOT NULL PRIMARY KEY, employer_id INTEGER NOT NULL, employee_id INTEGER NOT NULL, deleted_at DATETIME)'
|
22
|
-
ActiveRecord::Base.connection.execute 'CREATE TABLE custom_column_models (id INTEGER NOT NULL PRIMARY KEY, destroyed_at DATETIME)'
|
23
|
-
ActiveRecord::Base.connection.execute 'CREATE TABLE non_paranoid_models (id INTEGER NOT NULL PRIMARY KEY, parent_model_id INTEGER)'
|
24
20
|
|
25
21
|
class ParanoiaTest < Test::Unit::TestCase
|
26
22
|
def test_plain_model_class_is_not_paranoid
|
@@ -63,37 +59,6 @@ class ParanoiaTest < Test::Unit::TestCase
|
|
63
59
|
assert_equal 0, model.class.unscoped.count
|
64
60
|
end
|
65
61
|
|
66
|
-
# Anti-regression test for #81, which would've introduced a bug to break this test.
|
67
|
-
def test_destroy_behavior_for_plain_models_callbacks
|
68
|
-
model = CallbackModel.new
|
69
|
-
model.save
|
70
|
-
model.remove_called_variables # clear called callback flags
|
71
|
-
model.destroy
|
72
|
-
|
73
|
-
assert_equal nil, model.instance_variable_get(:@update_callback_called)
|
74
|
-
assert_equal nil, model.instance_variable_get(:@save_callback_called)
|
75
|
-
assert_equal nil, model.instance_variable_get(:@validate_called)
|
76
|
-
|
77
|
-
assert model.instance_variable_get(:@destroy_callback_called)
|
78
|
-
assert model.instance_variable_get(:@after_destroy_callback_called)
|
79
|
-
assert model.instance_variable_get(:@after_commit_callback_called)
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
|
-
def test_delete_behavior_for_plain_models_callbacks
|
84
|
-
model = CallbackModel.new
|
85
|
-
model.save
|
86
|
-
model.remove_called_variables # clear called callback flags
|
87
|
-
model.delete
|
88
|
-
|
89
|
-
assert_equal nil, model.instance_variable_get(:@update_callback_called)
|
90
|
-
assert_equal nil, model.instance_variable_get(:@save_callback_called)
|
91
|
-
assert_equal nil, model.instance_variable_get(:@validate_called)
|
92
|
-
assert_equal nil, model.instance_variable_get(:@destroy_callback_called)
|
93
|
-
assert_equal nil, model.instance_variable_get(:@after_destroy_callback_called)
|
94
|
-
assert_equal nil, model.instance_variable_get(:@after_commit_callback_called)
|
95
|
-
end
|
96
|
-
|
97
62
|
def test_destroy_behavior_for_paranoid_models
|
98
63
|
model = ParanoidModel.new
|
99
64
|
assert_equal 0, model.class.count
|
@@ -102,12 +67,11 @@ class ParanoiaTest < Test::Unit::TestCase
|
|
102
67
|
model.destroy
|
103
68
|
|
104
69
|
assert_equal false, model.deleted_at.nil?
|
105
|
-
assert_equal false, model.really_destroyed?
|
106
70
|
|
107
71
|
assert_equal 0, model.class.count
|
108
72
|
assert_equal 1, model.class.unscoped.count
|
109
73
|
end
|
110
|
-
|
74
|
+
|
111
75
|
def test_scoping_behavior_for_paranoid_models
|
112
76
|
ParanoidModel.unscoped.delete_all
|
113
77
|
parent1 = ParentModel.create
|
@@ -118,27 +82,9 @@ class ParanoiaTest < Test::Unit::TestCase
|
|
118
82
|
p2.destroy
|
119
83
|
assert_equal 0, parent1.paranoid_models.count
|
120
84
|
assert_equal 1, parent1.paranoid_models.only_deleted.count
|
121
|
-
assert_equal 1, parent1.paranoid_models.deleted.count
|
122
85
|
p3 = ParanoidModel.create(:parent_model => parent1)
|
123
86
|
assert_equal 2, parent1.paranoid_models.with_deleted.count
|
124
|
-
assert_equal [p1,
|
125
|
-
end
|
126
|
-
|
127
|
-
def test_destroy_behavior_for_custom_column_models
|
128
|
-
model = CustomColumnModel.new
|
129
|
-
assert_equal 0, model.class.count
|
130
|
-
model.save!
|
131
|
-
assert_nil model.destroyed_at
|
132
|
-
assert_equal 1, model.class.count
|
133
|
-
model.destroy
|
134
|
-
|
135
|
-
assert_equal false, model.destroyed_at.nil?
|
136
|
-
assert model.destroyed?
|
137
|
-
|
138
|
-
assert_equal 0, model.class.count
|
139
|
-
assert_equal 1, model.class.unscoped.count
|
140
|
-
assert_equal 1, model.class.only_deleted.count
|
141
|
-
assert_equal 1, model.class.deleted.count
|
87
|
+
assert_equal [p1,p3], parent1.paranoid_models.with_deleted
|
142
88
|
end
|
143
89
|
|
144
90
|
def test_destroy_behavior_for_featureful_paranoid_models
|
@@ -156,8 +102,8 @@ class ParanoiaTest < Test::Unit::TestCase
|
|
156
102
|
|
157
103
|
# Regression test for #24
|
158
104
|
def test_chaining_for_paranoid_models
|
159
|
-
scope = FeaturefulModel.where(:name =>
|
160
|
-
assert_equal
|
105
|
+
scope = FeaturefulModel.where(:name => "foo").only_deleted
|
106
|
+
assert_equal "foo", scope.where_values_hash['name']
|
161
107
|
assert_equal 2, scope.where_values.count
|
162
108
|
end
|
163
109
|
|
@@ -170,7 +116,6 @@ class ParanoiaTest < Test::Unit::TestCase
|
|
170
116
|
|
171
117
|
assert_equal model, ParanoidModel.only_deleted.last
|
172
118
|
assert_equal false, ParanoidModel.only_deleted.include?(model2)
|
173
|
-
assert_equal false, ParanoidModel.deleted.include?(model2)
|
174
119
|
end
|
175
120
|
|
176
121
|
def test_default_scope_for_has_many_relationships
|
@@ -218,14 +163,14 @@ class ParanoiaTest < Test::Unit::TestCase
|
|
218
163
|
model = CallbackModel.new
|
219
164
|
model.save
|
220
165
|
model.delete
|
221
|
-
assert_equal nil, model.instance_variable_get(:@
|
166
|
+
assert_equal nil, model.instance_variable_get(:@callback_called)
|
222
167
|
end
|
223
168
|
|
224
169
|
def test_destroy_behavior_for_callbacks
|
225
170
|
model = CallbackModel.new
|
226
171
|
model.save
|
227
172
|
model.destroy
|
228
|
-
assert model.instance_variable_get(:@
|
173
|
+
assert model.instance_variable_get(:@callback_called)
|
229
174
|
end
|
230
175
|
|
231
176
|
def test_restore
|
@@ -243,201 +188,25 @@ class ParanoiaTest < Test::Unit::TestCase
|
|
243
188
|
assert_equal false, model.destroyed?
|
244
189
|
end
|
245
190
|
|
246
|
-
|
247
|
-
def test_destroy_twice
|
248
|
-
model = ParanoidModel.new
|
249
|
-
model.save
|
250
|
-
model.destroy
|
251
|
-
model.destroy
|
252
|
-
|
253
|
-
assert_equal 1, ParanoidModel.unscoped.where(id: model.id).count
|
254
|
-
end
|
255
|
-
|
256
|
-
def test_destroy_return_value_on_success
|
257
|
-
model = ParanoidModel.create
|
258
|
-
return_value = model.destroy
|
259
|
-
|
260
|
-
assert_equal(return_value, model)
|
261
|
-
end
|
262
|
-
|
263
|
-
def test_destroy_return_value_on_failure
|
264
|
-
model = FailCallbackModel.create
|
265
|
-
return_value = model.destroy
|
266
|
-
|
267
|
-
assert_equal(return_value, false)
|
268
|
-
end
|
269
|
-
|
270
|
-
def test_restore_behavior_for_callbacks
|
271
|
-
model = CallbackModel.new
|
272
|
-
model.save
|
273
|
-
id = model.id
|
274
|
-
model.destroy
|
275
|
-
|
276
|
-
assert model.destroyed?
|
277
|
-
|
278
|
-
model = CallbackModel.only_deleted.find(id)
|
279
|
-
model.restore!
|
280
|
-
model.reload
|
281
|
-
|
282
|
-
assert model.instance_variable_get(:@restore_callback_called)
|
283
|
-
end
|
284
|
-
|
285
|
-
def test_really_destroy
|
286
|
-
model = ParanoidModel.new
|
287
|
-
model.save
|
288
|
-
model.destroy!
|
289
|
-
|
290
|
-
assert_equal 0, ParanoidModel.unscoped.where(id: model.id).count
|
291
|
-
end
|
292
|
-
|
293
|
-
def test_really_destroyed
|
191
|
+
def test_real_destroy
|
294
192
|
model = ParanoidModel.new
|
295
193
|
model.save
|
296
194
|
model.destroy!
|
297
195
|
|
298
|
-
|
299
|
-
end
|
300
|
-
|
301
|
-
def test_real_destroy_dependent_destroy
|
302
|
-
parent = ParentModel.create
|
303
|
-
child = parent.very_related_models.create
|
304
|
-
parent.really_destroy!
|
305
|
-
refute RelatedModel.unscoped.exists?(child.id)
|
306
|
-
end
|
307
|
-
|
308
|
-
def test_real_destroy_dependent_destroy_after_normal_destroy
|
309
|
-
parent = ParentModel.create
|
310
|
-
child = parent.very_related_models.create
|
311
|
-
parent.destroy
|
312
|
-
parent.really_destroy!
|
313
|
-
refute RelatedModel.unscoped.exists?(child.id)
|
314
|
-
end
|
315
|
-
|
316
|
-
def test_real_destroy_dependent_destroy_after_normal_destroy_does_not_delete_other_children
|
317
|
-
parent_1 = ParentModel.create
|
318
|
-
child_1 = parent_1.very_related_models.create
|
319
|
-
|
320
|
-
parent_2 = ParentModel.create
|
321
|
-
child_2 = parent_2.very_related_models.create
|
322
|
-
parent_1.destroy
|
323
|
-
parent_1.really_destroy!
|
324
|
-
assert RelatedModel.unscoped.exists?(child_2.id)
|
196
|
+
refute ParanoidModel.unscoped.exists?(model.id)
|
325
197
|
end
|
326
198
|
|
327
199
|
def test_real_delete
|
328
200
|
model = ParanoidModel.new
|
329
201
|
model.save
|
330
202
|
model.delete!
|
331
|
-
assert_equal 0, ParanoidModel.unscoped.where(id: model.id).count
|
332
|
-
end
|
333
|
-
|
334
|
-
def test_multiple_restore
|
335
|
-
a = ParanoidModel.new
|
336
|
-
a.save
|
337
|
-
a_id = a.id
|
338
|
-
a.destroy
|
339
|
-
|
340
|
-
b = ParanoidModel.new
|
341
|
-
b.save
|
342
|
-
b_id = b.id
|
343
|
-
b.destroy
|
344
|
-
|
345
|
-
c = ParanoidModel.new
|
346
|
-
c.save
|
347
|
-
c_id = c.id
|
348
|
-
c.destroy
|
349
|
-
|
350
|
-
ParanoidModel.restore([a_id, c_id])
|
351
|
-
|
352
|
-
a.reload
|
353
|
-
b.reload
|
354
|
-
c.reload
|
355
|
-
|
356
|
-
refute a.destroyed?
|
357
|
-
assert b.destroyed?
|
358
|
-
refute c.destroyed?
|
359
|
-
end
|
360
|
-
|
361
|
-
def test_restore_with_associations
|
362
|
-
parent = ParentModel.create
|
363
|
-
first_child = parent.very_related_models.create
|
364
|
-
second_child = parent.non_paranoid_models.create
|
365
|
-
|
366
|
-
parent.destroy
|
367
|
-
assert_equal false, parent.deleted_at.nil?
|
368
|
-
assert_equal false, first_child.reload.deleted_at.nil?
|
369
|
-
assert_equal true, second_child.destroyed?
|
370
|
-
|
371
|
-
parent.restore!
|
372
|
-
assert_equal true, parent.deleted_at.nil?
|
373
|
-
assert_equal false, first_child.reload.deleted_at.nil?
|
374
|
-
assert_equal true, second_child.destroyed?
|
375
|
-
|
376
|
-
parent.destroy
|
377
|
-
parent.restore(:recursive => true)
|
378
|
-
assert_equal true, parent.deleted_at.nil?
|
379
|
-
assert_equal true, first_child.reload.deleted_at.nil?
|
380
|
-
assert_equal true, second_child.destroyed?
|
381
|
-
|
382
|
-
parent.destroy
|
383
|
-
ParentModel.restore(parent.id, :recursive => true)
|
384
|
-
assert_equal true, parent.reload.deleted_at.nil?
|
385
|
-
assert_equal true, first_child.reload.deleted_at.nil?
|
386
|
-
assert_equal true, second_child.destroyed?
|
387
|
-
end
|
388
|
-
|
389
|
-
# regression tests for #118
|
390
|
-
def test_restore_with_has_one_association
|
391
|
-
# setup and destroy test objects
|
392
|
-
hasOne = ParanoidModelWithHasOne.create
|
393
|
-
belongsTo = ParanoidModelWithBelong.create
|
394
|
-
hasOne.paranoid_model_with_belong = belongsTo
|
395
|
-
hasOne.save!
|
396
|
-
|
397
|
-
hasOne.destroy
|
398
|
-
assert_equal false, hasOne.deleted_at.nil?
|
399
|
-
assert_equal false, belongsTo.deleted_at.nil?
|
400
|
-
|
401
|
-
# Does it restore has_one associations?
|
402
|
-
hasOne.restore(:recursive => true)
|
403
|
-
hasOne.save!
|
404
|
-
|
405
|
-
assert_equal true, hasOne.reload.deleted_at.nil?
|
406
|
-
assert_equal true, belongsTo.reload.deleted_at.nil?, "#{belongsTo.deleted_at}"
|
407
|
-
assert ParanoidModelWithBelong.with_deleted.reload.count != 0, "There should be a record"
|
408
|
-
end
|
409
|
-
|
410
|
-
def test_restore_with_nil_has_one_association
|
411
|
-
# setup and destroy test object
|
412
|
-
hasOne = ParanoidModelWithHasOne.create
|
413
|
-
hasOne.destroy
|
414
|
-
assert_equal false, hasOne.reload.deleted_at.nil?
|
415
|
-
|
416
|
-
# Does it raise NoMethodException on restore of nil
|
417
|
-
hasOne.restore(:recursive => true)
|
418
|
-
|
419
|
-
assert hasOne.reload.deleted_at.nil?
|
420
|
-
end
|
421
|
-
|
422
|
-
def test_observers_notified
|
423
|
-
a = ParanoidModelWithObservers.create
|
424
|
-
a.destroy
|
425
|
-
a.restore!
|
426
203
|
|
427
|
-
|
428
|
-
assert a.observers_notified.select {|args| args == [:after_restore, a]}
|
429
|
-
end
|
430
|
-
|
431
|
-
def test_observers_not_notified_if_not_supported
|
432
|
-
a = ParanoidModelWithObservers.create
|
433
|
-
a.destroy
|
434
|
-
a.restore!
|
435
|
-
# essentially, we're just ensuring that this doesn't crash
|
204
|
+
refute ParanoidModel.unscoped.exists?(model.id)
|
436
205
|
end
|
437
206
|
|
438
207
|
private
|
439
208
|
def get_featureful_model
|
440
|
-
FeaturefulModel.new(:name =>
|
209
|
+
FeaturefulModel.new(:name => "not empty")
|
441
210
|
end
|
442
211
|
end
|
443
212
|
|
@@ -452,13 +221,6 @@ class ParanoidModel < ActiveRecord::Base
|
|
452
221
|
acts_as_paranoid
|
453
222
|
end
|
454
223
|
|
455
|
-
class FailCallbackModel < ActiveRecord::Base
|
456
|
-
belongs_to :parent_model
|
457
|
-
acts_as_paranoid
|
458
|
-
|
459
|
-
before_destroy { |_| false }
|
460
|
-
end
|
461
|
-
|
462
224
|
class FeaturefulModel < ActiveRecord::Base
|
463
225
|
acts_as_paranoid
|
464
226
|
validates :name, :presence => true, :uniqueness => true
|
@@ -469,26 +231,12 @@ end
|
|
469
231
|
|
470
232
|
class CallbackModel < ActiveRecord::Base
|
471
233
|
acts_as_paranoid
|
472
|
-
before_destroy {|model| model.instance_variable_set :@
|
473
|
-
before_restore {|model| model.instance_variable_set :@restore_callback_called, true }
|
474
|
-
before_update {|model| model.instance_variable_set :@update_callback_called, true }
|
475
|
-
before_save {|model| model.instance_variable_set :@save_callback_called, true}
|
476
|
-
|
477
|
-
after_destroy {|model| model.instance_variable_set :@after_destroy_callback_called, true }
|
478
|
-
after_commit {|model| model.instance_variable_set :@after_commit_callback_called, true }
|
479
|
-
|
480
|
-
validate {|model| model.instance_variable_set :@validate_called, true }
|
481
|
-
|
482
|
-
def remove_called_variables
|
483
|
-
instance_variables.each {|name| (name.to_s.end_with?('_called')) ? remove_instance_variable(name) : nil}
|
484
|
-
end
|
234
|
+
before_destroy {|model| model.instance_variable_set :@callback_called, true }
|
485
235
|
end
|
486
236
|
|
487
237
|
class ParentModel < ActiveRecord::Base
|
488
238
|
acts_as_paranoid
|
489
239
|
has_many :related_models
|
490
|
-
has_many :very_related_models, :class_name => 'RelatedModel', dependent: :destroy
|
491
|
-
has_many :non_paranoid_models, dependent: :destroy
|
492
240
|
end
|
493
241
|
|
494
242
|
class RelatedModel < ActiveRecord::Base
|
@@ -513,34 +261,3 @@ class Job < ActiveRecord::Base
|
|
513
261
|
belongs_to :employer
|
514
262
|
belongs_to :employee
|
515
263
|
end
|
516
|
-
|
517
|
-
class CustomColumnModel < ActiveRecord::Base
|
518
|
-
acts_as_paranoid column: :destroyed_at
|
519
|
-
end
|
520
|
-
|
521
|
-
class NonParanoidModel < ActiveRecord::Base
|
522
|
-
end
|
523
|
-
|
524
|
-
class ParanoidModelWithObservers < ParanoidModel
|
525
|
-
def observers_notified
|
526
|
-
@observers_notified ||= []
|
527
|
-
end
|
528
|
-
|
529
|
-
def self.notify_observer(*args)
|
530
|
-
observers_notified << args
|
531
|
-
end
|
532
|
-
end
|
533
|
-
|
534
|
-
class ParanoidModelWithoutObservers < ParanoidModel
|
535
|
-
self.class.send(remove_method :notify_observers) if method_defined?(:notify_observers)
|
536
|
-
end
|
537
|
-
|
538
|
-
# refer back to regression test for #118
|
539
|
-
class ParanoidModelWithHasOne < ParanoidModel
|
540
|
-
has_one :paranoid_model_with_belong, :dependent => :destroy
|
541
|
-
end
|
542
|
-
|
543
|
-
class ParanoidModelWithBelong < ActiveRecord::Base
|
544
|
-
acts_as_paranoid
|
545
|
-
belongs_to :paranoid_model_with_has_one
|
546
|
-
end
|
metadata
CHANGED
@@ -1,57 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paranoia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- radarlistener@gmail.com
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2013-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '4.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '4.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 1.0.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 1.0.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: sqlite3
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.8.7
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.8.7
|
55
69
|
description: Paranoia is a re-implementation of acts_as_paranoid for Rails 3, using
|
56
70
|
much, much, much less code. You would use either plugin / gem if you wished that
|
57
71
|
when you called destroy on an Active Record object that it didn't actually destroy
|
@@ -63,14 +77,12 @@ executables: []
|
|
63
77
|
extensions: []
|
64
78
|
extra_rdoc_files: []
|
65
79
|
files:
|
66
|
-
-
|
67
|
-
- ".travis.yml"
|
80
|
+
- .gitignore
|
68
81
|
- Gemfile
|
69
82
|
- LICENSE
|
70
83
|
- README.md
|
71
84
|
- Rakefile
|
72
85
|
- lib/paranoia.rb
|
73
|
-
- lib/paranoia/rspec.rb
|
74
86
|
- lib/paranoia/version.rb
|
75
87
|
- paranoia.gemspec
|
76
88
|
- test/paranoia_test.rb
|
@@ -83,17 +95,17 @@ require_paths:
|
|
83
95
|
- lib
|
84
96
|
required_ruby_version: !ruby/object:Gem::Requirement
|
85
97
|
requirements:
|
86
|
-
- -
|
98
|
+
- - '>='
|
87
99
|
- !ruby/object:Gem::Version
|
88
100
|
version: '0'
|
89
101
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
102
|
requirements:
|
91
|
-
- -
|
103
|
+
- - '>='
|
92
104
|
- !ruby/object:Gem::Version
|
93
105
|
version: 1.3.6
|
94
106
|
requirements: []
|
95
107
|
rubyforge_project: paranoia
|
96
|
-
rubygems_version: 2.
|
108
|
+
rubygems_version: 2.0.0
|
97
109
|
signing_key:
|
98
110
|
specification_version: 4
|
99
111
|
summary: Paranoia is a re-implementation of acts_as_paranoid for Rails 3, using much,
|
data/.travis.yml
DELETED
data/lib/paranoia/rspec.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'rspec/expectations'
|
2
|
-
|
3
|
-
# Validate the subject's class did call "acts_as_paranoid"
|
4
|
-
RSpec::Matchers.define :act_as_paranoid do
|
5
|
-
match { |subject| subject.class.ancestors.include?(Paranoia) }
|
6
|
-
|
7
|
-
failure_message { "expected #{subject.class} to use `acts_as_paranoid`" }
|
8
|
-
failure_message_when_negated { "expected #{subject.class} not to use `acts_as_paranoid`" }
|
9
|
-
|
10
|
-
# RSpec 2 compatibility:
|
11
|
-
alias_method :failure_message_for_should, :failure_message
|
12
|
-
alias_method :failure_message_for_should_not, :failure_message_when_negated
|
13
|
-
end
|