acts_as_paranoid 0.5.0.beta2 → 0.5.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +41 -16
- data/lib/acts_as_paranoid.rb +8 -3
- data/lib/acts_as_paranoid/core.rb +29 -16
- data/lib/acts_as_paranoid/preloader_association.rb +15 -0
- data/lib/acts_as_paranoid/validations.rb +59 -25
- data/lib/acts_as_paranoid/version.rb +1 -1
- data/test/test_core.rb +42 -2
- data/test/test_helper.rb +53 -4
- data/test/test_preloader_association.rb +27 -0
- metadata +27 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 124d271ce76db90e3e605685839c061359d22ff6
|
4
|
+
data.tar.gz: 18fd8e01afccccf40e31b722bad341434c2d1899
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 113820d1b627fecfe8167342678b992b39af55758e82e2e5115e4ab9b69831d950fd605cc40cb2668178b37e83b6a0e80b68240a9fbee9b65982eeb365ab0c02
|
7
|
+
data.tar.gz: ddecec89fcc2e85ad58237bac886cc6bf072c28d5bf249cdc4714f3ab356275d0ceee470fafac867966c976452260f8022d53e10e5b750aa7d16fa8a38c9c2be
|
data/README.md
CHANGED
@@ -8,9 +8,9 @@ This gem can be used to hide records instead of deleting them, making them recov
|
|
8
8
|
|
9
9
|
## Support
|
10
10
|
|
11
|
-
**This branch targets Rails 4.x
|
11
|
+
**This branch targets Rails 4.x. and 5.x**
|
12
12
|
|
13
|
-
If you're working with another version, switch to the corresponding branch, or require an older version of the acts_as_paranoid gem.
|
13
|
+
If you're working with another version, switch to the corresponding branch, or require an older version of the `acts_as_paranoid` gem.
|
14
14
|
|
15
15
|
## Usage
|
16
16
|
|
@@ -37,12 +37,18 @@ The values shown are the defaults. While *column* can be anything (as long as it
|
|
37
37
|
|
38
38
|
If your column type is a `string`, you can also specify which value to use when marking an object as deleted by passing `:deleted_value` (default is "deleted"). Any records with a non-matching value in this column will be treated normally (ie: not deleted).
|
39
39
|
|
40
|
+
If your column type is a `boolean`, it is possible to specify `allow_nulls` option which is `true` by default. When set to `false`, entities that have `false` value in this column will be considered not deleted, and those which have `true` will be considered deleted. When `true` everything that has a not-null value will be considered deleted.
|
41
|
+
|
40
42
|
### Filtering
|
41
43
|
|
42
|
-
If a record is deleted by ActsAsParanoid, it won't be retrieved when accessing the database.
|
44
|
+
If a record is deleted by ActsAsParanoid, it won't be retrieved when accessing the database.
|
45
|
+
|
46
|
+
So, `Paranoiac.all` will **not** include the **deleted records**.
|
47
|
+
|
48
|
+
When you want to access them, you have 2 choices:
|
43
49
|
|
44
50
|
```ruby
|
45
|
-
Paranoiac.only_deleted # retrieves the deleted records
|
51
|
+
Paranoiac.only_deleted # retrieves only the deleted records
|
46
52
|
Paranoiac.with_deleted # retrieves all records, deleted or not
|
47
53
|
```
|
48
54
|
|
@@ -67,7 +73,13 @@ paranoiac.destroy!
|
|
67
73
|
Paranoiac.delete_all!(conditions)
|
68
74
|
```
|
69
75
|
|
70
|
-
You can also permanently delete a record by calling `
|
76
|
+
You can also permanently delete a record by calling `destroy_fully!` on the object.
|
77
|
+
|
78
|
+
Alternatively you can permanently delete a record by calling `destroy` or `delete_all` on the object **twice**.
|
79
|
+
|
80
|
+
If a record was already deleted (hidden by `ActsAsParanoid`) and you delete it again, it will be removed from the database.
|
81
|
+
|
82
|
+
Take this example:
|
71
83
|
|
72
84
|
```ruby
|
73
85
|
p = Paranoiac.first
|
@@ -83,7 +95,9 @@ Recovery is easy. Just invoke `recover` on it, like this:
|
|
83
95
|
Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover
|
84
96
|
```
|
85
97
|
|
86
|
-
All associations marked as `:dependent => :destroy` are also recursively recovered.
|
98
|
+
All associations marked as `:dependent => :destroy` are also recursively recovered.
|
99
|
+
|
100
|
+
If you would like to disable this behavior, you can call `recover` with the `recursive` option:
|
87
101
|
|
88
102
|
```ruby
|
89
103
|
Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover(:recursive => false)
|
@@ -97,7 +111,13 @@ class Paranoiac < ActiveRecord::Base
|
|
97
111
|
end
|
98
112
|
```
|
99
113
|
|
100
|
-
By default, dependent records will be recovered if they were deleted within 2 minutes of the object upon which they depend.
|
114
|
+
By default, dependent records will be recovered if they were deleted within 2 minutes of the object upon which they depend.
|
115
|
+
|
116
|
+
This restores the objects to the state before the recursive deletion without restoring other objects that were deleted earlier.
|
117
|
+
|
118
|
+
The behavior is only available when both parent and dependant are using timestamp fields to mark deletion, which is the default behavior.
|
119
|
+
|
120
|
+
This window can be changed with the `dependent_recovery_window` option:
|
101
121
|
|
102
122
|
```ruby
|
103
123
|
class Paranoiac < ActiveRecord::Base
|
@@ -125,9 +145,9 @@ ActiveRecord's built-in uniqueness validation does not account for records delet
|
|
125
145
|
|
126
146
|
```ruby
|
127
147
|
class Paranoiac < ActiveRecord::Base
|
128
|
-
|
129
|
-
|
130
|
-
|
148
|
+
acts_as_paranoid
|
149
|
+
validates_as_paranoid
|
150
|
+
validates_uniqueness_of_without_deleted :name
|
131
151
|
end
|
132
152
|
|
133
153
|
p1 = Paranoiac.create(:name => 'foo')
|
@@ -150,13 +170,15 @@ Paranoiac.with_deleted.first.deleted? #=> true
|
|
150
170
|
|
151
171
|
### Scopes
|
152
172
|
|
153
|
-
As you've probably guessed, `with_deleted` and `only_deleted` are scopes. You can, however, chain them freely with other scopes you might have.
|
173
|
+
As you've probably guessed, `with_deleted` and `only_deleted` are scopes. You can, however, chain them freely with other scopes you might have.
|
174
|
+
|
175
|
+
For example:
|
154
176
|
|
155
177
|
```ruby
|
156
178
|
Paranoiac.pretty.with_deleted
|
157
179
|
```
|
158
180
|
|
159
|
-
is exactly the same as
|
181
|
+
This is exactly the same as:
|
160
182
|
|
161
183
|
```ruby
|
162
184
|
Paranoiac.with_deleted.pretty
|
@@ -166,8 +188,8 @@ You can work freely with scopes and it will just work:
|
|
166
188
|
|
167
189
|
```ruby
|
168
190
|
class Paranoiac < ActiveRecord::Base
|
169
|
-
|
170
|
-
|
191
|
+
acts_as_paranoid
|
192
|
+
scope :pretty, where(:pretty => true)
|
171
193
|
end
|
172
194
|
|
173
195
|
Paranoiac.create(:pretty => true)
|
@@ -185,7 +207,9 @@ Paranoiac.pretty.only_deleted.count #=> 1
|
|
185
207
|
|
186
208
|
### Associations
|
187
209
|
|
188
|
-
Associations are also supported.
|
210
|
+
Associations are also supported.
|
211
|
+
|
212
|
+
From the simplest behaviors you'd expect to more nifty things like the ones mentioned previously or the usage of the `:with_deleted` option with `belongs_to`
|
189
213
|
|
190
214
|
```ruby
|
191
215
|
class Parent < ActiveRecord::Base
|
@@ -197,7 +221,7 @@ class ParanoiacChild < ActiveRecord::Base
|
|
197
221
|
belongs_to :parent
|
198
222
|
|
199
223
|
# You may need to provide a foreign_key like this
|
200
|
-
belongs_to :parent_including_deleted, :class_name => "Parent", foreign_key => 'parent_id', :with_deleted => true
|
224
|
+
belongs_to :parent_including_deleted, :class_name => "Parent", :foreign_key => 'parent_id', :with_deleted => true
|
201
225
|
end
|
202
226
|
|
203
227
|
parent = Parent.first
|
@@ -231,5 +255,6 @@ Watch out for these caveats:
|
|
231
255
|
* To [Gonçalo Silva](https://github.com/goncalossilva) for supporting this gem prior to v0.4.3
|
232
256
|
* To [Jean Boussier](https://github.com/byroot) for initial Rails 4.0.0 support
|
233
257
|
* To [Matijs van Zuijlen](https://github.com/mvz) for Rails 4.1 and 4.2 support
|
258
|
+
* To [Andrey Ponomarenko](https://github.com/sjke) for Rails 5 support
|
234
259
|
|
235
260
|
See `LICENSE`.
|
data/lib/acts_as_paranoid.rb
CHANGED
@@ -2,6 +2,7 @@ require 'acts_as_paranoid/core'
|
|
2
2
|
require 'acts_as_paranoid/associations'
|
3
3
|
require 'acts_as_paranoid/validations'
|
4
4
|
require 'acts_as_paranoid/relation'
|
5
|
+
require 'acts_as_paranoid/preloader_association'
|
5
6
|
|
6
7
|
module ActsAsParanoid
|
7
8
|
|
@@ -20,6 +21,7 @@ module ActsAsParanoid
|
|
20
21
|
|
21
22
|
self.paranoid_configuration = { :column => "deleted_at", :column_type => "time", :recover_dependent_associations => true, :dependent_recovery_window => 2.minutes }
|
22
23
|
self.paranoid_configuration.merge!({ :deleted_value => "deleted" }) if options[:column_type] == "string"
|
24
|
+
self.paranoid_configuration.merge!({ :allow_nulls => true }) if options[:column_type] == "boolean"
|
23
25
|
self.paranoid_configuration.merge!(options) # user options
|
24
26
|
|
25
27
|
raise ArgumentError, "'time', 'boolean' or 'string' expected for :column_type option, got #{paranoid_configuration[:column_type]}" unless ['time', 'boolean', 'string'].include? paranoid_configuration[:column_type]
|
@@ -31,15 +33,15 @@ module ActsAsParanoid
|
|
31
33
|
include ActsAsParanoid::Core
|
32
34
|
|
33
35
|
# Magic!
|
34
|
-
default_scope { where(
|
36
|
+
default_scope { where(paranoid_default_scope) }
|
35
37
|
|
36
38
|
if paranoid_configuration[:column_type] == 'time'
|
37
39
|
scope :deleted_inside_time_window, lambda {|time, window|
|
38
40
|
deleted_after_time((time - window)).deleted_before_time((time + window))
|
39
41
|
}
|
40
42
|
|
41
|
-
scope :deleted_after_time, lambda { |time| where("#{paranoid_column} > ?", time) }
|
42
|
-
scope :deleted_before_time, lambda { |time| where("#{paranoid_column} < ?", time) }
|
43
|
+
scope :deleted_after_time, lambda { |time| where("#{self.table_name}.#{paranoid_column} > ?", time) }
|
44
|
+
scope :deleted_before_time, lambda { |time| where("#{self.table_name}.#{paranoid_column} < ?", time) }
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
@@ -55,3 +57,6 @@ ActiveRecord::Relation.send :include, ActsAsParanoid::Relation
|
|
55
57
|
|
56
58
|
# Push the recover callback onto the activerecord callback list
|
57
59
|
ActiveRecord::Callbacks::CALLBACKS.push(:before_recover, :after_recover)
|
60
|
+
|
61
|
+
# Use with_deleted in preloader build_scope
|
62
|
+
ActiveRecord::Associations::Preloader::Association.send :include, ActsAsParanoid::PreloaderAssociation
|
@@ -23,9 +23,11 @@ module ActsAsParanoid
|
|
23
23
|
|
24
24
|
def only_deleted
|
25
25
|
if string_type_with_deleted_value?
|
26
|
-
without_paranoid_default_scope.where(
|
26
|
+
without_paranoid_default_scope.where(paranoid_column_reference => paranoid_configuration[:deleted_value])
|
27
|
+
elsif boolean_type_not_nullable?
|
28
|
+
without_paranoid_default_scope.where(paranoid_column_reference => true)
|
27
29
|
else
|
28
|
-
without_paranoid_default_scope.where(
|
30
|
+
without_paranoid_default_scope.where.not(paranoid_column_reference => nil)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
@@ -37,13 +39,14 @@ module ActsAsParanoid
|
|
37
39
|
where(conditions).update_all(["#{paranoid_configuration[:column]} = ?", delete_now_value])
|
38
40
|
end
|
39
41
|
|
40
|
-
def
|
42
|
+
def paranoid_default_scope
|
41
43
|
if string_type_with_deleted_value?
|
42
44
|
self.all.table[paranoid_column].eq(nil).
|
43
|
-
or(self.all.table[paranoid_column].not_eq(paranoid_configuration[:deleted_value]))
|
44
|
-
|
45
|
+
or(self.all.table[paranoid_column].not_eq(paranoid_configuration[:deleted_value]))
|
46
|
+
elsif boolean_type_not_nullable?
|
47
|
+
self.all.table[paranoid_column].eq(false)
|
45
48
|
else
|
46
|
-
self.all.table[paranoid_column].eq(nil)
|
49
|
+
self.all.table[paranoid_column].eq(nil)
|
47
50
|
end
|
48
51
|
end
|
49
52
|
|
@@ -51,6 +54,10 @@ module ActsAsParanoid
|
|
51
54
|
paranoid_column_type == :string && !paranoid_configuration[:deleted_value].nil?
|
52
55
|
end
|
53
56
|
|
57
|
+
def boolean_type_not_nullable?
|
58
|
+
paranoid_column_type == :boolean && !paranoid_configuration[:allow_nulls]
|
59
|
+
end
|
60
|
+
|
54
61
|
def paranoid_column
|
55
62
|
paranoid_configuration[:column].to_sym
|
56
63
|
end
|
@@ -75,12 +82,15 @@ module ActsAsParanoid
|
|
75
82
|
|
76
83
|
def without_paranoid_default_scope
|
77
84
|
scope = self.all
|
78
|
-
|
79
|
-
|
80
|
-
|
85
|
+
|
86
|
+
if ActiveRecord::VERSION::MAJOR < 5
|
87
|
+
# ActiveRecord 4.0.*
|
88
|
+
scope = scope.with_default_scope if ActiveRecord::VERSION::MINOR < 1
|
89
|
+
scope.where_values.delete(paranoid_default_scope)
|
81
90
|
else
|
82
|
-
scope = scope.
|
83
|
-
|
91
|
+
scope = scope.unscope(where: paranoid_default_scope)
|
92
|
+
# Fix problems with unscope group chain
|
93
|
+
scope = scope.unscoped if scope.to_sql.include? paranoid_default_scope.to_sql
|
84
94
|
end
|
85
95
|
|
86
96
|
scope
|
@@ -122,9 +132,7 @@ module ActsAsParanoid
|
|
122
132
|
end
|
123
133
|
end
|
124
134
|
|
125
|
-
|
126
|
-
destroy!
|
127
|
-
end
|
135
|
+
alias_method :destroy, :destroy!
|
128
136
|
|
129
137
|
def recover(options={})
|
130
138
|
options = {
|
@@ -179,8 +187,13 @@ module ActsAsParanoid
|
|
179
187
|
end
|
180
188
|
|
181
189
|
def deleted?
|
182
|
-
!
|
183
|
-
|
190
|
+
!if self.class.string_type_with_deleted_value?
|
191
|
+
paranoid_value != self.class.delete_now_value || paranoid_value.nil?
|
192
|
+
elsif self.class.boolean_type_not_nullable?
|
193
|
+
paranoid_value == false
|
194
|
+
else
|
195
|
+
paranoid_value.nil?
|
196
|
+
end
|
184
197
|
end
|
185
198
|
|
186
199
|
alias_method :destroyed?, :deleted?
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActsAsParanoid
|
2
|
+
module PreloaderAssociation
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
def build_scope_with_deleted
|
6
|
+
scope = build_scope_without_deleted
|
7
|
+
scope = scope.with_deleted if options[:with_deleted] && klass.respond_to?(:with_deleted)
|
8
|
+
scope
|
9
|
+
end
|
10
|
+
|
11
|
+
alias_method_chain :build_scope, :deleted
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -6,42 +6,76 @@ module ActsAsParanoid
|
|
6
6
|
base.extend ClassMethods
|
7
7
|
end
|
8
8
|
|
9
|
-
class UniquenessWithoutDeletedValidator
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
coder = record.class.column_types[attribute.to_s]
|
16
|
-
|
17
|
-
if value && coder
|
18
|
-
value = if coder.respond_to? :type_cast_for_database
|
19
|
-
coder.type_cast_for_database value
|
20
|
-
else
|
21
|
-
coder.type_cast_for_write value
|
22
|
-
end
|
9
|
+
class UniquenessWithoutDeletedValidator
|
10
|
+
def self.[](version)
|
11
|
+
version = version.to_s
|
12
|
+
name = "V#{version.tr('.', '_')}"
|
13
|
+
unless constants.include? name.to_sym
|
14
|
+
raise "Unknown validator version #{version.inspect}; expected one of #{constants.sort.join(', ')}"
|
23
15
|
end
|
16
|
+
const_get name
|
17
|
+
end
|
18
|
+
|
19
|
+
class V5 < ActiveRecord::Validations::UniquenessValidator
|
20
|
+
def validate_each(record, attribute, value)
|
21
|
+
finder_class = find_finder_class_for(record)
|
22
|
+
table = finder_class.arel_table
|
23
|
+
|
24
|
+
coder = record.class.attribute_types[attribute.to_s]
|
25
|
+
value = coder.type_cast_for_schema value if value && coder
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
relation = build_relation(finder_class, table, attribute, value)
|
28
|
+
[Array(finder_class.primary_key), Array(record.send(:id))].transpose.each do |pk_key, pk_value|
|
29
|
+
relation = relation.where(table[pk_key.to_sym].not_eq(pk_value))
|
30
|
+
end if record.persisted?
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
Array.wrap(options[:scope]).each do |scope_item|
|
33
|
+
relation = relation.where(table[scope_item].eq(record.public_send(scope_item)))
|
34
|
+
end
|
35
|
+
|
36
|
+
if relation.where(finder_class.paranoid_default_scope).where(relation).exists?
|
37
|
+
record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
|
38
|
+
end
|
33
39
|
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class V4 < ActiveRecord::Validations::UniquenessValidator
|
43
|
+
def validate_each(record, attribute, value)
|
44
|
+
finder_class = find_finder_class_for(record)
|
45
|
+
table = finder_class.arel_table
|
46
|
+
|
47
|
+
# TODO: Use record.class.column_types[attribute.to_s].coder ?
|
48
|
+
coder = record.class.column_types[attribute.to_s]
|
49
|
+
|
50
|
+
if value && coder
|
51
|
+
value = if coder.respond_to? :type_cast_for_database
|
52
|
+
coder.type_cast_for_database value
|
53
|
+
else
|
54
|
+
coder.type_cast_for_write value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
relation = build_relation(finder_class, table, attribute, value)
|
59
|
+
[Array(finder_class.primary_key), Array(record.send(:id))].transpose.each do |pk_key, pk_value|
|
60
|
+
relation = relation.and(table[pk_key.to_sym].not_eq(pk_value))
|
61
|
+
end if record.persisted?
|
62
|
+
|
63
|
+
Array.wrap(options[:scope]).each do |scope_item|
|
64
|
+
scope_value = record.send(scope_item)
|
65
|
+
relation = relation.and(table[scope_item].eq(scope_value))
|
66
|
+
end
|
34
67
|
|
35
|
-
|
36
|
-
|
37
|
-
|
68
|
+
# Re-add ActsAsParanoid default scope conditions manually.
|
69
|
+
if finder_class.unscoped.where(finder_class.paranoid_default_scope).where(relation).exists?
|
70
|
+
record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
|
71
|
+
end
|
38
72
|
end
|
39
73
|
end
|
40
74
|
end
|
41
75
|
|
42
76
|
module ClassMethods
|
43
77
|
def validates_uniqueness_of_without_deleted(*attr_names)
|
44
|
-
validates_with UniquenessWithoutDeletedValidator, _merge_attributes(attr_names)
|
78
|
+
validates_with UniquenessWithoutDeletedValidator[ActiveRecord::VERSION::MAJOR], _merge_attributes(attr_names)
|
45
79
|
end
|
46
80
|
end
|
47
81
|
end
|
data/test/test_core.rb
CHANGED
@@ -304,8 +304,8 @@ class ParanoidTest < ParanoidBaseTest
|
|
304
304
|
@paranoid_with_callback.recover
|
305
305
|
end
|
306
306
|
|
307
|
-
|
308
|
-
|
307
|
+
assert @paranoid_with_callback.called_before_recover
|
308
|
+
assert @paranoid_with_callback.called_after_recover
|
309
309
|
end
|
310
310
|
|
311
311
|
def test_delete_by_multiple_id_is_paranoid
|
@@ -393,4 +393,44 @@ class ParanoidTest < ParanoidBaseTest
|
|
393
393
|
2.times { ps.destroy }
|
394
394
|
assert_equal 0, ParanoidString.with_deleted.where(:id => ps).count
|
395
395
|
end
|
396
|
+
|
397
|
+
# Test boolean type columns, that are not nullable
|
398
|
+
def test_boolean_type_with_no_nil_value_before_destroy
|
399
|
+
ps = ParanoidBooleanNotNullable.create!()
|
400
|
+
assert_equal 1, ParanoidBooleanNotNullable.where(:id => ps).count
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_boolean_type_with_no_nil_value_after_destroy
|
404
|
+
ps = ParanoidBooleanNotNullable.create!()
|
405
|
+
ps.destroy
|
406
|
+
assert_equal 0, ParanoidBooleanNotNullable.where(:id => ps).count
|
407
|
+
end
|
408
|
+
|
409
|
+
def test_boolean_type_with_no_nil_value_before_destroy_with_deleted
|
410
|
+
ps = ParanoidBooleanNotNullable.create!()
|
411
|
+
assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(:id => ps).count
|
412
|
+
end
|
413
|
+
|
414
|
+
def test_boolean_type_with_no_nil_value_after_destroy_with_deleted
|
415
|
+
ps = ParanoidBooleanNotNullable.create!()
|
416
|
+
ps.destroy
|
417
|
+
assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(:id => ps).count
|
418
|
+
end
|
419
|
+
|
420
|
+
def test_boolean_type_with_no_nil_value_before_destroy_only_deleted
|
421
|
+
ps = ParanoidBooleanNotNullable.create!()
|
422
|
+
assert_equal 0, ParanoidBooleanNotNullable.only_deleted.where(:id => ps).count
|
423
|
+
end
|
424
|
+
|
425
|
+
def test_boolean_type_with_no_nil_value_after_destroy_only_deleted
|
426
|
+
ps = ParanoidBooleanNotNullable.create!()
|
427
|
+
ps.destroy
|
428
|
+
assert_equal 1, ParanoidBooleanNotNullable.only_deleted.where(:id => ps).count
|
429
|
+
end
|
430
|
+
|
431
|
+
def test_boolean_type_with_no_nil_value_after_destroyed_twice
|
432
|
+
ps = ParanoidBooleanNotNullable.create!()
|
433
|
+
2.times { ps.destroy }
|
434
|
+
assert_equal 0, ParanoidBooleanNotNullable.with_deleted.where(:id => ps).count
|
435
|
+
end
|
396
436
|
end
|
data/test/test_helper.rb
CHANGED
@@ -111,14 +111,14 @@ def setup_db
|
|
111
111
|
|
112
112
|
create_table :super_paranoids do |t|
|
113
113
|
t.string :type
|
114
|
-
t.references :has_many_inherited_super_paranoidz
|
114
|
+
t.references :has_many_inherited_super_paranoidz, index: { name: 'index__sp_id_on_has_many_isp' }
|
115
115
|
t.datetime :deleted_at
|
116
116
|
|
117
117
|
timestamps t
|
118
118
|
end
|
119
119
|
|
120
120
|
create_table :has_many_inherited_super_paranoidzs do |t|
|
121
|
-
t.references :super_paranoidz
|
121
|
+
t.references :super_paranoidz, index: { name: 'index_has_many_isp_on_sp_id' }
|
122
122
|
t.datetime :deleted_at
|
123
123
|
|
124
124
|
timestamps t
|
@@ -181,6 +181,33 @@ def setup_db
|
|
181
181
|
t.string :paranoid_thing_type
|
182
182
|
t.datetime :deleted_at
|
183
183
|
end
|
184
|
+
|
185
|
+
create_table :paranoid_boolean_not_nullables do |t|
|
186
|
+
t.string :name
|
187
|
+
t.boolean :deleted, :boolean, :null => false, :default => false
|
188
|
+
end
|
189
|
+
|
190
|
+
create_table :paranoid_belongs_to_polymorphics do |t|
|
191
|
+
t.string :name
|
192
|
+
t.string :parent_type
|
193
|
+
t.integer :parent_id
|
194
|
+
t.datetime :deleted_at
|
195
|
+
|
196
|
+
t.timestamps
|
197
|
+
end
|
198
|
+
|
199
|
+
create_table :not_paranoid_has_many_as_parents do |t|
|
200
|
+
t.string :name
|
201
|
+
|
202
|
+
t.timestamps
|
203
|
+
end
|
204
|
+
|
205
|
+
create_table :paranoid_has_many_as_parents do |t|
|
206
|
+
t.string :name
|
207
|
+
t.datetime :deleted_at
|
208
|
+
|
209
|
+
t.timestamps
|
210
|
+
end
|
184
211
|
end
|
185
212
|
end
|
186
213
|
|
@@ -190,9 +217,12 @@ def timestamps(table)
|
|
190
217
|
end
|
191
218
|
|
192
219
|
def teardown_db
|
193
|
-
ActiveRecord::
|
194
|
-
ActiveRecord::Base.connection.
|
220
|
+
tables = if ActiveRecord::VERSION::MAJOR < 5
|
221
|
+
ActiveRecord::Base.connection.tables
|
222
|
+
else
|
223
|
+
ActiveRecord::Base.connection.data_sources
|
195
224
|
end
|
225
|
+
tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
|
196
226
|
end
|
197
227
|
|
198
228
|
class ParanoidTime < ActiveRecord::Base
|
@@ -351,6 +381,20 @@ class ParanoidWithScopedValidation < ActiveRecord::Base
|
|
351
381
|
validates_uniqueness_of :name, :scope => :category
|
352
382
|
end
|
353
383
|
|
384
|
+
class ParanoidBelongsToPolymorphic < ActiveRecord::Base
|
385
|
+
acts_as_paranoid
|
386
|
+
belongs_to :parent, :polymorphic => true, :with_deleted => true
|
387
|
+
end
|
388
|
+
|
389
|
+
class NotParanoidHasManyAsParent < ActiveRecord::Base
|
390
|
+
has_many :paranoid_belongs_to_polymorphics, :as => :parent, :dependent => :destroy
|
391
|
+
end
|
392
|
+
|
393
|
+
class ParanoidHasManyAsParent < ActiveRecord::Base
|
394
|
+
acts_as_paranoid
|
395
|
+
has_many :paranoid_belongs_to_polymorphics, :as => :parent, :dependent => :destroy
|
396
|
+
end
|
397
|
+
|
354
398
|
class ParanoidBaseTest < ActiveSupport::TestCase
|
355
399
|
def setup
|
356
400
|
setup_db
|
@@ -421,3 +465,8 @@ class ParanoidSection < ActiveRecord::Base
|
|
421
465
|
belongs_to :paranoid_time
|
422
466
|
belongs_to :paranoid_thing, :polymorphic => true, :dependent => :destroy
|
423
467
|
end
|
468
|
+
|
469
|
+
class ParanoidBooleanNotNullable < ActiveRecord::Base
|
470
|
+
acts_as_paranoid column: 'deleted', column_type: 'boolean', allow_nulls: false
|
471
|
+
end
|
472
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PreloaderAssociationTest < ParanoidBaseTest
|
4
|
+
def test_includes_with_deleted
|
5
|
+
paranoid_time = ParanoidTime.first
|
6
|
+
paranoid_has_many_dependant = paranoid_time.paranoid_has_many_dependants.create(:name => 'dependant!')
|
7
|
+
|
8
|
+
paranoid_time.destroy
|
9
|
+
|
10
|
+
ParanoidHasManyDependant.with_deleted.includes(:paranoid_time_with_deleted).each do |hasmany|
|
11
|
+
assert_not_nil hasmany.paranoid_time_with_deleted
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_includes_with_deleted_with_polymorphic_parent
|
16
|
+
not_paranoid_parent = NotParanoidHasManyAsParent.create(name: 'not paranoid parent')
|
17
|
+
paranoid_parent = ParanoidHasManyAsParent.create(name: 'paranoid parent')
|
18
|
+
ParanoidBelongsToPolymorphic.create(:name => 'belongs_to', :parent => not_paranoid_parent)
|
19
|
+
ParanoidBelongsToPolymorphic.create(:name => 'belongs_to', :parent => paranoid_parent)
|
20
|
+
|
21
|
+
paranoid_parent.destroy
|
22
|
+
|
23
|
+
ParanoidBelongsToPolymorphic.with_deleted.includes(:parent).each do |hasmany|
|
24
|
+
assert_not_nil hasmany.parent
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_paranoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.0.
|
4
|
+
version: 0.5.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zachary Scott
|
@@ -10,36 +10,48 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2016-07-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- - "
|
19
|
+
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '4.0'
|
22
|
+
- - "<"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '5.1'
|
22
25
|
type: :runtime
|
23
26
|
prerelease: false
|
24
27
|
version_requirements: !ruby/object:Gem::Requirement
|
25
28
|
requirements:
|
26
|
-
- - "
|
29
|
+
- - ">="
|
27
30
|
- !ruby/object:Gem::Version
|
28
31
|
version: '4.0'
|
32
|
+
- - "<"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '5.1'
|
29
35
|
- !ruby/object:Gem::Dependency
|
30
36
|
name: activesupport
|
31
37
|
requirement: !ruby/object:Gem::Requirement
|
32
38
|
requirements:
|
33
|
-
- - "
|
39
|
+
- - ">="
|
34
40
|
- !ruby/object:Gem::Version
|
35
41
|
version: '4.0'
|
42
|
+
- - "<"
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '5.1'
|
36
45
|
type: :runtime
|
37
46
|
prerelease: false
|
38
47
|
version_requirements: !ruby/object:Gem::Requirement
|
39
48
|
requirements:
|
40
|
-
- - "
|
49
|
+
- - ">="
|
41
50
|
- !ruby/object:Gem::Version
|
42
51
|
version: '4.0'
|
52
|
+
- - "<"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.1'
|
43
55
|
- !ruby/object:Gem::Dependency
|
44
56
|
name: bundler
|
45
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +126,7 @@ files:
|
|
114
126
|
- lib/acts_as_paranoid.rb
|
115
127
|
- lib/acts_as_paranoid/associations.rb
|
116
128
|
- lib/acts_as_paranoid/core.rb
|
129
|
+
- lib/acts_as_paranoid/preloader_association.rb
|
117
130
|
- lib/acts_as_paranoid/relation.rb
|
118
131
|
- lib/acts_as_paranoid/validations.rb
|
119
132
|
- lib/acts_as_paranoid/version.rb
|
@@ -122,6 +135,7 @@ files:
|
|
122
135
|
- test/test_default_scopes.rb
|
123
136
|
- test/test_helper.rb
|
124
137
|
- test/test_inheritance.rb
|
138
|
+
- test/test_preloader_association.rb
|
125
139
|
- test/test_relations.rb
|
126
140
|
- test/test_validations.rb
|
127
141
|
homepage: https://github.com/ActsAsParanoid/acts_as_paranoid
|
@@ -144,16 +158,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
158
|
version: 1.3.6
|
145
159
|
requirements: []
|
146
160
|
rubyforge_project:
|
147
|
-
rubygems_version: 2.
|
161
|
+
rubygems_version: 2.5.1
|
148
162
|
signing_key:
|
149
163
|
specification_version: 4
|
150
164
|
summary: Active Record plugin which allows you to hide and restore records without
|
151
165
|
actually deleting them.
|
152
166
|
test_files:
|
153
|
-
- test/test_associations.rb
|
154
|
-
- test/test_core.rb
|
155
|
-
- test/test_default_scopes.rb
|
156
|
-
- test/test_helper.rb
|
157
167
|
- test/test_inheritance.rb
|
168
|
+
- test/test_preloader_association.rb
|
158
169
|
- test/test_relations.rb
|
170
|
+
- test/test_core.rb
|
159
171
|
- test/test_validations.rb
|
172
|
+
- test/test_associations.rb
|
173
|
+
- test/test_helper.rb
|
174
|
+
- test/test_default_scopes.rb
|
175
|
+
has_rdoc:
|