acts_as_audited_customized 1.2.2 → 1.3.1
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/README +6 -2
- data/VERSION +1 -1
- data/lib/acts_as_audited.rb +86 -2
- data/{generators/audit_model/templates/model.rb → lib/acts_as_audited/audit.rb} +27 -25
- data/lib/acts_as_audited/audit_sweeper.rb +11 -8
- data/rails/init.rb +1 -0
- metadata +5 -7
- data/generators/audit_model/USAGE +0 -9
- data/generators/audit_model/audit_model_generator.rb +0 -20
data/README
CHANGED
@@ -7,7 +7,7 @@ The purpose of this fork is to store both the previous values and the changed va
|
|
7
7
|
== Installation
|
8
8
|
|
9
9
|
* acts_as_audited can be installed as a gem:
|
10
|
-
|
10
|
+
|
11
11
|
# config/environment.rb
|
12
12
|
config.gem 'acts_as_audited', :lib => false, :source => 'http://gemcutter.org'
|
13
13
|
|
@@ -26,7 +26,7 @@ Declare <tt>acts_as_audited</tt> on your models:
|
|
26
26
|
class User < ActiveRecord::Base
|
27
27
|
acts_as_audited :except => [:password, :mistress]
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
Within a web request, will automatically record the user that made the change if your controller has a <tt>current_user</tt> method.
|
31
31
|
|
32
32
|
To record a user in the audits outside of a web request, you can use <tt>as_user</tt>:
|
@@ -44,6 +44,10 @@ If your model declares +attr_accessible+ after +acts_as_audited+, you need to se
|
|
44
44
|
attr_accessible :name
|
45
45
|
end
|
46
46
|
|
47
|
+
12/21/10:
|
48
|
+
|
49
|
+
There have been no tests written for any of the new features. There's just been no time.
|
50
|
+
|
47
51
|
== Compatability
|
48
52
|
|
49
53
|
acts_as_audited works with Rails 2.1 or later.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.3.1
|
data/lib/acts_as_audited.rb
CHANGED
@@ -37,6 +37,16 @@ module CollectiveIdea #:nodoc:
|
|
37
37
|
mattr_accessor :human_model
|
38
38
|
@@human_model = :user
|
39
39
|
|
40
|
+
# Any additional attributes you wish your model to write to. Default: []
|
41
|
+
mattr_accessor :additional_attributes
|
42
|
+
@@additional_attributes = []
|
43
|
+
|
44
|
+
# Whether or not you want to use the Observer to set current_<%= human_model %>.
|
45
|
+
# Set this to :false if your models have access to the current_<%= human_model %> method.
|
46
|
+
# Default :true
|
47
|
+
mattr_accessor :use_observer
|
48
|
+
@@use_observer = :true
|
49
|
+
|
40
50
|
class << self
|
41
51
|
# Call this method to modify defaults in your initializers.
|
42
52
|
#
|
@@ -46,6 +56,36 @@ module CollectiveIdea #:nodoc:
|
|
46
56
|
# end
|
47
57
|
def configure
|
48
58
|
yield self
|
59
|
+
|
60
|
+
modify_audit_model
|
61
|
+
end
|
62
|
+
|
63
|
+
def modify_audit_model
|
64
|
+
Audit.class_eval do
|
65
|
+
belongs_to @@human_model, :polymorphic => true
|
66
|
+
|
67
|
+
[@@additional_attributes].flatten.each do |attrib|
|
68
|
+
belongs_to attrib, :class_name => @@human_model.to_s.classify, :foreign_key => "#{attrib}_id"
|
69
|
+
end
|
70
|
+
|
71
|
+
alias_method :user_as_model=, "#{@@human_model}=".to_sym
|
72
|
+
alias_method "#{@@human_model}=".to_sym, :user_as_string=
|
73
|
+
|
74
|
+
alias_method :user_as_model, @@human_model
|
75
|
+
alias_method @@human_model, :user_as_string
|
76
|
+
|
77
|
+
def set_audit_user
|
78
|
+
self.send(@@human_model, Thread.current[:acts_as_audited_user]) if Thread.current[:acts_as_audited_user]
|
79
|
+
nil # prevent stopping callback chains
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
if @@use_observer
|
84
|
+
::ActionController::Base.class_eval do
|
85
|
+
cache_sweeper :audit_sweeper
|
86
|
+
end
|
87
|
+
Audit.add_observer(AuditSweeper.instance)
|
88
|
+
end
|
49
89
|
end
|
50
90
|
|
51
91
|
def included(base) # :nodoc:
|
@@ -81,10 +121,14 @@ module CollectiveIdea #:nodoc:
|
|
81
121
|
# don't allow multiple calls
|
82
122
|
return if self.included_modules.include?(CollectiveIdea::Acts::Audited::InstanceMethods)
|
83
123
|
|
124
|
+
reserved_options = [:protect, :on, :create, :update, :destroy, :only, :except, :if, :unless]
|
84
125
|
options = {:protect => accessible_attributes.nil?}.merge(options)
|
85
126
|
|
86
127
|
class_inheritable_reader :non_audited_columns
|
87
128
|
class_inheritable_reader :auditing_enabled
|
129
|
+
class_inheritable_reader :manually_set_columns
|
130
|
+
class_inheritable_reader :if_condition
|
131
|
+
class_inheritable_reader :unless_condition
|
88
132
|
|
89
133
|
if options[:only]
|
90
134
|
except = self.column_names - options[:only].flatten.map(&:to_s)
|
@@ -94,6 +138,9 @@ module CollectiveIdea #:nodoc:
|
|
94
138
|
except |= Array(options[:except]).collect(&:to_s) if options[:except]
|
95
139
|
end
|
96
140
|
write_inheritable_attribute :non_audited_columns, except
|
141
|
+
write_inheritable_attribute :manually_set_columns, options.reject {|k, v| reserved_options.include?(k) }
|
142
|
+
write_inheritable_attribute :if_condition, options.delete(:if)
|
143
|
+
write_inheritable_attribute :unless_condition, options.delete(:unless)
|
97
144
|
|
98
145
|
has_many :audits, :as => :auditable, :order => "#{Audit.quoted_table_name}.version"
|
99
146
|
attr_protected :audit_ids if options[:protect]
|
@@ -187,6 +234,43 @@ module CollectiveIdea #:nodoc:
|
|
187
234
|
end
|
188
235
|
end
|
189
236
|
|
237
|
+
def evaluate(value)
|
238
|
+
case value
|
239
|
+
when Proc
|
240
|
+
value.arity > 0 ? value.call(self) : value.call
|
241
|
+
else
|
242
|
+
value
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def on_behalf_of_result
|
247
|
+
evaluate(on_behalf_of_call)
|
248
|
+
end
|
249
|
+
|
250
|
+
def set_manually_set_columns
|
251
|
+
manually_set_columns.inject(set_current_user) do |attrs, (attrib, value)|
|
252
|
+
attrs[attrib] = evaluate(value)
|
253
|
+
attrs
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def set_current_user
|
258
|
+
method = "current_#{CollectiveIdea::Acts::Audited.human_model}"
|
259
|
+
!CollectiveIdea::Acts::Audited.use_observer && self.class.respond_to?(method) ? { CollectiveIdea::Acts::Audited.human_model => self.class.send(method) } : {}
|
260
|
+
end
|
261
|
+
|
262
|
+
def eval_condition(condition)
|
263
|
+
evaluate(condition)
|
264
|
+
end
|
265
|
+
|
266
|
+
def eval_if_condition
|
267
|
+
!if_condition || eval_condition(if_condition)
|
268
|
+
end
|
269
|
+
|
270
|
+
def eval_unless_condition
|
271
|
+
!unless_condition || !eval_condition(unless_condition)
|
272
|
+
end
|
273
|
+
|
190
274
|
def audits_to(version = nil)
|
191
275
|
if version == :previous
|
192
276
|
version = if self.version
|
@@ -215,7 +299,8 @@ module CollectiveIdea #:nodoc:
|
|
215
299
|
end
|
216
300
|
|
217
301
|
def write_audit(attrs)
|
218
|
-
|
302
|
+
attrs = attrs.merge(set_manually_set_columns)
|
303
|
+
self.audits.create attrs if auditing_enabled && eval_if_condition && eval_unless_condition
|
219
304
|
end
|
220
305
|
end # InstanceMethods
|
221
306
|
|
@@ -251,7 +336,6 @@ module CollectiveIdea #:nodoc:
|
|
251
336
|
def audit_as( user, &block )
|
252
337
|
Audit.as_user( user, &block )
|
253
338
|
end
|
254
|
-
|
255
339
|
end
|
256
340
|
end
|
257
341
|
end
|
@@ -3,16 +3,17 @@ require 'set'
|
|
3
3
|
# Audit saves the changes to ActiveRecord models. It has the following attributes:
|
4
4
|
#
|
5
5
|
# * <tt>auditable</tt>: the ActiveRecord model that was changed
|
6
|
-
# * <tt
|
6
|
+
# * <tt>user</tt>: the user that performed the change; a string or an ActiveRecord model
|
7
7
|
# * <tt>action</tt>: one of create, update, or delete
|
8
8
|
# * <tt>changes</tt>: a serialized hash of all the changes
|
9
9
|
# * <tt>created_at</tt>: Time that the change was performed
|
10
10
|
#
|
11
11
|
class Audit < ActiveRecord::Base
|
12
12
|
belongs_to :auditable, :polymorphic => true
|
13
|
-
belongs_to
|
13
|
+
# belongs_to :user, :polymorphic => true
|
14
|
+
# belongs_to :on_behalf_of, :class_name => 'User', :foreign_key => 'on_behalf_of_id'
|
14
15
|
|
15
|
-
before_create :set_version_number, :
|
16
|
+
before_create :set_version_number, :set_audit_user
|
16
17
|
|
17
18
|
serialize :changes
|
18
19
|
|
@@ -28,19 +29,19 @@ class Audit < ActiveRecord::Base
|
|
28
29
|
# by +user+. This method is hopefully threadsafe, making it ideal
|
29
30
|
# for background operations that require audit information.
|
30
31
|
def as_user(user, &block)
|
31
|
-
Thread.current[:
|
32
|
+
Thread.current[:acts_as_audited_user] = user
|
32
33
|
yield
|
33
|
-
Thread.current[:
|
34
|
+
Thread.current[:acts_as_audited_user] = nil
|
34
35
|
end
|
35
36
|
|
36
|
-
def manual_audit(
|
37
|
+
def manual_audit(user, action, on_behalf_of = nil, auditable = nil)
|
37
38
|
attribs = { :action => action }
|
38
39
|
|
39
|
-
case
|
40
|
+
case user
|
40
41
|
when ActiveRecord::Base
|
41
|
-
attribs[
|
42
|
+
attribs[CollectiveIdea::Acts::Audited.human_model] = user
|
42
43
|
when String
|
43
|
-
attribs[:username] =
|
44
|
+
attribs[:username] = user
|
44
45
|
end
|
45
46
|
|
46
47
|
case auditable
|
@@ -50,26 +51,27 @@ class Audit < ActiveRecord::Base
|
|
50
51
|
attribs[:auditable_type] = auditable
|
51
52
|
end
|
52
53
|
|
54
|
+
attribs[:on_behalf_of] = on_behalf_of if on_behalf_of
|
53
55
|
Audit.create attribs
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
57
|
-
# Allows
|
58
|
-
def
|
59
|
+
# Allows user to be set to either a string or an ActiveRecord object
|
60
|
+
def user_as_string=(user) #:nodoc:
|
59
61
|
# reset both either way
|
60
|
-
self
|
61
|
-
|
62
|
-
self
|
63
|
-
self.username =
|
62
|
+
self.user_as_model = self.username = nil
|
63
|
+
user.is_a?(ActiveRecord::Base) ?
|
64
|
+
self.user_as_model = user :
|
65
|
+
self.username = user
|
64
66
|
end
|
65
|
-
alias_method
|
66
|
-
alias_method
|
67
|
+
# alias_method :user_as_model=, :user=
|
68
|
+
# alias_method :user=, :user_as_string=
|
67
69
|
|
68
|
-
def
|
69
|
-
self
|
70
|
+
def user_as_string #:nodoc:
|
71
|
+
self.user_as_model || self.username
|
70
72
|
end
|
71
|
-
alias_method
|
72
|
-
alias_method
|
73
|
+
# alias_method :user_as_model, :user
|
74
|
+
# alias_method :user, :user_as_string
|
73
75
|
|
74
76
|
def revision
|
75
77
|
clazz = auditable_type.constantize
|
@@ -131,9 +133,9 @@ private
|
|
131
133
|
self.version = max + 1
|
132
134
|
end
|
133
135
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
137
|
-
end
|
136
|
+
# def set_audit_user
|
137
|
+
# self.user = Thread.current[:acts_as_audited_user] if Thread.current[:acts_as_audited_user]
|
138
|
+
# nil # prevent stopping callback chains
|
139
|
+
# end
|
138
140
|
|
139
141
|
end
|
@@ -19,19 +19,22 @@ module CollectiveIdea #:nodoc:
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
ActionController::Base.class_eval do
|
23
|
+
extend CollectiveIdea::ActionController::Audited
|
24
|
+
end
|
25
|
+
|
22
26
|
class AuditSweeper < ActionController::Caching::Sweeper #:nodoc:
|
27
|
+
def current_user_method
|
28
|
+
"current_#{CollectiveIdea::Acts::Audited.human_model}".to_sym
|
29
|
+
end
|
30
|
+
|
23
31
|
def before_create(audit)
|
24
|
-
|
32
|
+
raise "Got here"
|
33
|
+
audit.send("#{CollectiveIdea::Acts::Audited.human_model}=".to_sym, current_user) unless audit.send(CollectiveIdea::Acts::Audited.human_model)
|
25
34
|
end
|
26
35
|
|
27
36
|
def current_user
|
28
|
-
|
29
|
-
controller.send(method) if controller.respond_to?(method, true)
|
37
|
+
controller.send current_user_method if controller.respond_to?(current_user_method, true)
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
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
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_audited_customized
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
8
|
+
- 3
|
9
|
+
- 1
|
10
|
+
version: 1.3.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brandon Keepers
|
@@ -77,14 +77,12 @@ files:
|
|
77
77
|
- README
|
78
78
|
- Rakefile
|
79
79
|
- VERSION
|
80
|
-
- generators/audit_model/USAGE
|
81
|
-
- generators/audit_model/audit_model_generator.rb
|
82
|
-
- generators/audit_model/templates/model.rb
|
83
80
|
- generators/audited_migration/USAGE
|
84
81
|
- generators/audited_migration/audited_migration_generator.rb
|
85
82
|
- generators/audited_migration/templates/migration.rb
|
86
83
|
- init.rb
|
87
84
|
- lib/acts_as_audited.rb
|
85
|
+
- lib/acts_as_audited/audit.rb
|
88
86
|
- lib/acts_as_audited/audit_sweeper.rb
|
89
87
|
- rails/init.rb
|
90
88
|
- test/acts_as_audited_test.rb
|
@@ -1,9 +0,0 @@
|
|
1
|
-
Description:
|
2
|
-
The audit model generator creates the Audit model in app/models/ associating it with the correct "human" class ("user" by default).
|
3
|
-
|
4
|
-
Example:
|
5
|
-
./script/generate audit_model Person
|
6
|
-
|
7
|
-
This will create the Audit model in app/models/ associating it to the Person model.
|
8
|
-
|
9
|
-
You must generate the migration using the same "human" class.
|
@@ -1,20 +0,0 @@
|
|
1
|
-
class AuditModelGenerator < Rails::Generator::NamedBase
|
2
|
-
def initialize(runtime_args, runtime_options = {})
|
3
|
-
runtime_args << 'user' if runtime_args.empty?
|
4
|
-
super
|
5
|
-
@human_model = runtime_args[0] ? runtime_args[0].underscore : 'user'
|
6
|
-
end
|
7
|
-
|
8
|
-
def manifest
|
9
|
-
record do |m|
|
10
|
-
m.directory(File.join('app', 'models'))
|
11
|
-
m.template('model.rb', "app/models/audit.rb", :assigns => { :human_model => @human_model })
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
protected
|
16
|
-
|
17
|
-
def banner
|
18
|
-
"Usage: #{$0} audit_model [human_model_name]"
|
19
|
-
end
|
20
|
-
end
|