acts_as_audited_customized 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ module CollectiveIdea #:nodoc:
2
+ module ActionController #:nodoc:
3
+ module Audited #:nodoc:
4
+ def audit(*models)
5
+ ActiveSupport::Deprecation.warn("#audit is deprecated. Declare #acts_as_audited in your models.", caller)
6
+
7
+ options = models.extract_options!
8
+
9
+ # Parse the options hash looking for classes
10
+ options.each_key do |key|
11
+ models << [key, options.delete(key)] if key.is_a?(Class)
12
+ end
13
+
14
+ models.each do |(model, model_options)|
15
+ model.send :acts_as_audited, model_options || {}
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ class AuditSweeper < ActionController::Caching::Sweeper #:nodoc:
23
+ def before_create(audit)
24
+ audit.send("#{CollectiveIdea::Acts::Audited.human_model}=", current_user) unless audit.send(CollectiveIdea::Acts::Audited.human_model)
25
+ end
26
+
27
+ def current_user
28
+ method = "current_#{CollectiveIdea::Acts::Audited.human_model}"
29
+ controller.send(method) if controller.respond_to?(method, true)
30
+ end
31
+ end
32
+
33
+ ActionController::Base.class_eval do
34
+ extend CollectiveIdea::ActionController::Audited
35
+ cache_sweeper :audit_sweeper
36
+ end
37
+ Audit.add_observer(AuditSweeper.instance)
data/rails/init.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'acts_as_audited'
2
+
3
+ ActiveRecord::Base.send :include, CollectiveIdea::Acts::Audited
4
+
5
+ if defined?(ActionController) and defined?(ActionController::Base)
6
+ require 'acts_as_audited/audit_sweeper'
7
+ end
@@ -0,0 +1,374 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ module CollectiveIdea
4
+ module Acts
5
+ class AuditedTest < Test::Unit::TestCase
6
+ should "include instance methods" do
7
+ User.new.should be_kind_of(CollectiveIdea::Acts::Audited::InstanceMethods)
8
+ end
9
+
10
+ should "extend singleton methods" do
11
+ User.should be_kind_of(CollectiveIdea::Acts::Audited::SingletonMethods)
12
+ end
13
+
14
+ ['created_at', 'updated_at', 'created_on', 'updated_on', 'lock_version', 'id', 'password'].each do |column|
15
+ should "not audit #{column}" do
16
+ User.non_audited_columns.should include(column)
17
+ end
18
+ end
19
+
20
+ should "not save non-audited columns" do
21
+ create_user.audits.first.changes.keys.any?{|col| ['created_at', 'updated_at', 'password'].include? col}.should be(false)
22
+ end
23
+
24
+ context "on create" do
25
+ setup { @user = create_user }
26
+
27
+ should_change 'Audit.count', :by => 1
28
+
29
+ should 'create associated audit' do
30
+ @user.audits.count.should == 1
31
+ end
32
+
33
+ should "set the action to 'create'" do
34
+ @user.audits.first.action.should == 'create'
35
+ end
36
+
37
+ should "store all the audited attributes" do
38
+ @user.audits.first.changes.should == @user.audited_attributes
39
+ end
40
+
41
+ should "not audit an attribute which is excepted if specified on create and on destroy" do
42
+ on_create_destroy_except_name = OnCreateDestroyExceptName.create(:name => 'Bart')
43
+ on_create_destroy_except_name.audits.first.changes.keys.any?{|col| ['name'].include? col}.should be(false)
44
+ end
45
+
46
+ should "not save an audit if only specified on update and on destroy" do
47
+ lambda { on_update_destroy = OnUpdateDestroy.create(:name => 'Bart') }.should_not change { Audit.count }
48
+ end
49
+ end
50
+
51
+ context "on update" do
52
+ setup do
53
+ @user = create_user(:name => 'Brandon')
54
+ end
55
+
56
+ should "save an audit" do
57
+ lambda { @user.update_attribute(:name, "Someone") }.should change { @user.audits.count }.by(1)
58
+ lambda { @user.update_attribute(:name, "Someone else") }.should change { @user.audits.count }.by(1)
59
+ end
60
+
61
+ should "not save an audit if the record is not changed" do
62
+ lambda { @user.save! }.should_not change { Audit.count }
63
+ end
64
+
65
+ should "set the action to 'update'" do
66
+ @user.update_attributes :name => 'Changed'
67
+ @user.audits.last.action.should == 'update'
68
+ end
69
+
70
+ should "store the changed attributes" do
71
+ @user.update_attributes :name => 'Changed'
72
+ @user.audits.last.changes.should == {'name' => ['Brandon', 'Changed']}
73
+ end
74
+
75
+ # Dirty tracking in Rails 2.0-2.2 had issues with type casting
76
+ if ActiveRecord::VERSION::STRING >= '2.3'
77
+ should "not save an audit if the value doesn't change after type casting" do
78
+ @user.update_attributes! :logins => 0, :activated => true
79
+ lambda { @user.update_attribute :logins, '0' }.should_not change { Audit.count }
80
+ lambda { @user.update_attribute :activated, 1 }.should_not change { Audit.count }
81
+ lambda { @user.update_attribute :activated, '1' }.should_not change { Audit.count }
82
+ end
83
+ end
84
+
85
+ should "not save an audit if only specified on create and on destroy" do
86
+ on_create_destroy = OnCreateDestroy.create(:name => 'Bart')
87
+ lambda { on_create_destroy.update_attributes :name => 'Changed' }.should_not change { Audit.count }
88
+ end
89
+ end
90
+
91
+ context "on destroy" do
92
+ setup do
93
+ @user = create_user
94
+ end
95
+
96
+ should "save an audit" do
97
+ lambda { @user.destroy }.should change { Audit.count }.by(1)
98
+ @user.audits.size.should == 2
99
+ end
100
+
101
+ should "set the action to 'destroy'" do
102
+ @user.destroy
103
+ @user.audits.last.action.should == 'destroy'
104
+ end
105
+
106
+ should "store all of the audited attributes" do
107
+ @user.destroy
108
+ @user.audits.last.changes.should == @user.audited_attributes
109
+ end
110
+
111
+ should "be able to reconstruct destroyed record without history" do
112
+ @user.audits.delete_all
113
+ @user.destroy
114
+ revision = @user.audits.first.revision
115
+ revision.name.should == @user.name
116
+ end
117
+
118
+ should "not save an audit if only specified on create and on update" do
119
+ on_create_update = OnCreateUpdate.create(:name => 'Bart')
120
+ lambda { on_create_update.destroy }.should_not change { Audit.count }
121
+ end
122
+ end
123
+
124
+ context "dirty tracking" do
125
+ setup do
126
+ @user = create_user
127
+ end
128
+
129
+ should "not be changed when the record is saved" do
130
+ u = User.new(:name => 'Brandon')
131
+ u.changed?.should be(true)
132
+ u.save
133
+ u.changed?.should be(false)
134
+ end
135
+
136
+ should "be changed when an attribute has been changed" do
137
+ @user.name = "Bobby"
138
+ @user.changed?.should be(true)
139
+ @user.name_changed?.should be(true)
140
+ @user.username_changed?.should be(false)
141
+ end
142
+
143
+ # Dirty tracking in Rails 2.0-2.2 had issues with type casting
144
+ if ActiveRecord::VERSION::STRING >= '2.3'
145
+ should "not be changed if the value doesn't change after type casting" do
146
+ @user.update_attributes! :logins => 0, :activated => true
147
+ @user.logins = '0'
148
+ @user.changed?.should be(false)
149
+ end
150
+ end
151
+
152
+ end
153
+
154
+ context "revisions" do
155
+ setup do
156
+ @user = create_versions
157
+ end
158
+
159
+ should "be an Array of Users" do
160
+ @user.revisions.should be_kind_of(Array)
161
+ @user.revisions.each {|version| version.should be_kind_of(User) }
162
+ end
163
+
164
+ should "have one revision for a new record" do
165
+ create_user.revisions.size.should == 1
166
+ end
167
+
168
+ should "have one revision for each audit" do
169
+ @user.revisions.size.should == @user.audits.size
170
+ end
171
+
172
+ should "set the attributes for each revision" do
173
+ u = User.create(:name => 'Brandon', :username => 'brandon')
174
+ u.update_attributes :name => 'Foobar'
175
+ u.update_attributes :name => 'Awesome', :username => 'keepers'
176
+
177
+ u.revisions.size.should == 3
178
+
179
+ u.revisions[0].name.should == 'Brandon'
180
+ u.revisions[0].username.should == 'brandon'
181
+
182
+ u.revisions[1].name.should == 'Foobar'
183
+ u.revisions[1].username.should == 'brandon'
184
+
185
+ u.revisions[2].name.should == 'Awesome'
186
+ u.revisions[2].username.should == 'keepers'
187
+ end
188
+
189
+ should "access to only recent revisions" do
190
+ u = User.create(:name => 'Brandon', :username => 'brandon')
191
+ u.update_attributes :name => 'Foobar'
192
+ u.update_attributes :name => 'Awesome', :username => 'keepers'
193
+
194
+ u.revisions(2).size.should == 2
195
+
196
+ u.revisions(2)[0].name.should == 'Foobar'
197
+ u.revisions(2)[0].username.should == 'brandon'
198
+
199
+ u.revisions(2)[1].name.should == 'Awesome'
200
+ u.revisions(2)[1].username.should == 'keepers'
201
+ end
202
+
203
+ should "be empty if no audits exist" do
204
+ @user.audits.delete_all
205
+ @user.revisions.empty?.should be(true)
206
+ end
207
+
208
+ should "ignore attributes that have been deleted" do
209
+ @user.audits.last.update_attributes :changes => {:old_attribute => 'old value'}
210
+ lambda { @user.revisions }.should_not raise_error
211
+ end
212
+
213
+ end
214
+
215
+ context "revision" do
216
+ setup do
217
+ @user = create_versions(5)
218
+ end
219
+
220
+ should "maintain identity" do
221
+ @user.revision(1).should == @user
222
+ end
223
+
224
+ should "find the given revision" do
225
+ revision = @user.revision(3)
226
+ revision.should be_kind_of(User)
227
+ revision.version.should == 3
228
+ revision.name.should == 'Foobar 3'
229
+ end
230
+
231
+ should "find the previous revision with :previous" do
232
+ revision = @user.revision(:previous)
233
+ revision.version.should == 4
234
+ revision.should == @user.revision(4)
235
+ end
236
+
237
+ should "be able to get the previous revision repeatedly" do
238
+ previous = @user.revision(:previous)
239
+ previous.version.should == 4
240
+ previous.revision(:previous).version.should == 3
241
+ end
242
+
243
+ should "be able to set protected attributes" do
244
+ u = User.create(:name => 'Brandon')
245
+ u.update_attribute :logins, 1
246
+ u.update_attribute :logins, 2
247
+
248
+ u.revision(3).logins.should == 2
249
+ u.revision(2).logins.should == 1
250
+ u.revision(1).logins.should == 0
251
+ end
252
+
253
+ should "set attributes directly" do
254
+ u = User.create(:name => '<Joe>')
255
+ u.revision(1).name.should == '&lt;Joe&gt;'
256
+ end
257
+
258
+ should "set the attributes for each revision" do
259
+ u = User.create(:name => 'Brandon', :username => 'brandon')
260
+ u.update_attributes :name => 'Foobar'
261
+ u.update_attributes :name => 'Awesome', :username => 'keepers'
262
+
263
+ u.revision(3).name.should == 'Awesome'
264
+ u.revision(3).username.should == 'keepers'
265
+
266
+ u.revision(2).name.should == 'Foobar'
267
+ u.revision(2).username.should == 'brandon'
268
+
269
+ u.revision(1).name.should == 'Brandon'
270
+ u.revision(1).username.should == 'brandon'
271
+ end
272
+
273
+ should "not raise an error when no previous audits exist" do
274
+ @user.audits.destroy_all
275
+ lambda{ @user.revision(:previous) }.should_not raise_error
276
+ end
277
+
278
+ should "mark revision's attributes as changed" do
279
+ @user.revision(1).name_changed?.should be(true)
280
+ end
281
+
282
+ should "record new audit when saving revision" do
283
+ lambda { @user.revision(1).save! }.should change { @user.audits.count }.by(1)
284
+ end
285
+
286
+ end
287
+
288
+ context "revision_at" do
289
+ should "find the latest revision before the given time" do
290
+ u = create_user
291
+ Audit.update(u.audits.first.id, :created_at => 1.hour.ago)
292
+ u.update_attributes :name => 'updated'
293
+ u.revision_at(2.minutes.ago).version.should == 1
294
+ end
295
+
296
+ should "be nil if given a time before audits" do
297
+ create_user.revision_at(1.week.ago).should be(nil)
298
+ end
299
+
300
+ end
301
+
302
+ context "without auditing" do
303
+
304
+ should "not save an audit when calling #save_without_auditing" do
305
+ lambda {
306
+ u = User.new(:name => 'Brandon')
307
+ u.save_without_auditing.should be(true)
308
+ }.should_not change { Audit.count }
309
+ end
310
+
311
+ should "not save an audit inside of the #without_auditing block" do
312
+ lambda do
313
+ User.without_auditing { User.create(:name => 'Brandon') }
314
+ end.should_not change { Audit.count }
315
+ end
316
+ end
317
+
318
+ context "attr_protected and attr_accessible" do
319
+ class UnprotectedUser < ActiveRecord::Base
320
+ set_table_name :users
321
+ acts_as_audited :protect => false
322
+ attr_accessible :name, :username, :password
323
+ end
324
+ should "not raise error when attr_accessible is set and protected is false" do
325
+ lambda{
326
+ UnprotectedUser.new(:name => 'NO FAIL!')
327
+ }.should_not raise_error(RuntimeError)
328
+ end
329
+
330
+ class AccessibleUser < ActiveRecord::Base
331
+ set_table_name :users
332
+ attr_accessible :name, :username, :password # declare attr_accessible before calling aaa
333
+ acts_as_audited
334
+ end
335
+ should "not raise an error when attr_accessible is declared before acts_as_audited" do
336
+ lambda{
337
+ AccessibleUser.new(:name => 'NO FAIL!')
338
+ }.should_not raise_error
339
+ end
340
+ end
341
+
342
+ context "audit as" do
343
+ setup do
344
+ @user = User.create :name => 'Testing'
345
+ end
346
+
347
+ should "record user objects" do
348
+ Company.audit_as( @user ) do
349
+ company = Company.create :name => 'The auditors'
350
+ company.name = 'The Auditors'
351
+ company.save
352
+
353
+ company.audits.each do |audit|
354
+ audit.user.should == @user
355
+ end
356
+ end
357
+ end
358
+
359
+ should "record usernames" do
360
+ Company.audit_as( @user.name ) do
361
+ company = Company.create :name => 'The auditors'
362
+ company.name = 'The Auditors, Inc'
363
+ company.save
364
+
365
+ company.audits.each do |audit|
366
+ audit.username.should == @user.name
367
+ end
368
+ end
369
+ end
370
+ end
371
+
372
+ end
373
+ end
374
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ class AuditsController < ActionController::Base
4
+ def audit
5
+ @company = Company.create
6
+ render :nothing => true
7
+ end
8
+
9
+ def update_user
10
+ current_user.update_attributes({:password => 'foo'})
11
+ render :nothing => true
12
+ end
13
+
14
+ private
15
+ attr_accessor :current_user
16
+ end
17
+ AuditsController.view_paths = [File.dirname(__FILE__)]
18
+ ActionController::Routing::Routes.draw {|m| m.connect ':controller/:action/:id' }
19
+
20
+ class AuditsControllerTest < ActionController::TestCase
21
+ should "audit user" do
22
+ user = @controller.send(:current_user=, create_user)
23
+ lambda { post :audit }.should change { Audit.count }
24
+ assigns(:company).audits.last.user.should == user
25
+ end
26
+
27
+ should "not save blank audits" do
28
+ user = @controller.send(:current_user=, create_user)
29
+ lambda { post :update_user }.should_not change { Audit.count }
30
+ end
31
+ end