audit_model 0.2.0 → 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.
- checksums.yaml +4 -4
- data/README.md +53 -2
- data/lib/audit_model/controllers/helpers.rb +2 -2
- data/lib/audit_model/models/base.rb +19 -15
- data/lib/audit_model/models/helpers.rb +34 -12
- data/lib/audit_model/models/revision.rb +19 -0
- data/lib/audit_model/version.rb +1 -1
- data/lib/generators/audit_model/install/templates/revision.rb +7 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebd0dcefac241688d051a1f655677777a08ddb6d
|
4
|
+
data.tar.gz: bf92e33f15d3dcc5188db421fe1add51e605502d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
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[:
|
13
|
+
Thread.current[:user] = get_user
|
14
14
|
end
|
15
15
|
|
16
16
|
def clear_current_user
|
17
|
-
Thread.current[:
|
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
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
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
|
-
|
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
|
-
|
16
|
-
|
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
|
-
|
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
|
-
|
71
|
+
Revision.audit(self, :create) if self.class.audit_enabled
|
50
72
|
end
|
51
73
|
|
52
74
|
def audit_on_update
|
53
|
-
|
75
|
+
Revision.audit(self, :update) if self.changed? && self.class.audit_enabled
|
54
76
|
end
|
55
77
|
|
56
78
|
def audit_on_destroy
|
57
|
-
|
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
|
data/lib/audit_model/version.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
class CreateRevisions < ActiveRecord::Migration
|
2
2
|
create_table :revisions do |t|
|
3
|
-
t.integer :user_id
|
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 :
|
10
|
+
t.timestamp :revision_date
|
10
11
|
end
|
11
|
-
|
12
|
-
add_index :revisions, [:
|
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.
|
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-
|
11
|
+
date: 2016-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|