acts_as_paranoid 0.5.0.beta2 → 0.5.0.rc1
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/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:
|