acts_as_audited_collection 0.3
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.
- data/LICENSE +19 -0
- data/README.md +144 -0
- data/Rakefile +45 -0
- data/generators/audited_collection_migration/USAGE +10 -0
- data/generators/audited_collection_migration/audited_collection_migration_generator.rb +9 -0
- data/generators/audited_collection_migration/templates/migration.rb +21 -0
- data/init.rb +3 -0
- data/install.rb +1 -0
- data/lib/acts_as_audited_collection.rb +230 -0
- data/lib/acts_as_audited_collection/collection_audit.rb +10 -0
- data/lib/tasks/acts_as_audited_collection_tasks.rake +4 -0
- data/rails/init.rb +5 -0
- data/spec/acts_as_audited_collection_spec.rb +483 -0
- data/spec/db/acts_as_audited_collection.sqlite3.db +0 -0
- data/spec/db/database.yml +3 -0
- data/spec/db/schema.rb +47 -0
- data/spec/debug.log +56964 -0
- data/spec/models.rb +69 -0
- data/spec/spec_helper.rb +19 -0
- data/uninstall.rb +1 -0
- metadata +82 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
# Released under the MIT license. See the LICENSE file for details
|
2
|
+
|
3
|
+
class CollectionAudit < ActiveRecord::Base
|
4
|
+
belongs_to :parent_record, :polymorphic => true
|
5
|
+
belongs_to :child_record, :polymorphic => true
|
6
|
+
belongs_to :user, :polymorphic => true
|
7
|
+
|
8
|
+
belongs_to :child_audit, :class_name => 'CollectionAudit'
|
9
|
+
has_many :parent_audits, :class_name => 'CollectionAudit', :foreign_key => :child_audit_id
|
10
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,483 @@
|
|
1
|
+
# Released under the MIT license. See the LICENSE file for details
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
4
|
+
|
5
|
+
describe 'Acts as audited collection plugin' do
|
6
|
+
it 'can be included in an ActiveRecord model' do
|
7
|
+
class A < ActiveRecord::Base
|
8
|
+
self
|
9
|
+
end.should respond_to :acts_as_audited_collection
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'requires a parent to be specified' do
|
13
|
+
lambda {
|
14
|
+
class B < ActiveRecord::Base
|
15
|
+
acts_as_audited_collection
|
16
|
+
end
|
17
|
+
}.should raise_error ActiveRecord::ConfigurationError
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'infers the collection name correctly from the class' do
|
21
|
+
class Person < ActiveRecord::Base
|
22
|
+
belongs_to :test_parent
|
23
|
+
|
24
|
+
acts_as_audited_collection :parent => :test_parent
|
25
|
+
|
26
|
+
audited_collections
|
27
|
+
end.should have_key :people
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'allows the audited collection through a belongs_to relationship' do
|
31
|
+
class Person < ActiveRecord::Base
|
32
|
+
belongs_to :test_parent
|
33
|
+
|
34
|
+
acts_as_audited_collection :parent => :test_parent
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'refuses the audited collection through a has_one relationship' do
|
39
|
+
lambda {
|
40
|
+
class Person < ActiveRecord::Base
|
41
|
+
has_one :test
|
42
|
+
|
43
|
+
acts_as_audited_collection :parent => :test
|
44
|
+
end
|
45
|
+
}.should raise_error ActiveRecord::ConfigurationError
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'refuses an audited collection parent where no child relation is specified' do
|
49
|
+
lambda {
|
50
|
+
class Person < ActiveRecord::Base
|
51
|
+
acts_as_audited_collection_parent
|
52
|
+
end
|
53
|
+
}.should raise_error ActiveRecord::ConfigurationError
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'refuses an audited collection parent through a belongs_to relationship' do
|
57
|
+
lambda {
|
58
|
+
class Person < ActiveRecord::Base
|
59
|
+
belongs_to :test
|
60
|
+
|
61
|
+
acts_as_audited_collection_parent :for => :test
|
62
|
+
end
|
63
|
+
}.should raise_error ActiveRecord::ConfigurationError
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'allows an audited collection parent through a has_many relationship' do
|
67
|
+
class Person < ActiveRecord::Base
|
68
|
+
has_many :tests
|
69
|
+
|
70
|
+
acts_as_audited_collection_parent :for => :tests
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'configures an audited collection for cascading when required' do
|
75
|
+
class Person < ActiveRecord::Base
|
76
|
+
belongs_to :test_parent
|
77
|
+
|
78
|
+
acts_as_audited_collection :parent => :test_parent, :cascade => true
|
79
|
+
end
|
80
|
+
|
81
|
+
Person.audited_collections.should have_key :people
|
82
|
+
Person.audited_collections[:people].should have_key :cascade
|
83
|
+
Person.audited_collections[:people][:cascade].should be_true
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'configures an audited collection to track modificiations when required' do
|
87
|
+
class Person < ActiveRecord::Base
|
88
|
+
belongs_to :test_parent
|
89
|
+
|
90
|
+
acts_as_audited_collection :parent => :test_parent, :track_modifications => true
|
91
|
+
end
|
92
|
+
|
93
|
+
Person.audited_collections.should have_key :people
|
94
|
+
Person.audited_collections[:people].should have_key :track_modifications
|
95
|
+
Person.audited_collections[:people][:track_modifications].should be_true
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'audits an object creation when relationships are defined' do
|
99
|
+
p = TestParent.create :name => 'test parent'
|
100
|
+
c = nil
|
101
|
+
lambda {
|
102
|
+
c = p.test_children.create :name => 'test child'
|
103
|
+
}.should change(CollectionAudit, :count).by(1)
|
104
|
+
|
105
|
+
CollectionAudit.last.child_record.should == c
|
106
|
+
CollectionAudit.last.parent_record.should == p
|
107
|
+
CollectionAudit.last.action.should == 'add'
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'skips auditing on object creation when no relationships are defined' do
|
111
|
+
p = TestParent.create :name => 'test parent'
|
112
|
+
lambda {
|
113
|
+
c = TestChild.create :name => 'test child'
|
114
|
+
}.should_not change(CollectionAudit, :count)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'audits an object modification when a relation is created' do
|
118
|
+
c = TestChild.create :name => 'test child'
|
119
|
+
p = TestParent.create :name => 'test parent'
|
120
|
+
|
121
|
+
lambda {
|
122
|
+
c.test_parent = p
|
123
|
+
c.save!
|
124
|
+
}.should change(CollectionAudit, :count).by(1)
|
125
|
+
|
126
|
+
CollectionAudit.last.child_record.should == c
|
127
|
+
CollectionAudit.last.parent_record.should == p
|
128
|
+
CollectionAudit.last.action.should == 'add'
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'skips auditing on object modification when no relationships are altered' do
|
132
|
+
c = TestChild.create :name => 'test child'
|
133
|
+
p = TestParent.create :name => 'test parent'
|
134
|
+
|
135
|
+
lambda {
|
136
|
+
c.name = 'new name'
|
137
|
+
c.save!
|
138
|
+
}.should_not change(CollectionAudit, :count)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'audits an object modification when a relationship is removed' do
|
142
|
+
p = TestParent.create :name => 'test parent'
|
143
|
+
c = p.test_children.create :name => 'test child'
|
144
|
+
|
145
|
+
lambda {
|
146
|
+
c.test_parent = nil
|
147
|
+
c.save!
|
148
|
+
}.should change(CollectionAudit, :count).by(1)
|
149
|
+
|
150
|
+
CollectionAudit.last.child_record.should == c
|
151
|
+
CollectionAudit.last.parent_record.should == p
|
152
|
+
CollectionAudit.last.action.should == 'remove'
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'audits an object deletion when a relationship exists' do
|
156
|
+
p = TestParent.create :name => 'test parent'
|
157
|
+
c = p.test_children.create :name => 'test child'
|
158
|
+
|
159
|
+
lambda {
|
160
|
+
c.destroy.should be_true
|
161
|
+
}.should change(CollectionAudit, :count).by(1)
|
162
|
+
|
163
|
+
# child_record will be nil, because the record has been deleted.
|
164
|
+
CollectionAudit.last.child_record_id.should == c.id
|
165
|
+
CollectionAudit.last.parent_record.should == p
|
166
|
+
CollectionAudit.last.action.should == 'remove'
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'skips auditing an object deletion when no relationships exist' do
|
170
|
+
c = TestChild.create :name => 'test child'
|
171
|
+
|
172
|
+
lambda {
|
173
|
+
c.destroy.should be_true
|
174
|
+
}.should_not change(CollectionAudit, :count)
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'saves the collection name with the audit entry' do
|
178
|
+
p = TestParent.create :name => 'test parent'
|
179
|
+
c = p.test_children.create :name => 'test child'
|
180
|
+
CollectionAudit.last.association.should == 'test_children'
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'makes the collection history available through the parent class' do
|
184
|
+
p = TestParent.create :name => 'test parent'
|
185
|
+
c = p.test_children.create :name => 'test child'
|
186
|
+
|
187
|
+
p.test_children_audits.should include CollectionAudit.last
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'correctly audits a secondary collection' do
|
191
|
+
p = TestParent.create :name => 'test parent'
|
192
|
+
c = nil
|
193
|
+
lambda {
|
194
|
+
c = p.other_test_children.create :name => 'test child'
|
195
|
+
}.should change(CollectionAudit, :count).by(1)
|
196
|
+
|
197
|
+
# Basic sanity checking, to make sure the model stays valid
|
198
|
+
p.other_test_children.should include c
|
199
|
+
p.test_children.should be_empty
|
200
|
+
c.other_test_parent.should == p
|
201
|
+
c.test_parent.should be_nil
|
202
|
+
|
203
|
+
p.test_children_audits.should be_empty
|
204
|
+
p.other_test_children_audits.length.should == 1
|
205
|
+
|
206
|
+
p.other_test_children_audits.last.child_record.should == c
|
207
|
+
p.other_test_children_audits.last.parent_record.should == p
|
208
|
+
p.other_test_children_audits.last.action.should == 'add'
|
209
|
+
p.other_test_children_audits.last.association.should == 'other_test_children'
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'correctly audits when a parent is reassociated through a secondary collection' do
|
213
|
+
p = TestParent.create :name => 'test parent'
|
214
|
+
c = p.test_children.create :name => 'test child'
|
215
|
+
lambda {
|
216
|
+
c.test_parent = nil
|
217
|
+
c.other_test_parent = p
|
218
|
+
c.save!
|
219
|
+
}.should change(CollectionAudit, :count).by(2)
|
220
|
+
|
221
|
+
# One from the initial creation
|
222
|
+
p.test_children_audits.length.should == 2
|
223
|
+
p.test_children_audits.should be_all { |a| a.child_record == c }
|
224
|
+
p.test_children_audits.first.action.should == 'add'
|
225
|
+
p.test_children_audits.last.action.should == 'remove'
|
226
|
+
p.other_test_children_audits.length.should == 1
|
227
|
+
p.other_test_children_audits.should be_all { |a| a.child_record == c && a.action == 'add' }
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'correctly audits when a child is assigned to a new parent' do
|
231
|
+
p1 = TestParent.create :name => 'test parent'
|
232
|
+
c = p1.test_children.create :name => 'test child'
|
233
|
+
p2 = TestParent.create :name => 'another parent'
|
234
|
+
|
235
|
+
lambda {
|
236
|
+
c.test_parent = p2
|
237
|
+
c.save!
|
238
|
+
}.should change(CollectionAudit, :count).by(2)
|
239
|
+
|
240
|
+
# One from the initial creation
|
241
|
+
p1.test_children_audits.length.should == 2
|
242
|
+
p1.test_children_audits.should be_all { |a| a.child_record == c }
|
243
|
+
p1.test_children_audits.first.action.should == 'add'
|
244
|
+
p1.test_children_audits.last.action.should == 'remove'
|
245
|
+
p2.test_children_audits.length.should == 1
|
246
|
+
p2.test_children_audits.should be_all { |a| a.child_record == c && a.action == 'add' }
|
247
|
+
end
|
248
|
+
|
249
|
+
it 'disables collection auditing for a block passed to the without_collection_audit method' do
|
250
|
+
p = TestParent.create :name => 'test parent'
|
251
|
+
c = nil
|
252
|
+
lambda {
|
253
|
+
result = TestChild.without_collection_audit do
|
254
|
+
c = p.test_children.create :name => 'test child'
|
255
|
+
end
|
256
|
+
|
257
|
+
# Make sure we get the right return value
|
258
|
+
result.should == c
|
259
|
+
}.should_not change(CollectionAudit, :count)
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'enables collection auditing after completion of a block passed to the without_collection_audit method' do
|
263
|
+
p = TestParent.create :name => 'test parent'
|
264
|
+
TestChild.without_collection_audit do
|
265
|
+
p.test_children.create :name => 'test child'
|
266
|
+
end
|
267
|
+
lambda {
|
268
|
+
p.test_children.create :name => 'another child'
|
269
|
+
}.should change(CollectionAudit, :count).by(1)
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'tracks modifications through an auditing collection with modification tracking enabled' do
|
273
|
+
p = TestParent.create :name => 'test parent'
|
274
|
+
c = p.other_test_children.create :name => 'test child'
|
275
|
+
|
276
|
+
lambda {
|
277
|
+
c.name = 'new name'
|
278
|
+
c.save!
|
279
|
+
}.should change(CollectionAudit, :count).by(1)
|
280
|
+
|
281
|
+
CollectionAudit.last.child_record.should == c
|
282
|
+
CollectionAudit.last.parent_record.should == p
|
283
|
+
CollectionAudit.last.action.should == 'modify'
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'tracks modifications to attributes listed in :only' do
|
287
|
+
p = TestParent.create :name => 'test parent'
|
288
|
+
c = p.test_children_with_only.create :name => 'test child'
|
289
|
+
|
290
|
+
lambda {
|
291
|
+
c.name = 'new name'
|
292
|
+
c.save!
|
293
|
+
}.should change(CollectionAudit, :count).by(1)
|
294
|
+
|
295
|
+
CollectionAudit.last.child_record.should == c
|
296
|
+
CollectionAudit.last.parent_record.should == p
|
297
|
+
CollectionAudit.last.action.should == 'modify'
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'ignores modifications to attributes not listed in :only' do
|
301
|
+
p = TestParent.create :name => 'test parent'
|
302
|
+
c = p.test_children_with_only.create :name => 'test child'
|
303
|
+
|
304
|
+
lambda {
|
305
|
+
c.description = 'new description'
|
306
|
+
c.save!
|
307
|
+
}.should_not change(CollectionAudit, :count)
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'ignores modifications to attributes listed in :except' do
|
311
|
+
p = TestParent.create :name => 'test parent'
|
312
|
+
c = p.test_children_with_except.create :name => 'test child'
|
313
|
+
|
314
|
+
lambda {
|
315
|
+
c.name = 'new name'
|
316
|
+
c.save!
|
317
|
+
}.should_not change(CollectionAudit, :count)
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'tracks modifications to attributes not listed in :except' do
|
321
|
+
p = TestParent.create :name => 'test parent'
|
322
|
+
c = p.test_children_with_except.create :name => 'test child'
|
323
|
+
|
324
|
+
lambda {
|
325
|
+
c.description = 'new name'
|
326
|
+
c.save!
|
327
|
+
}.should change(CollectionAudit, :count).by(1)
|
328
|
+
|
329
|
+
CollectionAudit.last.child_record.should == c
|
330
|
+
CollectionAudit.last.parent_record.should == p
|
331
|
+
CollectionAudit.last.action.should == 'modify'
|
332
|
+
end
|
333
|
+
|
334
|
+
it 'tracks grandchild modifications through a cascading auditing collection' do
|
335
|
+
p = TestParent.create :name => 'test parent'
|
336
|
+
# other_test_children has track_modifications enabled
|
337
|
+
c = p.other_test_children.create :name => 'test child'
|
338
|
+
g = nil
|
339
|
+
lambda {
|
340
|
+
g = c.test_grandchildren.create :name => 'test grandchild'
|
341
|
+
}.should change(CollectionAudit, :count).by(2)
|
342
|
+
|
343
|
+
audits = CollectionAudit.find :all, :order => 'id desc', :limit => 2
|
344
|
+
# First the grandchild would have been logged ..
|
345
|
+
audits[1].child_record.should == g
|
346
|
+
audits[1].parent_record.should == c
|
347
|
+
audits[1].action.should == 'add'
|
348
|
+
# .. then the child would have been logged.
|
349
|
+
audits[0].child_record.should == c
|
350
|
+
audits[0].parent_record.should == p
|
351
|
+
audits[0].action.should == 'modify'
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'tracks a grandchild being reassociated with a different child' do
|
355
|
+
p = TestParent.create :name => 'test parent'
|
356
|
+
# other_test_children has track_modifications enabled
|
357
|
+
c1 = p.other_test_children.create :name => 'test child'
|
358
|
+
c2 = p.other_test_children.create :name => 'another child'
|
359
|
+
g = c1.test_grandchildren.create :name => 'test grandchild'
|
360
|
+
|
361
|
+
lambda {
|
362
|
+
g.update_attributes :test_child => c2
|
363
|
+
}.should change(CollectionAudit, :count).by(4)
|
364
|
+
|
365
|
+
audits = CollectionAudit.find :all, :order => 'id desc', :limit => 4
|
366
|
+
|
367
|
+
# First the grandchild removal would have been logged ..
|
368
|
+
audits[3].child_record.should == g
|
369
|
+
audits[3].parent_record.should == c1
|
370
|
+
audits[3].action.should == 'remove'
|
371
|
+
# .. then the child 1 modification would have been logged ..
|
372
|
+
audits[2].child_record.should == c1
|
373
|
+
audits[2].parent_record.should == p
|
374
|
+
audits[2].action.should == 'modify'
|
375
|
+
# .. then the grandchild addition would have been logged ..
|
376
|
+
audits[1].child_record.should == g
|
377
|
+
audits[1].parent_record.should == c2
|
378
|
+
audits[1].action.should == 'add'
|
379
|
+
# .. then the child 2 modification would have been logged.
|
380
|
+
audits[0].child_record.should == c2
|
381
|
+
audits[0].parent_record.should == p
|
382
|
+
audits[0].action.should == 'modify'
|
383
|
+
end
|
384
|
+
|
385
|
+
it 'tracks great-grandchild modifications through a cascading auditing collection' do
|
386
|
+
p = TestParent.create :name => 'test parent'
|
387
|
+
c = p.other_test_children.create :name => 'test child'
|
388
|
+
g = c.test_grandchildren.create :name => 'test grandchild'
|
389
|
+
gg = nil
|
390
|
+
|
391
|
+
lambda {
|
392
|
+
gg = g.test_great_grandchildren.create :name => 'test great-grandchild'
|
393
|
+
}.should change(CollectionAudit, :count).by(3)
|
394
|
+
|
395
|
+
audits = CollectionAudit.find :all, :order => 'id desc', :limit => 3
|
396
|
+
# First the great-grandchild would have been logged ..
|
397
|
+
audits[2].child_record.should == gg
|
398
|
+
audits[2].parent_record.should == g
|
399
|
+
audits[2].action.should == 'add'
|
400
|
+
# .. then the grandchild would have been logged ..
|
401
|
+
audits[1].child_record.should == g
|
402
|
+
audits[1].parent_record.should == c
|
403
|
+
audits[1].action.should == 'modify'
|
404
|
+
# .. then the child would have been logged.
|
405
|
+
audits[0].child_record.should == c
|
406
|
+
audits[0].parent_record.should == p
|
407
|
+
audits[0].action.should == 'modify'
|
408
|
+
end
|
409
|
+
|
410
|
+
it 'tracks the child audit of a cascading audit' do
|
411
|
+
p = TestParent.create :name => 'test parent'
|
412
|
+
# other_test_children has track_modifications enabled
|
413
|
+
c = p.other_test_children.create :name => 'test child'
|
414
|
+
g = c.test_grandchildren.create :name => 'test grandchild'
|
415
|
+
|
416
|
+
pa = p.other_test_children_audits.last
|
417
|
+
ca = c.test_grandchildren_audits.last
|
418
|
+
pa.child_audit.should == ca
|
419
|
+
ca.parent_audits.should == [pa]
|
420
|
+
end
|
421
|
+
|
422
|
+
it 'reports a soft delete as if it were a delete' do
|
423
|
+
p = TestChild.create :name => 'test parent'
|
424
|
+
c = p.test_soft_delete_grandchildren.create :name => 'test child'
|
425
|
+
lambda {
|
426
|
+
c.update_attributes! :deleted => true
|
427
|
+
}.should change(CollectionAudit, :count).by(1)
|
428
|
+
|
429
|
+
CollectionAudit.last.action.should == 'remove'
|
430
|
+
CollectionAudit.last.parent_record.should == p
|
431
|
+
CollectionAudit.last.child_record.should == c
|
432
|
+
end
|
433
|
+
|
434
|
+
it 'ignores an object which is soft deleted when created' do
|
435
|
+
p = TestChild.create :name => 'test parent'
|
436
|
+
lambda {
|
437
|
+
c = p.test_soft_delete_grandchildren.create :name => 'test child',
|
438
|
+
:deleted => true
|
439
|
+
}.should_not change(CollectionAudit, :count)
|
440
|
+
end
|
441
|
+
|
442
|
+
it 'ignores a changed object which is soft deleted' do
|
443
|
+
p = TestChild.create :name => 'test parent'
|
444
|
+
c = p.test_soft_delete_grandchildren.create :name => 'test child',
|
445
|
+
:deleted => true
|
446
|
+
lambda {
|
447
|
+
c.update_attributes! :name => 'test child with new name'
|
448
|
+
}.should_not change(CollectionAudit, :count)
|
449
|
+
end
|
450
|
+
|
451
|
+
it 'reports a soft undelete as if it were an add' do
|
452
|
+
p = TestChild.create :name => 'test parent'
|
453
|
+
c = p.test_soft_delete_grandchildren.create :name => 'test child',
|
454
|
+
:deleted => true
|
455
|
+
lambda {
|
456
|
+
c.update_attributes! :deleted => false
|
457
|
+
}.should change(CollectionAudit, :count).by(1)
|
458
|
+
|
459
|
+
CollectionAudit.last.action.should == 'add'
|
460
|
+
CollectionAudit.last.parent_record.should == p
|
461
|
+
CollectionAudit.last.child_record.should == c
|
462
|
+
end
|
463
|
+
|
464
|
+
it 'cascades a soft delete upward as a normal delete' do
|
465
|
+
p = TestParent.create :name => 'test parent'
|
466
|
+
c = p.other_test_children.create :name => 'test child'
|
467
|
+
g = c.test_soft_delete_grandchildren.create :name => 'test grandchild'
|
468
|
+
lambda {
|
469
|
+
g.update_attributes! :deleted => true
|
470
|
+
}.should change(CollectionAudit, :count).by(2)
|
471
|
+
|
472
|
+
ca = CollectionAudit.last
|
473
|
+
ca.action.should == 'modify'
|
474
|
+
ca.child_record.should == c
|
475
|
+
ca.parent_record.should == p
|
476
|
+
|
477
|
+
ca = ca.child_audit
|
478
|
+
ca.should_not be_nil
|
479
|
+
ca.action.should == 'remove'
|
480
|
+
ca.child_record.should == g
|
481
|
+
ca.parent_record.should == c
|
482
|
+
end
|
483
|
+
end
|