acts_as_audited_customized 1.2.2 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
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.2.2
1
+ 1.3.1
@@ -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
- self.audits.create attrs if auditing_enabled
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><%= human_model %></tt>: the <%= human_model %> that performed the change; a string or an ActiveRecord model
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 :<%= human_model %>, :polymorphic => true
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, :set_audit_<%= human_model %>
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[:acts_as_audited_<%= human_model %>] = user
32
+ Thread.current[:acts_as_audited_user] = user
32
33
  yield
33
- Thread.current[:acts_as_audited_<%= human_model %>] = nil
34
+ Thread.current[:acts_as_audited_user] = nil
34
35
  end
35
36
 
36
- def manual_audit(<%= human_model %>, action, auditable = nil)
37
+ def manual_audit(user, action, on_behalf_of = nil, auditable = nil)
37
38
  attribs = { :action => action }
38
39
 
39
- case <%= human_model %>
40
+ case user
40
41
  when ActiveRecord::Base
41
- attribs[:<%= human_model %>] = <%= human_model %>
42
+ attribs[CollectiveIdea::Acts::Audited.human_model] = user
42
43
  when String
43
- attribs[:username] = <%= human_model %>
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 <%= human_model %> to be set to either a string or an ActiveRecord object
58
- def <%= human_model %>_as_string=(<%= human_model %>) #:nodoc:
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.<%= human_model %>_as_model = self.username = nil
61
- <%= human_model %>.is_a?(ActiveRecord::Base) ?
62
- self.<%= human_model %>_as_model = <%= human_model %> :
63
- self.username = <%= human_model %>
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 :<%= human_model %>_as_model=, :<%= human_model %>=
66
- alias_method :<%= human_model %>=, :<%= human_model %>_as_string=
67
+ # alias_method :user_as_model=, :user=
68
+ # alias_method :user=, :user_as_string=
67
69
 
68
- def <%= human_model %>_as_string #:nodoc:
69
- self.<%= human_model %>_as_model || self.username
70
+ def user_as_string #:nodoc:
71
+ self.user_as_model || self.username
70
72
  end
71
- alias_method :<%= human_model %>_as_model, :<%= human_model %>
72
- alias_method :<%= human_model %>, :<%= human_model %>_as_string
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 set_audit_<%= human_model %>
135
- self.<%= human_model %> = Thread.current[:acts_as_audited_<%= human_model %>] if Thread.current[:acts_as_audited_<%= human_model %>]
136
- nil # prevent stopping callback chains
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
- audit.send("#{CollectiveIdea::Acts::Audited.human_model}=", current_user) unless audit.send(CollectiveIdea::Acts::Audited.human_model)
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
- method = "current_#{CollectiveIdea::Acts::Audited.human_model}"
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
@@ -1,3 +1,4 @@
1
+ require 'acts_as_audited/audit'
1
2
  require 'acts_as_audited'
2
3
 
3
4
  ActiveRecord::Base.send :include, CollectiveIdea::Acts::Audited
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: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 2
9
- - 2
10
- version: 1.2.2
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