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 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