audit_model 0.2.0 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ecfdf66cff271315a58dde4a53b3699c26cd513
4
- data.tar.gz: e8f1672bce78f28ccabe6bd41a0f0451cdd285b1
3
+ metadata.gz: ebd0dcefac241688d051a1f655677777a08ddb6d
4
+ data.tar.gz: bf92e33f15d3dcc5188db421fe1add51e605502d
5
5
  SHA512:
6
- metadata.gz: 9dd4a6f127ad3dd0b21ad950b0f2b075ecac5b349ff1d763a30aca684ac0230043530ee37ba60e67997980db403575bd6a2ae96dd4e64858fd374d91aff2254a
7
- data.tar.gz: 151fe8095d9822825490bc931654c0d317f7f362c4b8ef6dffe7d2c2495ec798b00779dce21bd6e1708b19bc9e3f5c5d196fb92e083dc46d20897e6b6865df44
6
+ metadata.gz: 851c47ab75009da4e4135ebdc799c59ab9815619d9d0d4e96f58043e0cd22d02c4052bde5a2e02f00c0687b11af07f98609b00468a065cc3dc81fdf74abd31fb
7
+ data.tar.gz: ff994a7e238bb17dfff34d8f58b09f56b24f0226df8f0158535040992380be0c578aa8845bfc9fb9fc902e16d8104e9b737be5f8af73daceafaed9b9012a2676
data/README.md CHANGED
@@ -32,23 +32,74 @@ class User < ActiveRecord::Base
32
32
  end
33
33
  ```
34
34
 
35
+ ## Configuration
36
+ When you run the following command you create a configuration file **config/initializers/audit_model.rb**
37
+ ```
38
+ rails g audit_model:install
39
+ ```
40
+ You can configure which method the application uses to retrieve the current user by default the method is [#current_user](#).
41
+ ```
42
+ #!ruby
43
+ AuditModel.setup do |config|
44
+ config.user_method = "current_user"
45
+ end
46
+ ```
47
+
35
48
  ## Usage
36
49
  In the model you have [#audits](#) method that returns the audits.
37
50
  ```
38
51
  #!ruby
39
- User.audits
52
+ user = User.create(email: "user@example.com", name: "user example")
53
+ user.audits
40
54
  ```
41
55
  Audits are ActiveRecord models, knowing that you can make any query based on ActiveRecord.
42
56
  You can do something like this:
43
57
  ```
44
58
  #!ruby
