acts_as_paranoid 0.4.1 → 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +1 -1
- data/{README.markdown → README.md} +26 -17
- data/lib/acts_as_paranoid/core.rb +16 -8
- data/lib/acts_as_paranoid/relation.rb +2 -2
- data/lib/acts_as_paranoid/version.rb +3 -0
- data/lib/acts_as_paranoid.rb +10 -14
- data/test/test_associations.rb +222 -0
- data/test/test_core.rb +387 -0
- data/test/test_default_scopes.rb +52 -0
- data/test/test_helper.rb +442 -0
- data/test/test_inheritance.rb +14 -0
- data/test/test_observers.rb +16 -0
- data/test/test_relations.rb +117 -0
- data/test/test_validations.rb +42 -0
- metadata +102 -28
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 57c69c6d7676bda21b0f8da016bd556f77003894
|
4
|
+
data.tar.gz: 5293e8a3b417fecdfe117aefddcd8e2a0d2f4b09
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8ae49e59c2f487c80243bb42c4d6e33c4f1676ecd0d039ba420c1e1e49e02b83a4c6635515d1ef53dd4ba0c68ebce427b386ce684992d4139ef2e4c638f61dd5
|
7
|
+
data.tar.gz: f449a10feae541515688ed6c55446aa815025982f293a2375c44ec74b68a8cfe7928abc1dffee3758a868bca4d6d92eb13632642bb0dc40279d47e5973a7bfb0
|
data/LICENSE
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
# ActsAsParanoid
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/ActsAsParanoid/acts_as_paranoid.png?branch=0-4-stable)](https://travis-ci.org/ActsAsParanoid/acts_as_paranoid)
|
4
|
+
|
3
5
|
A simple plugin which hides records instead of deleting them, being able to recover them.
|
4
6
|
|
5
7
|
**This branch targets Rails 3.2.** If you're working with another version, switch to the corresponding branch.
|
6
8
|
|
7
|
-
## Credits
|
8
|
-
|
9
|
-
This plugin was inspired by [acts_as_paranoid](http://github.com/technoweenie/acts_as_paranoid) and [acts_as_active](http://github.com/fernandoluizao/acts_as_active).
|
10
|
-
|
11
|
-
While porting it to Rails 3, I decided to apply the ideas behind those plugins to an unified solution while removing a **lot** of the complexity found in them. I eventually ended up writing a new plugin from scratch.
|
12
|
-
|
13
9
|
## Usage
|
14
10
|
|
15
11
|
You can enable ActsAsParanoid like this:
|
@@ -186,29 +182,34 @@ Paranoiac.pretty.only_deleted.count #=> 1
|
|
186
182
|
Associations are also supported. 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`
|
187
183
|
|
188
184
|
```ruby
|
189
|
-
class
|
190
|
-
|
185
|
+
class Parent < ActiveRecord::Base
|
186
|
+
has_many :children, :class_name => "ParanoiacChild"
|
191
187
|
end
|
192
188
|
|
193
189
|
class ParanoiacChild < ActiveRecord::Base
|
194
|
-
|
195
|
-
|
190
|
+
acts_as_paranoid
|
191
|
+
belongs_to :parent
|
192
|
+
|
193
|
+
# You may need to provide a foreign_key like this
|
194
|
+
belongs_to :parent_including_deleted, :class_name => "Parent", foreign_key => 'parent_id', :with_deleted => true
|
196
195
|
end
|
197
196
|
|
198
|
-
parent =
|
197
|
+
parent = Parent.first
|
199
198
|
child = parent.children.create
|
200
199
|
parent.destroy
|
201
200
|
|
202
201
|
child.parent #=> nil
|
203
|
-
child.
|
202
|
+
child.parent_including_deleted #=> Parent (it works!)
|
204
203
|
```
|
205
204
|
|
206
205
|
## Caveats
|
207
206
|
|
208
207
|
Watch out for these caveats:
|
209
208
|
|
209
|
+
|
210
210
|
- You cannot use scopes named `with_deleted` and `only_deleted`
|
211
211
|
- You cannot use scopes named `deleted_inside_time_window`, `deleted_before_time`, `deleted_after_time` **if** your paranoid column's type is `time`
|
212
|
+
- You cannot name association `*_with_deleted`
|
212
213
|
- `unscoped` will return all records, deleted or not
|
213
214
|
|
214
215
|
# Support
|
@@ -219,20 +220,21 @@ This gem supports the most recent versions of Rails and Ruby.
|
|
219
220
|
|
220
221
|
For Rails 3.2 check the README at the [rails3.2](https://github.com/goncalossilva/rails3_acts_as_paranoid/tree/rails3.2) branch and add this to your Gemfile:
|
221
222
|
|
222
|
-
|
223
|
+
gem "acts_as_paranoid", "~> 0.4.0"
|
223
224
|
|
224
225
|
For Rails 3.1 check the README at the [rails3.1](https://github.com/goncalossilva/rails3_acts_as_paranoid/tree/rails3.1) branch and add this to your Gemfile:
|
225
226
|
|
226
|
-
|
227
|
+
gem "rails3_acts_as_paranoid", "~>0.1.4"
|
227
228
|
|
228
229
|
For Rails 3.0 check the README at the [rails3.0](https://github.com/goncalossilva/rails3_acts_as_paranoid/tree/rails3.0) branch and add this to your Gemfile:
|
229
230
|
|
230
|
-
|
231
|
+
gem "rails3_acts_as_paranoid", "~>0.0.9"
|
231
232
|
|
232
233
|
|
233
234
|
## Ruby
|
234
235
|
|
235
|
-
This gem is tested on Ruby 1.9, JRuby and Rubinius (both in 1.9 mode).
|
236
|
+
This gem is tested on Ruby 1.9, JRuby and Rubinius (both in 1.9 mode).
|
237
|
+
|
236
238
|
|
237
239
|
# Acknowledgements
|
238
240
|
|
@@ -244,4 +246,11 @@ This gem is tested on Ruby 1.9, JRuby and Rubinius (both in 1.9 mode). It *might
|
|
244
246
|
* To [Craig Walker](https://github.com/softcraft-development) for Rails 3.1 support and fixing various pending issues
|
245
247
|
* To [Charles G.](https://github.com/chuckg) for Rails 3.2 support and for making a desperately needed global code refactoring
|
246
248
|
|
247
|
-
|
249
|
+
## Credits
|
250
|
+
|
251
|
+
This plugin was inspired by [acts_as_paranoid](http://github.com/technoweenie/acts_as_paranoid) and [acts_as_active](http://github.com/fernandoluizao/acts_as_active).
|
252
|
+
|
253
|
+
While porting it to Rails 3, I decided to apply the ideas behind those plugins to an unified solution while removing a **lot** of the complexity found in them. I eventually ended up writing a new plugin from scratch.
|
254
|
+
|
255
|
+
|
256
|
+
Copyright © 2014 Zachary Scott, Gonçalo Silva, Rick Olson, released under the MIT license
|
@@ -94,7 +94,7 @@ module ActsAsParanoid
|
|
94
94
|
run_callbacks :destroy do
|
95
95
|
destroy_dependent_associations!
|
96
96
|
# Handle composite keys, otherwise we would just use `self.class.primary_key.to_sym => self.id`.
|
97
|
-
self.class.delete_all!(Hash[[Array(self.class.primary_key), Array(self.id)].transpose])
|
97
|
+
self.class.delete_all!(Hash[[Array(self.class.primary_key), Array(self.id)].transpose]) if persisted?
|
98
98
|
self.paranoid_value = self.class.delete_now_value
|
99
99
|
freeze
|
100
100
|
end
|
@@ -106,7 +106,7 @@ module ActsAsParanoid
|
|
106
106
|
with_transaction_returning_status do
|
107
107
|
run_callbacks :destroy do
|
108
108
|
# Handle composite keys, otherwise we would just use `self.class.primary_key.to_sym => self.id`.
|
109
|
-
self.class.delete_all(Hash[[Array(self.class.primary_key), Array(self.id)].transpose])
|
109
|
+
self.class.delete_all(Hash[[Array(self.class.primary_key), Array(self.id)].transpose]) if persisted?
|
110
110
|
self.paranoid_value = self.class.delete_now_value
|
111
111
|
self
|
112
112
|
end
|
@@ -134,17 +134,17 @@ module ActsAsParanoid
|
|
134
134
|
|
135
135
|
def recover_dependent_associations(window, options)
|
136
136
|
self.class.dependent_associations.each do |reflection|
|
137
|
-
next unless reflection.
|
137
|
+
next unless (klass = get_reflection_class(reflection)).paranoid?
|
138
138
|
|
139
|
-
scope =
|
139
|
+
scope = klass.only_deleted
|
140
140
|
|
141
141
|
# Merge in the association's scope
|
142
142
|
scope = scope.merge(association(reflection.name).association_scope)
|
143
143
|
|
144
144
|
# We can only recover by window if both parent and dependant have a
|
145
145
|
# paranoid column type of :time.
|
146
|
-
if self.class.paranoid_column_type == :time &&
|
147
|
-
scope = scope.merge(
|
146
|
+
if self.class.paranoid_column_type == :time && klass.paranoid_column_type == :time
|
147
|
+
scope = scope.merge(klass.deleted_inside_time_window(paranoid_value, window))
|
148
148
|
end
|
149
149
|
|
150
150
|
scope.each do |object|
|
@@ -155,9 +155,9 @@ module ActsAsParanoid
|
|
155
155
|
|
156
156
|
def destroy_dependent_associations!
|
157
157
|
self.class.dependent_associations.each do |reflection|
|
158
|
-
next unless reflection.
|
158
|
+
next unless (klass = get_reflection_class(reflection)).paranoid?
|
159
159
|
|
160
|
-
scope =
|
160
|
+
scope = klass.only_deleted
|
161
161
|
|
162
162
|
# Merge in the association's scope
|
163
163
|
scope = scope.merge(association(reflection.name).association_scope)
|
@@ -177,6 +177,14 @@ module ActsAsParanoid
|
|
177
177
|
|
178
178
|
private
|
179
179
|
|
180
|
+
def get_reflection_class(reflection)
|
181
|
+
if reflection.macro == :belongs_to && reflection.options.include?(:polymorphic)
|
182
|
+
self.send(reflection.foreign_type).constantize
|
183
|
+
else
|
184
|
+
reflection.klass
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
180
188
|
def paranoid_value=(value)
|
181
189
|
self.send("#{self.class.paranoid_column}=", value)
|
182
190
|
end
|
@@ -5,7 +5,7 @@ module ActsAsParanoid
|
|
5
5
|
def paranoid?
|
6
6
|
klass.try(:paranoid?) ? true : false
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
def paranoid_deletion_attributes
|
10
10
|
{ klass.paranoid_column => klass.delete_now_value }
|
11
11
|
end
|
@@ -18,7 +18,7 @@ module ActsAsParanoid
|
|
18
18
|
orig_delete_all
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def delete_all(conditions = nil)
|
23
23
|
if paranoid?
|
24
24
|
update_all(paranoid_deletion_attributes, conditions)
|
data/lib/acts_as_paranoid.rb
CHANGED
@@ -1,27 +1,23 @@
|
|
1
|
-
require 'active_record/base'
|
2
|
-
require 'active_record/relation'
|
3
|
-
require 'active_record/callbacks'
|
4
1
|
require 'acts_as_paranoid/core'
|
5
2
|
require 'acts_as_paranoid/associations'
|
6
3
|
require 'acts_as_paranoid/validations'
|
7
4
|
require 'acts_as_paranoid/relation'
|
8
5
|
|
9
|
-
|
10
6
|
module ActsAsParanoid
|
11
|
-
|
7
|
+
|
12
8
|
def paranoid?
|
13
9
|
self.included_modules.include?(ActsAsParanoid::Core)
|
14
10
|
end
|
15
|
-
|
11
|
+
|
16
12
|
def validates_as_paranoid
|
17
13
|
include ActsAsParanoid::Validations
|
18
14
|
end
|
19
|
-
|
15
|
+
|
20
16
|
def acts_as_paranoid(options = {})
|
21
17
|
raise ArgumentError, "Hash expected, got #{options.class.name}" if not options.is_a?(Hash) and not options.empty?
|
22
|
-
|
18
|
+
|
23
19
|
class_attribute :paranoid_configuration, :paranoid_column_reference
|
24
|
-
|
20
|
+
|
25
21
|
self.paranoid_configuration = { :column => "deleted_at", :column_type => "time", :recover_dependent_associations => true, :dependent_recovery_window => 2.minutes }
|
26
22
|
self.paranoid_configuration.merge!({ :deleted_value => "deleted" }) if options[:column_type] == "string"
|
27
23
|
self.paranoid_configuration.merge!(options) # user options
|
@@ -29,11 +25,11 @@ module ActsAsParanoid
|
|
29
25
|
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]
|
30
26
|
|
31
27
|
self.paranoid_column_reference = "#{self.table_name}.#{paranoid_configuration[:column]}"
|
32
|
-
|
28
|
+
|
33
29
|
return if paranoid?
|
34
|
-
|
30
|
+
|
35
31
|
include ActsAsParanoid::Core
|
36
|
-
|
32
|
+
|
37
33
|
# Magic!
|
38
34
|
default_scope { where(paranoid_default_scope_sql) }
|
39
35
|
|
@@ -42,8 +38,8 @@ module ActsAsParanoid
|
|
42
38
|
deleted_after_time((time - window)).deleted_before_time((time + window))
|
43
39
|
}
|
44
40
|
|
45
|
-
scope :deleted_after_time, lambda { |time| where("#{paranoid_column} > ?", time) }
|
46
|
-
scope :deleted_before_time, lambda { |time| where("#{paranoid_column} < ?", time) }
|
41
|
+
scope :deleted_after_time, lambda { |time| where("#{self.table_name}.#{paranoid_column} > ?", time) }
|
42
|
+
scope :deleted_before_time, lambda { |time| where("#{self.table_name}.#{paranoid_column} < ?", time) }
|
47
43
|
end
|
48
44
|
end
|
49
45
|
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AssociationsTest < ParanoidBaseTest
|
4
|
+
def test_removal_with_associations
|
5
|
+
# This test shows that the current implementation doesn't handle
|
6
|
+
# assciation deletion correctly (when hard deleting via parent-object)
|
7
|
+
paranoid_company_1 = ParanoidDestroyCompany.create! :name => "ParanoidDestroyCompany #1"
|
8
|
+
paranoid_company_2 = ParanoidDeleteCompany.create! :name => "ParanoidDestroyCompany #1"
|
9
|
+
paranoid_company_1.paranoid_products.create! :name => "ParanoidProduct #1"
|
10
|
+
paranoid_company_2.paranoid_products.create! :name => "ParanoidProduct #2"
|
11
|
+
|
12
|
+
assert_equal 1, ParanoidDestroyCompany.count
|
13
|
+
assert_equal 1, ParanoidDeleteCompany.count
|
14
|
+
assert_equal 2, ParanoidProduct.count
|
15
|
+
|
16
|
+
ParanoidDestroyCompany.first.destroy
|
17
|
+
assert_equal 0, ParanoidDestroyCompany.count
|
18
|
+
assert_equal 1, ParanoidProduct.count
|
19
|
+
assert_equal 1, ParanoidDestroyCompany.with_deleted.count
|
20
|
+
assert_equal 2, ParanoidProduct.with_deleted.count
|
21
|
+
|
22
|
+
ParanoidDestroyCompany.with_deleted.first.destroy!
|
23
|
+
assert_equal 0, ParanoidDestroyCompany.count
|
24
|
+
assert_equal 1, ParanoidProduct.count
|
25
|
+
assert_equal 0, ParanoidDestroyCompany.with_deleted.count
|
26
|
+
assert_equal 1, ParanoidProduct.with_deleted.count
|
27
|
+
|
28
|
+
ParanoidDeleteCompany.with_deleted.first.destroy!
|
29
|
+
assert_equal 0, ParanoidDeleteCompany.count
|
30
|
+
assert_equal 0, ParanoidProduct.count
|
31
|
+
assert_equal 0, ParanoidDeleteCompany.with_deleted.count
|
32
|
+
assert_equal 0, ParanoidProduct.with_deleted.count
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_belongs_to_with_deleted
|
36
|
+
paranoid_time = ParanoidTime.first
|
37
|
+
paranoid_has_many_dependant = paranoid_time.paranoid_has_many_dependants.create(:name => 'dependant!')
|
38
|
+
|
39
|
+
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time
|
40
|
+
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted
|
41
|
+
|
42
|
+
paranoid_time.destroy
|
43
|
+
|
44
|
+
assert_nil paranoid_has_many_dependant.paranoid_time(true)
|
45
|
+
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted(true)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_belongs_to_polymorphic_with_deleted
|
49
|
+
paranoid_time = ParanoidTime.first
|
50
|
+
paranoid_has_many_dependant = ParanoidHasManyDependant.create!(:name => 'dependant!', :paranoid_time_polymorphic_with_deleted => paranoid_time)
|
51
|
+
|
52
|
+
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time
|
53
|
+
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted
|
54
|
+
|
55
|
+
paranoid_time.destroy
|
56
|
+
|
57
|
+
assert_nil paranoid_has_many_dependant.paranoid_time(true)
|
58
|
+
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted(true)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_belongs_to_nil_polymorphic_with_deleted
|
62
|
+
paranoid_time = ParanoidTime.first
|
63
|
+
paranoid_has_many_dependant = ParanoidHasManyDependant.create!(:name => 'dependant!', :paranoid_time_polymorphic_with_deleted => nil)
|
64
|
+
|
65
|
+
assert_nil paranoid_has_many_dependant.paranoid_time
|
66
|
+
assert_nil paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted
|
67
|
+
|
68
|
+
paranoid_time.destroy
|
69
|
+
|
70
|
+
assert_nil paranoid_has_many_dependant.paranoid_time(true)
|
71
|
+
assert_nil paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted(true)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_belongs_to_options
|
75
|
+
paranoid_time = ParanoidHasManyDependant.reflections[:paranoid_time]
|
76
|
+
assert_equal :belongs_to, paranoid_time.macro
|
77
|
+
assert_nil paranoid_time.options[:with_deleted]
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_belongs_to_with_deleted_options
|
81
|
+
paranoid_time_with_deleted = ParanoidHasManyDependant.reflections[:paranoid_time_with_deleted]
|
82
|
+
assert_equal :belongs_to, paranoid_time_with_deleted.macro
|
83
|
+
assert paranoid_time_with_deleted.options[:with_deleted]
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_belongs_to_polymorphic_with_deleted_options
|
87
|
+
paranoid_time_polymorphic_with_deleted = ParanoidHasManyDependant.reflections[:paranoid_time_polymorphic_with_deleted]
|
88
|
+
assert_equal :belongs_to, paranoid_time_polymorphic_with_deleted.macro
|
89
|
+
assert paranoid_time_polymorphic_with_deleted.options[:with_deleted]
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_only_find_associated_records_when_finding_with_paranoid_deleted
|
93
|
+
parent = ParanoidBelongsDependant.create
|
94
|
+
child = ParanoidHasManyDependant.create
|
95
|
+
parent.paranoid_has_many_dependants << child
|
96
|
+
|
97
|
+
unrelated_parent = ParanoidBelongsDependant.create
|
98
|
+
unrelated_child = ParanoidHasManyDependant.create
|
99
|
+
unrelated_parent.paranoid_has_many_dependants << unrelated_child
|
100
|
+
|
101
|
+
child.destroy
|
102
|
+
assert_paranoid_deletion(child)
|
103
|
+
|
104
|
+
assert_equal [child], parent.paranoid_has_many_dependants.with_deleted.to_a
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_cannot_find_a_paranoid_deleted_many_many_association
|
108
|
+
left = ParanoidManyManyParentLeft.create
|
109
|
+
right = ParanoidManyManyParentRight.create
|
110
|
+
left.paranoid_many_many_parent_rights << right
|
111
|
+
|
112
|
+
left.paranoid_many_many_parent_rights.delete(right)
|
113
|
+
|
114
|
+
left.reload
|
115
|
+
|
116
|
+
assert_equal [], left.paranoid_many_many_children, "Linking objects not deleted"
|
117
|
+
assert_equal [], left.paranoid_many_many_parent_rights, "Associated objects not unlinked"
|
118
|
+
assert_equal right, ParanoidManyManyParentRight.find(right.id), "Associated object deleted"
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_cannot_find_a_paranoid_destroyed_many_many_association
|
122
|
+
left = ParanoidManyManyParentLeft.create
|
123
|
+
right = ParanoidManyManyParentRight.create
|
124
|
+
left.paranoid_many_many_parent_rights << right
|
125
|
+
|
126
|
+
left.paranoid_many_many_parent_rights.destroy(right)
|
127
|
+
|
128
|
+
left.reload
|
129
|
+
|
130
|
+
assert_equal [], left.paranoid_many_many_children, "Linking objects not deleted"
|
131
|
+
assert_equal [], left.paranoid_many_many_parent_rights, "Associated objects not unlinked"
|
132
|
+
assert_equal right, ParanoidManyManyParentRight.find(right.id), "Associated object deleted"
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_cannot_find_a_has_many_through_object_when_its_linking_object_is_paranoid_destroyed
|
136
|
+
left = ParanoidManyManyParentLeft.create
|
137
|
+
right = ParanoidManyManyParentRight.create
|
138
|
+
left.paranoid_many_many_parent_rights << right
|
139
|
+
|
140
|
+
child = left.paranoid_many_many_children.first
|
141
|
+
|
142
|
+
child.destroy
|
143
|
+
|
144
|
+
left.reload
|
145
|
+
|
146
|
+
assert_equal [], left.paranoid_many_many_parent_rights, "Associated objects not deleted"
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_cannot_find_a_paranoid_deleted_model
|
150
|
+
model = ParanoidBelongsDependant.create
|
151
|
+
model.destroy
|
152
|
+
|
153
|
+
assert_raises ActiveRecord::RecordNotFound do
|
154
|
+
ParanoidBelongsDependant.find(model.id)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_bidirectional_has_many_through_association_clear_is_paranoid
|
159
|
+
left = ParanoidManyManyParentLeft.create
|
160
|
+
right = ParanoidManyManyParentRight.create
|
161
|
+
left.paranoid_many_many_parent_rights << right
|
162
|
+
|
163
|
+
child = left.paranoid_many_many_children.first
|
164
|
+
assert_equal left, child.paranoid_many_many_parent_left, "Child's left parent is incorrect"
|
165
|
+
assert_equal right, child.paranoid_many_many_parent_right, "Child's right parent is incorrect"
|
166
|
+
|
167
|
+
left.paranoid_many_many_parent_rights.clear
|
168
|
+
|
169
|
+
assert_paranoid_deletion(child)
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_bidirectional_has_many_through_association_destroy_is_paranoid
|
173
|
+
left = ParanoidManyManyParentLeft.create
|
174
|
+
right = ParanoidManyManyParentRight.create
|
175
|
+
left.paranoid_many_many_parent_rights << right
|
176
|
+
|
177
|
+
child = left.paranoid_many_many_children.first
|
178
|
+
assert_equal left, child.paranoid_many_many_parent_left, "Child's left parent is incorrect"
|
179
|
+
assert_equal right, child.paranoid_many_many_parent_right, "Child's right parent is incorrect"
|
180
|
+
|
181
|
+
left.paranoid_many_many_parent_rights.destroy(right)
|
182
|
+
|
183
|
+
assert_paranoid_deletion(child)
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_bidirectional_has_many_through_association_delete_is_paranoid
|
187
|
+
left = ParanoidManyManyParentLeft.create
|
188
|
+
right = ParanoidManyManyParentRight.create
|
189
|
+
left.paranoid_many_many_parent_rights << right
|
190
|
+
|
191
|
+
child = left.paranoid_many_many_children.first
|
192
|
+
assert_equal left, child.paranoid_many_many_parent_left, "Child's left parent is incorrect"
|
193
|
+
assert_equal right, child.paranoid_many_many_parent_right, "Child's right parent is incorrect"
|
194
|
+
|
195
|
+
left.paranoid_many_many_parent_rights.delete(right)
|
196
|
+
|
197
|
+
assert_paranoid_deletion(child)
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_belongs_to_on_normal_model_is_paranoid
|
201
|
+
not_paranoid = HasOneNotParanoid.create
|
202
|
+
not_paranoid.paranoid_time = ParanoidTime.create
|
203
|
+
|
204
|
+
assert not_paranoid.save
|
205
|
+
assert_not_nil not_paranoid.paranoid_time
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_double_belongs_to_with_deleted
|
209
|
+
not_paranoid = DoubleHasOneNotParanoid.create
|
210
|
+
not_paranoid.paranoid_time = ParanoidTime.create
|
211
|
+
|
212
|
+
assert not_paranoid.save
|
213
|
+
assert_not_nil not_paranoid.paranoid_time
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_mass_assignment_of_paranoid_column_enabled
|
217
|
+
now = Time.now
|
218
|
+
record = ParanoidTime.create! :name => 'Foo', :deleted_at => now
|
219
|
+
assert_equal 'Foo', record.name
|
220
|
+
assert_equal now, record.deleted_at
|
221
|
+
end
|
222
|
+
end
|