acts_as_paranoid 0.5.0 → 0.7.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 +5 -5
- data/CHANGELOG.md +117 -0
- data/LICENSE +1 -1
- data/README.md +175 -50
- data/lib/acts_as_paranoid.rb +34 -31
- data/lib/acts_as_paranoid/associations.rb +28 -17
- data/lib/acts_as_paranoid/core.rb +144 -53
- data/lib/acts_as_paranoid/relation.rb +2 -0
- data/lib/acts_as_paranoid/validations.rb +8 -65
- data/lib/acts_as_paranoid/version.rb +3 -1
- data/test/test_associations.rb +161 -39
- data/test/test_core.rb +252 -55
- data/test/test_default_scopes.rb +38 -37
- data/test/test_helper.rb +136 -67
- data/test/test_inheritance.rb +5 -3
- data/test/test_relations.rb +29 -21
- data/test/test_validations.rb +10 -7
- metadata +80 -30
- data/lib/acts_as_paranoid/preloader_association.rb +0 -15
- data/test/test_preloader_association.rb +0 -27
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/array/wrap"
|
2
4
|
|
3
5
|
module ActsAsParanoid
|
4
6
|
module Validations
|
@@ -6,76 +8,17 @@ module ActsAsParanoid
|
|
6
8
|
base.extend ClassMethods
|
7
9
|
end
|
8
10
|
|
9
|
-
class UniquenessWithoutDeletedValidator
|
10
|
-
|
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(', ')}"
|
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
|
26
|
-
|
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?
|
31
|
-
|
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
|
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
|
11
|
+
class UniquenessWithoutDeletedValidator < ActiveRecord::Validations::UniquenessValidator
|
12
|
+
private
|
67
13
|
|
68
|
-
|
69
|
-
|
70
|
-
record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
|
71
|
-
end
|
72
|
-
end
|
14
|
+
def build_relation(klass, attribute, value)
|
15
|
+
super.where(klass.paranoid_default_scope)
|
73
16
|
end
|
74
17
|
end
|
75
18
|
|
76
19
|
module ClassMethods
|
77
20
|
def validates_uniqueness_of_without_deleted(*attr_names)
|
78
|
-
validates_with UniquenessWithoutDeletedValidator
|
21
|
+
validates_with UniquenessWithoutDeletedValidator, _merge_attributes(attr_names)
|
79
22
|
end
|
80
23
|
end
|
81
24
|
end
|
data/test/test_associations.rb
CHANGED
@@ -1,27 +1,34 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
2
4
|
|
3
5
|
class AssociationsTest < ParanoidBaseTest
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
paranoid_company_1.paranoid_products.create! :name => "ParanoidProduct #1"
|
8
|
-
paranoid_company_2.paranoid_products.create! :name => "ParanoidProduct #2"
|
6
|
+
def test_removal_with_destroy_associations
|
7
|
+
paranoid_company = ParanoidDestroyCompany.create! name: "ParanoidDestroyCompany #1"
|
8
|
+
paranoid_company.paranoid_products.create! name: "ParanoidProduct #1"
|
9
9
|
|
10
10
|
assert_equal 1, ParanoidDestroyCompany.count
|
11
|
-
assert_equal 1,
|
12
|
-
assert_equal 2, ParanoidProduct.count
|
11
|
+
assert_equal 1, ParanoidProduct.count
|
13
12
|
|
14
13
|
ParanoidDestroyCompany.first.destroy
|
15
14
|
assert_equal 0, ParanoidDestroyCompany.count
|
16
|
-
assert_equal
|
15
|
+
assert_equal 0, ParanoidProduct.count
|
17
16
|
assert_equal 1, ParanoidDestroyCompany.with_deleted.count
|
18
|
-
assert_equal
|
17
|
+
assert_equal 1, ParanoidProduct.with_deleted.count
|
19
18
|
|
20
19
|
ParanoidDestroyCompany.with_deleted.first.destroy
|
21
20
|
assert_equal 0, ParanoidDestroyCompany.count
|
22
|
-
assert_equal
|
21
|
+
assert_equal 0, ParanoidProduct.count
|
23
22
|
assert_equal 0, ParanoidDestroyCompany.with_deleted.count
|
24
|
-
assert_equal
|
23
|
+
assert_equal 0, ParanoidProduct.with_deleted.count
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_removal_with_delete_all_associations
|
27
|
+
paranoid_company = ParanoidDeleteCompany.create! name: "ParanoidDestroyCompany #1"
|
28
|
+
paranoid_company.paranoid_products.create! name: "ParanoidProduct #2"
|
29
|
+
|
30
|
+
assert_equal 1, ParanoidDeleteCompany.count
|
31
|
+
assert_equal 1, ParanoidProduct.count
|
25
32
|
|
26
33
|
ParanoidDeleteCompany.first.destroy
|
27
34
|
assert_equal 0, ParanoidDeleteCompany.count
|
@@ -38,64 +45,122 @@ class AssociationsTest < ParanoidBaseTest
|
|
38
45
|
|
39
46
|
def test_belongs_to_with_scope_option
|
40
47
|
paranoid_has_many_dependant = ParanoidHasManyDependant.new
|
48
|
+
|
49
|
+
expected_includes_values = ParanoidTime.includes(:not_paranoid).includes_values
|
50
|
+
includes_values = paranoid_has_many_dependant
|
51
|
+
.association(:paranoid_time_with_scope).scope.includes_values
|
52
|
+
|
53
|
+
assert_equal expected_includes_values, includes_values
|
54
|
+
|
55
|
+
paranoid_time = ParanoidTime.create(name: "not-hello")
|
56
|
+
paranoid_has_many_dependant.paranoid_time = paranoid_time
|
57
|
+
paranoid_has_many_dependant.save!
|
58
|
+
|
59
|
+
assert_nil paranoid_has_many_dependant.paranoid_time_with_scope
|
60
|
+
|
61
|
+
paranoid_time.update(name: "hello")
|
62
|
+
|
63
|
+
paranoid_has_many_dependant.reload
|
64
|
+
|
65
|
+
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_scope
|
66
|
+
|
67
|
+
paranoid_time.destroy
|
68
|
+
|
69
|
+
paranoid_has_many_dependant.reload
|
70
|
+
|
71
|
+
assert_nil paranoid_has_many_dependant.paranoid_time_with_scope
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_belongs_to_with_scope_and_deleted_option
|
75
|
+
paranoid_has_many_dependant = ParanoidHasManyDependant.new
|
41
76
|
includes_values = ParanoidTime.includes(:not_paranoid).includes_values
|
42
77
|
|
43
|
-
assert_equal includes_values, paranoid_has_many_dependant
|
78
|
+
assert_equal includes_values, paranoid_has_many_dependant
|
79
|
+
.association(:paranoid_time_with_scope_with_deleted).scope.includes_values
|
80
|
+
|
81
|
+
paranoid_time = ParanoidTime.create(name: "not-hello")
|
82
|
+
paranoid_has_many_dependant.paranoid_time = paranoid_time
|
83
|
+
paranoid_has_many_dependant.save!
|
84
|
+
|
85
|
+
assert_nil paranoid_has_many_dependant.paranoid_time_with_scope_with_deleted
|
86
|
+
|
87
|
+
paranoid_time.update(name: "hello")
|
88
|
+
paranoid_has_many_dependant.reload
|
89
|
+
|
90
|
+
assert_equal paranoid_time, paranoid_has_many_dependant
|
91
|
+
.paranoid_time_with_scope_with_deleted
|
92
|
+
|
93
|
+
paranoid_time.destroy
|
94
|
+
paranoid_has_many_dependant.reload
|
95
|
+
|
96
|
+
assert_equal paranoid_time, paranoid_has_many_dependant
|
97
|
+
.paranoid_time_with_scope_with_deleted
|
44
98
|
end
|
45
99
|
|
46
100
|
def test_belongs_to_with_deleted
|
47
101
|
paranoid_time = ParanoidTime.first
|
48
|
-
paranoid_has_many_dependant = paranoid_time.paranoid_has_many_dependants
|
102
|
+
paranoid_has_many_dependant = paranoid_time.paranoid_has_many_dependants
|
103
|
+
.create(name: "dependant!")
|
49
104
|
|
50
105
|
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time
|
51
106
|
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted
|
52
107
|
|
53
108
|
paranoid_time.destroy
|
109
|
+
paranoid_has_many_dependant.reload
|
54
110
|
|
55
|
-
assert_nil paranoid_has_many_dependant.paranoid_time
|
56
|
-
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted
|
111
|
+
assert_nil paranoid_has_many_dependant.paranoid_time
|
112
|
+
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted
|
57
113
|
end
|
58
114
|
|
59
115
|
def test_belongs_to_polymorphic_with_deleted
|
60
116
|
paranoid_time = ParanoidTime.first
|
61
|
-
paranoid_has_many_dependant = ParanoidHasManyDependant
|
117
|
+
paranoid_has_many_dependant = ParanoidHasManyDependant
|
118
|
+
.create!(name: "dependant!", paranoid_time_polymorphic_with_deleted: paranoid_time)
|
62
119
|
|
63
120
|
assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time
|
64
|
-
assert_equal paranoid_time, paranoid_has_many_dependant
|
121
|
+
assert_equal paranoid_time, paranoid_has_many_dependant
|
122
|
+
.paranoid_time_polymorphic_with_deleted
|
65
123
|
|
66
124
|
paranoid_time.destroy
|
67
125
|
|
68
|
-
assert_nil paranoid_has_many_dependant.paranoid_time
|
69
|
-
assert_equal paranoid_time, paranoid_has_many_dependant
|
126
|
+
assert_nil paranoid_has_many_dependant.reload.paranoid_time
|
127
|
+
assert_equal paranoid_time, paranoid_has_many_dependant
|
128
|
+
.reload.paranoid_time_polymorphic_with_deleted
|
70
129
|
end
|
71
130
|
|
72
131
|
def test_belongs_to_nil_polymorphic_with_deleted
|
73
132
|
paranoid_time = ParanoidTime.first
|
74
|
-
paranoid_has_many_dependant =
|
133
|
+
paranoid_has_many_dependant =
|
134
|
+
ParanoidHasManyDependant.create!(name: "dependant!",
|
135
|
+
paranoid_time_polymorphic_with_deleted: nil)
|
75
136
|
|
76
137
|
assert_nil paranoid_has_many_dependant.paranoid_time
|
77
138
|
assert_nil paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted
|
78
139
|
|
79
140
|
paranoid_time.destroy
|
80
141
|
|
81
|
-
assert_nil paranoid_has_many_dependant.paranoid_time
|
82
|
-
assert_nil paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted
|
142
|
+
assert_nil paranoid_has_many_dependant.reload.paranoid_time
|
143
|
+
assert_nil paranoid_has_many_dependant.reload.paranoid_time_polymorphic_with_deleted
|
83
144
|
end
|
84
145
|
|
85
146
|
def test_belongs_to_options
|
86
|
-
paranoid_time = ParanoidHasManyDependant.reflections
|
147
|
+
paranoid_time = ParanoidHasManyDependant.reflections
|
148
|
+
.with_indifferent_access[:paranoid_time]
|
87
149
|
assert_equal :belongs_to, paranoid_time.macro
|
88
150
|
assert_nil paranoid_time.options[:with_deleted]
|
89
151
|
end
|
90
152
|
|
91
153
|
def test_belongs_to_with_deleted_options
|
92
|
-
paranoid_time_with_deleted =
|
154
|
+
paranoid_time_with_deleted =
|
155
|
+
ParanoidHasManyDependant.reflections
|
156
|
+
.with_indifferent_access[:paranoid_time_with_deleted]
|
93
157
|
assert_equal :belongs_to, paranoid_time_with_deleted.macro
|
94
158
|
assert paranoid_time_with_deleted.options[:with_deleted]
|
95
159
|
end
|
96
160
|
|
97
161
|
def test_belongs_to_polymorphic_with_deleted_options
|
98
|
-
paranoid_time_polymorphic_with_deleted = ParanoidHasManyDependant.reflections
|
162
|
+
paranoid_time_polymorphic_with_deleted = ParanoidHasManyDependant.reflections
|
163
|
+
.with_indifferent_access[:paranoid_time_polymorphic_with_deleted]
|
99
164
|
assert_equal :belongs_to, paranoid_time_polymorphic_with_deleted.macro
|
100
165
|
assert paranoid_time_polymorphic_with_deleted.options[:with_deleted]
|
101
166
|
end
|
@@ -118,6 +183,50 @@ class AssociationsTest < ParanoidBaseTest
|
|
118
183
|
assert_equal [child], parent.paranoid_has_many_dependants.with_deleted.to_a
|
119
184
|
end
|
120
185
|
|
186
|
+
def test_join_with_model_with_deleted
|
187
|
+
obj = ParanoidHasManyDependant.create(paranoid_time: ParanoidTime.create)
|
188
|
+
assert_not_nil obj.paranoid_time
|
189
|
+
assert_not_nil obj.paranoid_time_with_deleted
|
190
|
+
|
191
|
+
obj.paranoid_time.destroy
|
192
|
+
obj.reload
|
193
|
+
|
194
|
+
assert_nil obj.paranoid_time
|
195
|
+
assert_not_nil obj.paranoid_time_with_deleted
|
196
|
+
|
197
|
+
# Note that obj is destroyed because of dependent: :destroy in ParanoidTime
|
198
|
+
assert obj.destroyed?
|
199
|
+
|
200
|
+
assert_empty ParanoidHasManyDependant.with_deleted.joins(:paranoid_time)
|
201
|
+
assert_equal [obj],
|
202
|
+
ParanoidHasManyDependant.with_deleted.joins(:paranoid_time_with_deleted)
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_includes_with_deleted
|
206
|
+
paranoid_time = ParanoidTime.first
|
207
|
+
paranoid_time.paranoid_has_many_dependants.create(name: "dependant!")
|
208
|
+
|
209
|
+
paranoid_time.destroy
|
210
|
+
|
211
|
+
ParanoidHasManyDependant.with_deleted
|
212
|
+
.includes(:paranoid_time_with_deleted).each do |hasmany|
|
213
|
+
assert_not_nil hasmany.paranoid_time_with_deleted
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_includes_with_deleted_with_polymorphic_parent
|
218
|
+
not_paranoid_parent = NotParanoidHasManyAsParent.create(name: "not paranoid parent")
|
219
|
+
paranoid_parent = ParanoidHasManyAsParent.create(name: "paranoid parent")
|
220
|
+
ParanoidBelongsToPolymorphic.create(name: "belongs_to", parent: not_paranoid_parent)
|
221
|
+
ParanoidBelongsToPolymorphic.create(name: "belongs_to", parent: paranoid_parent)
|
222
|
+
|
223
|
+
paranoid_parent.destroy
|
224
|
+
|
225
|
+
ParanoidBelongsToPolymorphic.with_deleted.includes(:parent).each do |hasmany|
|
226
|
+
assert_not_nil hasmany.parent
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
121
230
|
def test_cannot_find_a_paranoid_deleted_many_many_association
|
122
231
|
left = ParanoidManyManyParentLeft.create
|
123
232
|
right = ParanoidManyManyParentRight.create
|
@@ -128,8 +237,10 @@ class AssociationsTest < ParanoidBaseTest
|
|
128
237
|
left.reload
|
129
238
|
|
130
239
|
assert_equal [], left.paranoid_many_many_children, "Linking objects not deleted"
|
131
|
-
assert_equal [], left.paranoid_many_many_parent_rights,
|
132
|
-
|
240
|
+
assert_equal [], left.paranoid_many_many_parent_rights,
|
241
|
+
"Associated objects not unlinked"
|
242
|
+
assert_equal right, ParanoidManyManyParentRight.find(right.id),
|
243
|
+
"Associated object deleted"
|
133
244
|
end
|
134
245
|
|
135
246
|
def test_cannot_find_a_paranoid_destroyed_many_many_association
|
@@ -142,11 +253,13 @@ class AssociationsTest < ParanoidBaseTest
|
|
142
253
|
left.reload
|
143
254
|
|
144
255
|
assert_equal [], left.paranoid_many_many_children, "Linking objects not deleted"
|
145
|
-
assert_equal [], left.paranoid_many_many_parent_rights,
|
146
|
-
|
256
|
+
assert_equal [], left.paranoid_many_many_parent_rights,
|
257
|
+
"Associated objects not unlinked"
|
258
|
+
assert_equal right, ParanoidManyManyParentRight.find(right.id),
|
259
|
+
"Associated object deleted"
|
147
260
|
end
|
148
261
|
|
149
|
-
def
|
262
|
+
def test_cannot_find_a_has_many_through_object_when_its_linking_object_is_soft_destroyed
|
150
263
|
left = ParanoidManyManyParentLeft.create
|
151
264
|
right = ParanoidManyManyParentRight.create
|
152
265
|
left.paranoid_many_many_parent_rights << right
|
@@ -175,8 +288,10 @@ class AssociationsTest < ParanoidBaseTest
|
|
175
288
|
left.paranoid_many_many_parent_rights << right
|
176
289
|
|
177
290
|
child = left.paranoid_many_many_children.first
|
178
|
-
assert_equal left, child.paranoid_many_many_parent_left,
|
179
|
-
|
291
|
+
assert_equal left, child.paranoid_many_many_parent_left,
|
292
|
+
"Child's left parent is incorrect"
|
293
|
+
assert_equal right, child.paranoid_many_many_parent_right,
|
294
|
+
"Child's right parent is incorrect"
|
180
295
|
|
181
296
|
left.paranoid_many_many_parent_rights.clear
|
182
297
|
|
@@ -189,8 +304,10 @@ class AssociationsTest < ParanoidBaseTest
|
|
189
304
|
left.paranoid_many_many_parent_rights << right
|
190
305
|
|
191
306
|
child = left.paranoid_many_many_children.first
|
192
|
-
assert_equal left, child.paranoid_many_many_parent_left,
|
193
|
-
|
307
|
+
assert_equal left, child.paranoid_many_many_parent_left,
|
308
|
+
"Child's left parent is incorrect"
|
309
|
+
assert_equal right, child.paranoid_many_many_parent_right,
|
310
|
+
"Child's right parent is incorrect"
|
194
311
|
|
195
312
|
left.paranoid_many_many_parent_rights.destroy(right)
|
196
313
|
|
@@ -203,8 +320,10 @@ class AssociationsTest < ParanoidBaseTest
|
|
203
320
|
left.paranoid_many_many_parent_rights << right
|
204
321
|
|
205
322
|
child = left.paranoid_many_many_children.first
|
206
|
-
assert_equal left, child.paranoid_many_many_parent_left,
|
207
|
-
|
323
|
+
assert_equal left, child.paranoid_many_many_parent_left,
|
324
|
+
"Child's left parent is incorrect"
|
325
|
+
assert_equal right, child.paranoid_many_many_parent_right,
|
326
|
+
"Child's right parent is incorrect"
|
208
327
|
|
209
328
|
left.paranoid_many_many_parent_rights.delete(right)
|
210
329
|
|
@@ -228,9 +347,12 @@ class AssociationsTest < ParanoidBaseTest
|
|
228
347
|
end
|
229
348
|
|
230
349
|
def test_mass_assignment_of_paranoid_column_enabled
|
350
|
+
if Gem.loaded_specs["activerecord"].version >= Gem::Version.new("5.2.0")
|
351
|
+
skip "Creation as deleted is not supported with Rails >= 5.2"
|
352
|
+
end
|
231
353
|
now = Time.now
|
232
|
-
record = ParanoidTime.create! :
|
233
|
-
assert_equal
|
354
|
+
record = ParanoidTime.create! name: "Foo", deleted_at: now
|
355
|
+
assert_equal "Foo", record.name
|
234
356
|
assert_equal now, record.deleted_at
|
235
357
|
end
|
236
358
|
end
|
data/test/test_core.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
2
4
|
|
3
5
|
class ParanoidTest < ParanoidBaseTest
|
4
6
|
def test_paranoid?
|
@@ -69,6 +71,13 @@ class ParanoidTest < ParanoidBaseTest
|
|
69
71
|
assert_not_nil pt.paranoid_value
|
70
72
|
end
|
71
73
|
|
74
|
+
def test_non_persisted_delete
|
75
|
+
pt = ParanoidTime.new
|
76
|
+
assert_nil pt.paranoid_value
|
77
|
+
pt.delete
|
78
|
+
assert_not_nil pt.paranoid_value
|
79
|
+
end
|
80
|
+
|
72
81
|
def test_non_persisted_destroy!
|
73
82
|
pt = ParanoidTime.new
|
74
83
|
assert_nil pt.paranoid_value
|
@@ -94,12 +103,34 @@ class ParanoidTest < ParanoidBaseTest
|
|
94
103
|
assert_equal 1, ParanoidString.count
|
95
104
|
end
|
96
105
|
|
106
|
+
def test_recovery!
|
107
|
+
ParanoidBoolean.first.destroy
|
108
|
+
ParanoidBoolean.create(name: "paranoid")
|
109
|
+
|
110
|
+
assert_raise do
|
111
|
+
ParanoidBoolean.only_deleted.first.recover!
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Rails does not allow saving deleted records
|
116
|
+
def test_no_save_after_destroy
|
117
|
+
paranoid = ParanoidString.first
|
118
|
+
paranoid.destroy
|
119
|
+
paranoid.name = "Let's update!"
|
120
|
+
|
121
|
+
assert_not paranoid.save
|
122
|
+
assert_raises ActiveRecord::RecordNotSaved do
|
123
|
+
paranoid.save!
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
97
127
|
def setup_recursive_tests
|
98
128
|
@paranoid_time_object = ParanoidTime.first
|
99
129
|
|
100
130
|
# Create one extra ParanoidHasManyDependant record so that we can validate
|
101
131
|
# the correct dependants are recovered.
|
102
|
-
ParanoidTime.where(
|
132
|
+
ParanoidTime.where("id <> ?", @paranoid_time_object.id).first
|
133
|
+
.paranoid_has_many_dependants.create(name: "should not be recovered").destroy
|
103
134
|
|
104
135
|
@paranoid_boolean_count = ParanoidBoolean.count
|
105
136
|
|
@@ -108,20 +139,21 @@ class ParanoidTest < ParanoidBaseTest
|
|
108
139
|
assert_equal 1, NotParanoid.count
|
109
140
|
|
110
141
|
(1..3).each do |i|
|
111
|
-
has_many_object = @paranoid_time_object.paranoid_has_many_dependants
|
112
|
-
|
142
|
+
has_many_object = @paranoid_time_object.paranoid_has_many_dependants
|
143
|
+
.create(name: "has_many_#{i}")
|
144
|
+
has_many_object.create_paranoid_belongs_dependant(name: "belongs_to_#{i}")
|
113
145
|
has_many_object.save
|
114
146
|
|
115
|
-
paranoid_boolean = @paranoid_time_object.paranoid_booleans
|
116
|
-
|
147
|
+
paranoid_boolean = @paranoid_time_object.paranoid_booleans
|
148
|
+
.create(name: "boolean_#{i}")
|
149
|
+
paranoid_boolean.create_paranoid_has_one_dependant(name: "has_one_#{i}")
|
117
150
|
paranoid_boolean.save
|
118
151
|
|
119
|
-
@paranoid_time_object.not_paranoids.create(:
|
120
|
-
|
152
|
+
@paranoid_time_object.not_paranoids.create(name: "not_paranoid_a#{i}")
|
121
153
|
end
|
122
154
|
|
123
|
-
@paranoid_time_object.create_not_paranoid(:
|
124
|
-
@paranoid_time_object.create_has_one_not_paranoid(:
|
155
|
+
@paranoid_time_object.create_not_paranoid(name: "not_paranoid_belongs_to")
|
156
|
+
@paranoid_time_object.create_has_one_not_paranoid(name: "has_one_not_paranoid")
|
125
157
|
|
126
158
|
assert_equal 3, ParanoidTime.count
|
127
159
|
assert_equal 3, ParanoidHasManyDependant.count
|
@@ -172,7 +204,7 @@ class ParanoidTest < ParanoidBaseTest
|
|
172
204
|
@paranoid_time_object.destroy
|
173
205
|
@paranoid_time_object.reload
|
174
206
|
|
175
|
-
@paranoid_time_object.recover(:
|
207
|
+
@paranoid_time_object.recover(recursive: true)
|
176
208
|
|
177
209
|
assert_equal 3, ParanoidTime.count
|
178
210
|
assert_equal 3, ParanoidHasManyDependant.count
|
@@ -186,17 +218,21 @@ class ParanoidTest < ParanoidBaseTest
|
|
186
218
|
def test_recursive_recovery_dependant_window
|
187
219
|
setup_recursive_tests
|
188
220
|
|
189
|
-
@paranoid_time_object.destroy
|
190
|
-
@paranoid_time_object.reload
|
191
|
-
|
192
221
|
# Stop the following from recovering:
|
193
222
|
# - ParanoidHasManyDependant and its ParanoidBelongsDependant
|
194
223
|
# - A single ParanoidBelongsDependant, but not its parent
|
195
|
-
|
196
|
-
|
197
|
-
|
224
|
+
Time.stub :now, 2.days.ago do
|
225
|
+
@paranoid_time_object.paranoid_has_many_dependants.first.destroy
|
226
|
+
end
|
227
|
+
Time.stub :now, 1.hour.ago do
|
228
|
+
@paranoid_time_object.paranoid_has_many_dependants
|
229
|
+
.last.paranoid_belongs_dependant
|
230
|
+
.destroy
|
231
|
+
end
|
232
|
+
@paranoid_time_object.destroy
|
233
|
+
@paranoid_time_object.reload
|
198
234
|
|
199
|
-
@paranoid_time_object.recover(:
|
235
|
+
@paranoid_time_object.recover(recursive: true)
|
200
236
|
|
201
237
|
assert_equal 3, ParanoidTime.count
|
202
238
|
assert_equal 2, ParanoidHasManyDependant.count
|
@@ -209,31 +245,31 @@ class ParanoidTest < ParanoidBaseTest
|
|
209
245
|
|
210
246
|
def test_recursive_recovery_for_belongs_to_polymorphic
|
211
247
|
child_1 = ParanoidAndroid.create
|
212
|
-
section_1 = ParanoidSection.create(:
|
248
|
+
section_1 = ParanoidSection.create(paranoid_thing: child_1)
|
213
249
|
|
214
|
-
child_2 =
|
215
|
-
section_2 = ParanoidSection.create(:
|
250
|
+
child_2 = ParanoidPolygon.create(sides: 3)
|
251
|
+
section_2 = ParanoidSection.create(paranoid_thing: child_2)
|
216
252
|
|
217
253
|
assert_equal section_1.paranoid_thing, child_1
|
218
254
|
assert_equal section_1.paranoid_thing.class, ParanoidAndroid
|
219
255
|
assert_equal section_2.paranoid_thing, child_2
|
220
|
-
assert_equal section_2.paranoid_thing.class,
|
256
|
+
assert_equal section_2.paranoid_thing.class, ParanoidPolygon
|
221
257
|
|
222
|
-
parent = ParanoidTime.create(:
|
258
|
+
parent = ParanoidTime.create(name: "paranoid_parent")
|
223
259
|
parent.paranoid_sections << section_1
|
224
260
|
parent.paranoid_sections << section_2
|
225
261
|
|
226
262
|
assert_equal 4, ParanoidTime.count
|
227
263
|
assert_equal 2, ParanoidSection.count
|
228
264
|
assert_equal 1, ParanoidAndroid.count
|
229
|
-
assert_equal 1,
|
265
|
+
assert_equal 1, ParanoidPolygon.count
|
230
266
|
|
231
267
|
parent.destroy
|
232
268
|
|
233
269
|
assert_equal 3, ParanoidTime.count
|
234
270
|
assert_equal 0, ParanoidSection.count
|
235
271
|
assert_equal 0, ParanoidAndroid.count
|
236
|
-
assert_equal 0,
|
272
|
+
assert_equal 0, ParanoidPolygon.count
|
237
273
|
|
238
274
|
parent.reload
|
239
275
|
parent.recover
|
@@ -241,7 +277,7 @@ class ParanoidTest < ParanoidBaseTest
|
|
241
277
|
assert_equal 4, ParanoidTime.count
|
242
278
|
assert_equal 2, ParanoidSection.count
|
243
279
|
assert_equal 1, ParanoidAndroid.count
|
244
|
-
assert_equal 1,
|
280
|
+
assert_equal 1, ParanoidPolygon.count
|
245
281
|
end
|
246
282
|
|
247
283
|
def test_non_recursive_recovery
|
@@ -250,7 +286,7 @@ class ParanoidTest < ParanoidBaseTest
|
|
250
286
|
@paranoid_time_object.destroy
|
251
287
|
@paranoid_time_object.reload
|
252
288
|
|
253
|
-
@paranoid_time_object.recover(:
|
289
|
+
@paranoid_time_object.recover(recursive: false)
|
254
290
|
|
255
291
|
assert_equal 3, ParanoidTime.count
|
256
292
|
assert_equal 0, ParanoidHasManyDependant.count
|
@@ -261,6 +297,24 @@ class ParanoidTest < ParanoidBaseTest
|
|
261
297
|
assert_equal 0, HasOneNotParanoid.count
|
262
298
|
end
|
263
299
|
|
300
|
+
def test_dirty
|
301
|
+
pt = ParanoidTime.create
|
302
|
+
pt.destroy
|
303
|
+
assert_not pt.changed?
|
304
|
+
end
|
305
|
+
|
306
|
+
def test_delete_dirty
|
307
|
+
pt = ParanoidTime.create
|
308
|
+
pt.delete
|
309
|
+
assert_not pt.changed?
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_destroy_fully_dirty
|
313
|
+
pt = ParanoidTime.create
|
314
|
+
pt.destroy_fully!
|
315
|
+
assert_not pt.changed?
|
316
|
+
end
|
317
|
+
|
264
318
|
def test_deleted?
|
265
319
|
ParanoidTime.first.destroy
|
266
320
|
assert ParanoidTime.with_deleted.first.deleted?
|
@@ -269,6 +323,43 @@ class ParanoidTest < ParanoidBaseTest
|
|
269
323
|
assert ParanoidString.with_deleted.first.deleted?
|
270
324
|
end
|
271
325
|
|
326
|
+
def test_delete_deleted?
|
327
|
+
ParanoidTime.first.delete
|
328
|
+
assert ParanoidTime.with_deleted.first.deleted?
|
329
|
+
|
330
|
+
ParanoidString.first.delete
|
331
|
+
assert ParanoidString.with_deleted.first.deleted?
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_destroy_fully_deleted?
|
335
|
+
object = ParanoidTime.first
|
336
|
+
object.destroy_fully!
|
337
|
+
assert object.deleted?
|
338
|
+
|
339
|
+
object = ParanoidString.first
|
340
|
+
object.destroy_fully!
|
341
|
+
assert object.deleted?
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_deleted_fully?
|
345
|
+
ParanoidTime.first.destroy
|
346
|
+
assert_not ParanoidTime.with_deleted.first.deleted_fully?
|
347
|
+
|
348
|
+
ParanoidString.first.destroy
|
349
|
+
assert ParanoidString.with_deleted.first.deleted?
|
350
|
+
end
|
351
|
+
|
352
|
+
def test_delete_deleted_fully?
|
353
|
+
ParanoidTime.first.delete
|
354
|
+
assert_not ParanoidTime.with_deleted.first.deleted_fully?
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_destroy_fully_deleted_fully?
|
358
|
+
object = ParanoidTime.first
|
359
|
+
object.destroy_fully!
|
360
|
+
assert object.deleted_fully?
|
361
|
+
end
|
362
|
+
|
272
363
|
def test_paranoid_destroy_callbacks
|
273
364
|
@paranoid_with_callback = ParanoidWithCallback.first
|
274
365
|
ParanoidWithCallback.transaction do
|
@@ -308,6 +399,14 @@ class ParanoidTest < ParanoidBaseTest
|
|
308
399
|
assert @paranoid_with_callback.called_after_recover
|
309
400
|
end
|
310
401
|
|
402
|
+
def test_recovery_callbacks_without_destroy
|
403
|
+
@paranoid_with_callback = ParanoidWithCallback.first
|
404
|
+
@paranoid_with_callback.recover
|
405
|
+
|
406
|
+
assert_nil @paranoid_with_callback.called_before_recover
|
407
|
+
assert_nil @paranoid_with_callback.called_after_recover
|
408
|
+
end
|
409
|
+
|
311
410
|
def test_delete_by_multiple_id_is_paranoid
|
312
411
|
model_a = ParanoidBelongsDependant.create
|
313
412
|
model_b = ParanoidBelongsDependant.create
|
@@ -356,81 +455,179 @@ class ParanoidTest < ParanoidBaseTest
|
|
356
455
|
|
357
456
|
# Test string type columns that don't have a nil value when not deleted (Y/N for example)
|
358
457
|
def test_string_type_with_no_nil_value_before_destroy
|
359
|
-
ps = ParanoidString.create!(:
|
360
|
-
assert_equal 1, ParanoidString.where(:
|
458
|
+
ps = ParanoidString.create!(deleted: "not dead")
|
459
|
+
assert_equal 1, ParanoidString.where(id: ps).count
|
361
460
|
end
|
362
461
|
|
363
462
|
def test_string_type_with_no_nil_value_after_destroy
|
364
|
-
ps = ParanoidString.create!(:
|
463
|
+
ps = ParanoidString.create!(deleted: "not dead")
|
365
464
|
ps.destroy
|
366
|
-
assert_equal 0, ParanoidString.where(:
|
465
|
+
assert_equal 0, ParanoidString.where(id: ps).count
|
367
466
|
end
|
368
467
|
|
369
468
|
def test_string_type_with_no_nil_value_before_destroy_with_deleted
|
370
|
-
ps = ParanoidString.create!(:
|
371
|
-
assert_equal 1, ParanoidString.with_deleted.where(:
|
469
|
+
ps = ParanoidString.create!(deleted: "not dead")
|
470
|
+
assert_equal 1, ParanoidString.with_deleted.where(id: ps).count
|
372
471
|
end
|
373
472
|
|
374
473
|
def test_string_type_with_no_nil_value_after_destroy_with_deleted
|
375
|
-
ps = ParanoidString.create!(:
|
474
|
+
ps = ParanoidString.create!(deleted: "not dead")
|
376
475
|
ps.destroy
|
377
|
-
assert_equal 1, ParanoidString.with_deleted.where(:
|
476
|
+
assert_equal 1, ParanoidString.with_deleted.where(id: ps).count
|
378
477
|
end
|
379
478
|
|
380
479
|
def test_string_type_with_no_nil_value_before_destroy_only_deleted
|
381
|
-
ps = ParanoidString.create!(:
|
382
|
-
assert_equal 0, ParanoidString.only_deleted.where(:
|
480
|
+
ps = ParanoidString.create!(deleted: "not dead")
|
481
|
+
assert_equal 0, ParanoidString.only_deleted.where(id: ps).count
|
383
482
|
end
|
384
483
|
|
385
484
|
def test_string_type_with_no_nil_value_after_destroy_only_deleted
|
386
|
-
ps = ParanoidString.create!(:
|
485
|
+
ps = ParanoidString.create!(deleted: "not dead")
|
387
486
|
ps.destroy
|
388
|
-
assert_equal 1, ParanoidString.only_deleted.where(:
|
487
|
+
assert_equal 1, ParanoidString.only_deleted.where(id: ps).count
|
389
488
|
end
|
390
489
|
|
391
490
|
def test_string_type_with_no_nil_value_after_destroyed_twice
|
392
|
-
ps = ParanoidString.create!(:
|
491
|
+
ps = ParanoidString.create!(deleted: "not dead")
|
393
492
|
2.times { ps.destroy }
|
394
|
-
assert_equal 0, ParanoidString.with_deleted.where(:
|
493
|
+
assert_equal 0, ParanoidString.with_deleted.where(id: ps).count
|
395
494
|
end
|
396
495
|
|
397
496
|
# Test boolean type columns, that are not nullable
|
398
497
|
def test_boolean_type_with_no_nil_value_before_destroy
|
399
|
-
ps = ParanoidBooleanNotNullable.create!
|
400
|
-
assert_equal 1, ParanoidBooleanNotNullable.where(:
|
498
|
+
ps = ParanoidBooleanNotNullable.create!
|
499
|
+
assert_equal 1, ParanoidBooleanNotNullable.where(id: ps).count
|
401
500
|
end
|
402
501
|
|
403
502
|
def test_boolean_type_with_no_nil_value_after_destroy
|
404
|
-
ps = ParanoidBooleanNotNullable.create!
|
503
|
+
ps = ParanoidBooleanNotNullable.create!
|
405
504
|
ps.destroy
|
406
|
-
assert_equal 0, ParanoidBooleanNotNullable.where(:
|
505
|
+
assert_equal 0, ParanoidBooleanNotNullable.where(id: ps).count
|
407
506
|
end
|
408
507
|
|
409
508
|
def test_boolean_type_with_no_nil_value_before_destroy_with_deleted
|
410
|
-
ps = ParanoidBooleanNotNullable.create!
|
411
|
-
assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(:
|
509
|
+
ps = ParanoidBooleanNotNullable.create!
|
510
|
+
assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(id: ps).count
|
412
511
|
end
|
413
512
|
|
414
513
|
def test_boolean_type_with_no_nil_value_after_destroy_with_deleted
|
415
|
-
ps = ParanoidBooleanNotNullable.create!
|
514
|
+
ps = ParanoidBooleanNotNullable.create!
|
416
515
|
ps.destroy
|
417
|
-
assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(:
|
516
|
+
assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(id: ps).count
|
418
517
|
end
|
419
518
|
|
420
519
|
def test_boolean_type_with_no_nil_value_before_destroy_only_deleted
|
421
|
-
ps = ParanoidBooleanNotNullable.create!
|
422
|
-
assert_equal 0, ParanoidBooleanNotNullable.only_deleted.where(:
|
520
|
+
ps = ParanoidBooleanNotNullable.create!
|
521
|
+
assert_equal 0, ParanoidBooleanNotNullable.only_deleted.where(id: ps).count
|
423
522
|
end
|
424
523
|
|
425
524
|
def test_boolean_type_with_no_nil_value_after_destroy_only_deleted
|
426
|
-
ps = ParanoidBooleanNotNullable.create!
|
525
|
+
ps = ParanoidBooleanNotNullable.create!
|
427
526
|
ps.destroy
|
428
|
-
assert_equal 1, ParanoidBooleanNotNullable.only_deleted.where(:
|
527
|
+
assert_equal 1, ParanoidBooleanNotNullable.only_deleted.where(id: ps).count
|
429
528
|
end
|
430
529
|
|
431
530
|
def test_boolean_type_with_no_nil_value_after_destroyed_twice
|
432
|
-
ps = ParanoidBooleanNotNullable.create!
|
531
|
+
ps = ParanoidBooleanNotNullable.create!
|
532
|
+
2.times { ps.destroy }
|
533
|
+
assert_equal 0, ParanoidBooleanNotNullable.with_deleted.where(id: ps).count
|
534
|
+
end
|
535
|
+
|
536
|
+
def test_no_double_tap_destroys_fully
|
537
|
+
ps = ParanoidNoDoubleTapDestroysFully.create!
|
433
538
|
2.times { ps.destroy }
|
434
|
-
assert_equal
|
539
|
+
assert_equal 1, ParanoidNoDoubleTapDestroysFully.with_deleted.where(id: ps).count
|
540
|
+
end
|
541
|
+
|
542
|
+
def test_decrement_counters
|
543
|
+
paranoid_boolean = ParanoidBoolean.create!
|
544
|
+
paranoid_with_counter_cache = ParanoidWithCounterCache
|
545
|
+
.create!(paranoid_boolean: paranoid_boolean)
|
546
|
+
|
547
|
+
assert_equal 1, paranoid_boolean.paranoid_with_counter_caches_count
|
548
|
+
|
549
|
+
paranoid_with_counter_cache.destroy
|
550
|
+
|
551
|
+
assert_equal 0, paranoid_boolean.reload.paranoid_with_counter_caches_count
|
552
|
+
end
|
553
|
+
|
554
|
+
def test_decrement_custom_counters
|
555
|
+
paranoid_boolean = ParanoidBoolean.create!
|
556
|
+
paranoid_with_custom_counter_cache = ParanoidWithCustomCounterCache
|
557
|
+
.create!(paranoid_boolean: paranoid_boolean)
|
558
|
+
|
559
|
+
assert_equal 1, paranoid_boolean.custom_counter_cache
|
560
|
+
|
561
|
+
paranoid_with_custom_counter_cache.destroy
|
562
|
+
|
563
|
+
assert_equal 0, paranoid_boolean.reload.custom_counter_cache
|
564
|
+
end
|
565
|
+
|
566
|
+
def test_destroy_with_optional_belongs_to_and_counter_cache
|
567
|
+
ps = ParanoidWithCounterCacheOnOptionalBelognsTo.create!
|
568
|
+
ps.destroy
|
569
|
+
assert_equal 1, ParanoidWithCounterCacheOnOptionalBelognsTo.only_deleted
|
570
|
+
.where(id: ps).count
|
571
|
+
end
|
572
|
+
|
573
|
+
def test_hard_destroy_decrement_counters
|
574
|
+
paranoid_boolean = ParanoidBoolean.create!
|
575
|
+
paranoid_with_counter_cache = ParanoidWithCounterCache
|
576
|
+
.create!(paranoid_boolean: paranoid_boolean)
|
577
|
+
|
578
|
+
assert_equal 1, paranoid_boolean.paranoid_with_counter_caches_count
|
579
|
+
|
580
|
+
paranoid_with_counter_cache.destroy_fully!
|
581
|
+
|
582
|
+
assert_equal 0, paranoid_boolean.reload.paranoid_with_counter_caches_count
|
583
|
+
end
|
584
|
+
|
585
|
+
def test_hard_destroy_decrement_custom_counters
|
586
|
+
paranoid_boolean = ParanoidBoolean.create!
|
587
|
+
paranoid_with_custom_counter_cache = ParanoidWithCustomCounterCache
|
588
|
+
.create!(paranoid_boolean: paranoid_boolean)
|
589
|
+
|
590
|
+
assert_equal 1, paranoid_boolean.custom_counter_cache
|
591
|
+
|
592
|
+
paranoid_with_custom_counter_cache.destroy_fully!
|
593
|
+
|
594
|
+
assert_equal 0, paranoid_boolean.reload.custom_counter_cache
|
595
|
+
end
|
596
|
+
|
597
|
+
def test_increment_counters
|
598
|
+
paranoid_boolean = ParanoidBoolean.create!
|
599
|
+
paranoid_with_counter_cache = ParanoidWithCounterCache
|
600
|
+
.create!(paranoid_boolean: paranoid_boolean)
|
601
|
+
|
602
|
+
assert_equal 1, paranoid_boolean.paranoid_with_counter_caches_count
|
603
|
+
|
604
|
+
paranoid_with_counter_cache.destroy
|
605
|
+
|
606
|
+
assert_equal 0, paranoid_boolean.reload.paranoid_with_counter_caches_count
|
607
|
+
|
608
|
+
paranoid_with_counter_cache.recover
|
609
|
+
|
610
|
+
assert_equal 1, paranoid_boolean.reload.paranoid_with_counter_caches_count
|
611
|
+
end
|
612
|
+
|
613
|
+
def test_increment_custom_counters
|
614
|
+
paranoid_boolean = ParanoidBoolean.create!
|
615
|
+
paranoid_with_custom_counter_cache = ParanoidWithCustomCounterCache
|
616
|
+
.create!(paranoid_boolean: paranoid_boolean)
|
617
|
+
|
618
|
+
assert_equal 1, paranoid_boolean.custom_counter_cache
|
619
|
+
|
620
|
+
paranoid_with_custom_counter_cache.destroy
|
621
|
+
|
622
|
+
assert_equal 0, paranoid_boolean.reload.custom_counter_cache
|
623
|
+
|
624
|
+
paranoid_with_custom_counter_cache.recover
|
625
|
+
|
626
|
+
assert_equal 1, paranoid_boolean.reload.custom_counter_cache
|
627
|
+
end
|
628
|
+
|
629
|
+
def test_explicitly_setting_table_name_after_acts_as_paranoid_macro
|
630
|
+
assert_equal "explicit_table.deleted_at", ParanoidWithExplicitTableNameAfterMacro
|
631
|
+
.paranoid_column_reference
|
435
632
|
end
|
436
633
|
end
|