45
- User.audits.last
59
+ user.audits.last
46
60
  ```
47
61
  This will return the last change in the model.
62
+ You can also use [#revisions](#)
63
+ ```
64
+ #!ruby
65
+ user = User.find 3
66
+ revision = user.revisions.last
67
+ ```
68
+ So it's possible to obtain information
69
+ ```
70
+ #!ruby
71
+ revision.user # User who made the changes
72
+ revision.revision_date
73
+ revision.model # Model that was audited.
74
+ revision.audit # Model with the audit information
75
+ ```
76
+ ## Disabling auditing
77
+
78
+ If you want to disable auditing, you can use [#without_audit](#) in your model class.
79
+
80
+ ```
81
+ #!ruby
82
+ User.without_audit do
83
+ User.create(name: "User example", email: "user.example@domain.com")
84
+ end
85
+
86
+ User.without_audit do
87
+ user = User.find 3
88
+ user.update(email: "user-example@domain.com")
89
+ end
90
+ ```
91
+
48
92
  ## License
49
93
 
50
94
  AuditModel is released under the [MIT License](http://www.opensource.org/licenses/MIT).
51
95
 
96
+
97
+ ## Inspirations
98
+
99
+ * [Audited](https://github.com/collectiveidea/audited)
100
+ * [PaperTrail](https://github.com/airblade/paper_trail)
101
+
102
+
52
103
  ## Contributing
53
104
 
54
105
  Bug reports and pull requests are welcome on BitBucket at https://bitbucket.org/alissonbruno/audit_model
@@ -10,11 +10,11 @@ module AuditModel
10
10
 
11
11
  module InstanceMethods
12
12
  def set_current_user
13
- Thread.current[:user_id] = get_user.try(:id)
13
+ Thread.current[:user] = get_user
14
14
  end
15
15
 
16
16
  def clear_current_user
17
- Thread.current[:user_id] = nil
17
+ Thread.current[:user] = nil
18
18
  end
19
19
 
20
20
  private
@@ -2,7 +2,8 @@ module AuditModel
2
2
  module Models
3
3
  class Base < ActiveRecord::Base
4
4
  self.abstract_class = true
5
-
5
+ has_one :revision, foreign_key: "audit_id"
6
+
6
7
  BLACK_LIST = [
7
8
  "id",
8
9
  "created_at",
@@ -14,26 +15,29 @@ module AuditModel
14
15
  end
15
16
 
16
17
  class << self
17
- def audit(model, type)
18
- revision = Revision.new({
19
- model: model,
20
- user_id: Thread.current[:user_id],
21
- revison_date: Time.now
22
- })
23
- revision.audit = new sanitizer_args(model, type)
24
- revision.save!
18
+ def build(model, type)
19
+ return if type == :update && !any_change?(model)
20
+ attrs = sanitize(model, type)
21
+ attrs[:rev_type] = type
22
+ new(attrs)
25
23
  end
26
24
 
27
25
  private
28
26
 
29
- def sanitizer_args(model, type)
30
- args = model.attributes.merge(model.changed_attributes)
31
- args.except!(*BLACK_LIST).select! {|k,v| copy?(k) }
32
- args[:rev_type] = type
33
- args
27
+ def sanitize(model, type)
28
+ if type == :update
29
+ attrs = model.attributes.merge(model.changed_attributes)
30
+ elsif
31
+ attrs = model.attributes
32
+ end
33
+ attrs.except(*BLACK_LIST).select { |key,value| has_audit?(key) }
34
+ end
35
+
36
+ def any_change?(model)
37
+ model.changed? && model.changed_attributes.any? { |key,value| has_audit?(key) }
34
38
  end
35
39
 
36
- def copy?(attribute)
40
+ def has_audit?(attribute)
37
41
  attribute_names.include?(attribute)
38
42
  end
39
43
  end
@@ -3,17 +3,32 @@ module AuditModel
3
3
  module Helpers
4
4
  extend ActiveSupport::Concern
5
5
 
6
- included do
7
- send :include, InstanceMethods
8
- end
9
-
10
6
  module ClassMethods
11
7
  def auditable(options = {})
12
- options[:on] ||= [:update, :destroy]
8
+ send :include, InstanceMethods
9
+ class_attribute :audit_enabled, instance_writer: false
10
+ options[:on] ||= [:create, :update, :destroy]
13
11
  setup_callbacks options[:on]
14
12
  setup_model
15
- has_many :revisions, as: :model, class_name: "AuditModel::Models::Revision"
16
- has_many :audits, through: :revisions, source: :audit, source_type: audit_class
13
+ setup_associations
14
+
15
+ send :enable_audit
16
+ end
17
+
18
+ def without_audit
19
+ cache = audit_enabled
20
+ disable_audit
21
+ yield
22
+ ensure
23
+ enable_audit if cache
24
+ end
25
+
26
+ def disable_audit
27
+ self.audit_enabled = false
28
+ end
29
+
30
+ def enable_audit
31
+ self.audit_enabled = true
17
32
  end
18
33
 
19
34
  private
@@ -27,6 +42,11 @@ module AuditModel
27
42
  Object.const_set audit_class, Class.new(Models::Base)
28
43
  end
29
44
 
45
+ def setup_associations
46
+ has_many :revisions, as: :model, class_name: "AuditModel::Models::Revision"
47
+ has_many :audits, through: :revisions, source: :audit, source_type: audit_class
48
+ end
49
+
30
50
  def callback_on_create
31
51
  after_create :audit_on_create
32
52
  end
@@ -36,7 +56,7 @@ module AuditModel
36
56
  end
37
57
 
38
58
  def callback_on_destroy
39
- before_destroy :audit_on_destroy
59
+ after_destroy :audit_on_destroy
40
60
  end
41
61
 
42
62
  def audit_class
@@ -45,18 +65,20 @@ module AuditModel
45
65
  end
46
66
 
47
67
  module InstanceMethods
68
+ private
69
+
48
70
  def audit_on_create
49
- "#{self.class}Audit".constantize.audit(self, :create)
71
+ Revision.audit(self, :create) if self.class.audit_enabled
50
72
  end
51
73
 
52
74
  def audit_on_update
53
- "#{self.class}Audit".constantize.audit(self, :update)
75
+ Revision.audit(self, :update) if self.changed? && self.class.audit_enabled
54
76
  end
55
77
 
56
78
  def audit_on_destroy
57
- "#{self.class}Audit".constantize.audit(self, :destroy)
79
+ Revision.audit(self, :destroy) unless self.new_record? || !self.class.audit_enabled
58
80
  end
59
-
81
+
60
82
  end
61
83
  end
62
84
  end
@@ -3,6 +3,25 @@ module AuditModel
3
3
  class Revision < ActiveRecord::Base
4
4
  belongs_to :model, polymorphic: true
5
5
  belongs_to :audit, polymorphic: true
6
+ belongs_to :user, polymorphic: true
7
+
8
+ class << self
9
+ def audit(model, type)
10
+ data = {
11
+ model: model,
12
+ user: Thread.current[:user],
13
+ revision_date: Time.now,
14
+ audit: audit_class_for(model).build(model, type)
15
+ }
16
+ create(data)
17
+ end
18
+
19
+ private
20
+
21
+ def audit_class_for(model)
22
+ "#{model.class}Audit".constantize
23
+ end
24
+ end
6
25
  end
7
26
  end
8
27
  end
@@ -1,3 +1,3 @@
1
1
  module AuditModel
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3"
3
3
  end
@@ -1,13 +1,16 @@
1
1
  class CreateRevisions < ActiveRecord::Migration
2
2
  create_table :revisions do |t|
3
- t.integer :user_id, index: true
3
+ t.integer :user_id
4
+ t.string :user_type
4
5
  t.integer :model_id
5
6
  t.string :model_type
6
7
  t.integer :audit_id
7
8
  t.string :audit_type
8
9
 
9
- t.timestamp :revison_date
10
+ t.timestamp :revision_date
10
11
  end
11
- add_index :revisions, [:model_id, :model_type], :name => 'model_index'
12
- add_index :revisions, [:audit_id, :audit_type], :name => 'audit_index'
12
+
13
+ add_index :revisions, [:user_id, :user_type], name: 'revision_user_index'
14
+ add_index :revisions, [:model_id, :model_type], name: 'revision_model_index'
15
+ add_index :revisions, [:audit_id, :audit_type], name: 'revision_audit_index'
13
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: audit_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: '0.3'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alisson Bruno
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-01 00:00:00.000000000 Z
11
+ date: 2016-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler