audited 4.3.0 → 4.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of audited might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +10 -0
- data/Appraisals +3 -2
- data/CHANGELOG.md +190 -0
- data/README.md +27 -9
- data/gemfiles/rails50.gemfile +0 -1
- data/gemfiles/rails51.gemfile +7 -0
- data/lib/audited.rb +6 -5
- data/lib/audited/audit.rb +38 -8
- data/lib/audited/auditor.rb +11 -7
- data/lib/audited/rspec_matchers.rb +1 -1
- data/lib/audited/sweeper.rb +18 -29
- data/lib/audited/version.rb +1 -1
- data/lib/generators/audited/install_generator.rb +4 -0
- data/lib/generators/audited/migration_helper.rb +9 -0
- data/lib/generators/audited/templates/add_association_to_audits.rb +1 -1
- data/lib/generators/audited/templates/add_comment_to_audits.rb +1 -1
- data/lib/generators/audited/templates/add_remote_address_to_audits.rb +1 -1
- data/lib/generators/audited/templates/add_request_uuid_to_audits.rb +1 -1
- data/lib/generators/audited/templates/install.rb +2 -2
- data/lib/generators/audited/templates/rename_association_to_associated.rb +1 -1
- data/lib/generators/audited/templates/rename_changes_to_audited_changes.rb +1 -1
- data/lib/generators/audited/templates/rename_parent_to_association.rb +1 -1
- data/lib/generators/audited/upgrade_generator.rb +2 -0
- data/spec/audited/audit_spec.rb +49 -2
- data/spec/audited/auditor_spec.rb +43 -2
- data/spec/audited/sweeper_spec.rb +8 -6
- data/spec/support/active_record/models.rb +1 -0
- data/spec/support/active_record/postgres/1_change_audited_changes_type_to_json.rb +12 -0
- data/spec/support/active_record/postgres/2_change_audited_changes_type_to_jsonb.rb +12 -0
- data/test/install_generator_test.rb +31 -3
- data/test/upgrade_generator_test.rb +16 -1
- metadata +7 -17
- data/CHANGELOG +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b999065ad92a0fbe08d0739e44dfe966d35ee57f
|
4
|
+
data.tar.gz: 258e418fcfaf0b839c209435dda7ab509c25b52b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acb5cb634042722106e7b120791723d879677992628572c830c03d2594e472857127d09714ed6d61cd3aaec635b82e4396441d94a900556e01bc795ad1ed05a1
|
7
|
+
data.tar.gz: 41fff32c9c1b060f040007a038d2840c6e7c43f528dbc9924d3ac1727fee692c10e959bc43bbe2c25882c2cfad9f69b54d8bb21836a3786a1c11928ed10a5770
|
data/.travis.yml
CHANGED
@@ -4,22 +4,32 @@ rvm:
|
|
4
4
|
- 2.1
|
5
5
|
- 2.2.4
|
6
6
|
- 2.3.1
|
7
|
+
- 2.4.1
|
7
8
|
- ruby-head
|
8
9
|
env:
|
9
10
|
- DB=SQLITE
|
10
11
|
- DB=POSTGRES
|
11
12
|
- DB=MYSQL
|
13
|
+
addons:
|
14
|
+
postgresql: "9.4"
|
12
15
|
gemfile:
|
13
16
|
- gemfiles/rails40.gemfile
|
14
17
|
- gemfiles/rails41.gemfile
|
15
18
|
- gemfiles/rails42.gemfile
|
16
19
|
- gemfiles/rails50.gemfile
|
20
|
+
- gemfiles/rails51.gemfile
|
17
21
|
matrix:
|
18
22
|
allow_failures:
|
19
23
|
- rvm: ruby-head
|
20
24
|
exclude:
|
21
25
|
- rvm: 2.1
|
22
26
|
gemfile: gemfiles/rails50.gemfile
|
27
|
+
- rvm: 2.1
|
28
|
+
gemfile: gemfiles/rails51.gemfile
|
29
|
+
- rvm: 2.4.1
|
30
|
+
gemfile: gemfiles/rails40.gemfile
|
31
|
+
- rvm: 2.4.1
|
32
|
+
gemfile: gemfiles/rails41.gemfile
|
23
33
|
fast_finish: true
|
24
34
|
branches:
|
25
35
|
only:
|
data/Appraisals
CHANGED
@@ -16,7 +16,8 @@ end
|
|
16
16
|
|
17
17
|
appraise 'rails50' do
|
18
18
|
gem 'rails', '~> 5.0.0'
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
gem 'rails
|
21
|
+
appraise 'rails51' do
|
22
|
+
gem 'rails', '>= 5.1.0.rc1', '< 5.2'
|
22
23
|
end
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
# Audited ChangeLog
|
2
|
+
|
3
|
+
## Unreleased
|
4
|
+
|
5
|
+
Breaking changes
|
6
|
+
|
7
|
+
- None
|
8
|
+
|
9
|
+
Added
|
10
|
+
|
11
|
+
- None
|
12
|
+
|
13
|
+
Changed
|
14
|
+
|
15
|
+
- None
|
16
|
+
|
17
|
+
Fixed
|
18
|
+
|
19
|
+
- None
|
20
|
+
|
21
|
+
## 4.4.0 (2017-03-29)
|
22
|
+
|
23
|
+
Breaking changes
|
24
|
+
|
25
|
+
- None
|
26
|
+
|
27
|
+
Added
|
28
|
+
|
29
|
+
- Support for `audited_changes` to be a `json` or `jsonb` column in PostgreSQL
|
30
|
+
[#216](https://github.com/collectiveidea/audited/issues/216)
|
31
|
+
- Allow `Audited::Audit` to be subclassed by configuring `Audited.audit_class`
|
32
|
+
[#314](https://github.com/collectiveidea/audited/issues/314)
|
33
|
+
- Support for Ruby on Rails 5.1
|
34
|
+
[#329](https://github.com/collectiveidea/audited/issues/329)
|
35
|
+
- Support for Ruby 2.4
|
36
|
+
[#329](https://github.com/collectiveidea/audited/issues/329)
|
37
|
+
|
38
|
+
Changed
|
39
|
+
|
40
|
+
- Remove rails-observer dependency
|
41
|
+
[#325](https://github.com/collectiveidea/audited/issues/325)
|
42
|
+
- Undeprecated `Audited.audit_class` reader
|
43
|
+
[#314](https://github.com/collectiveidea/audited/issues/314)
|
44
|
+
|
45
|
+
Fixed
|
46
|
+
|
47
|
+
- SQL error in Rails Conditional GET (304 caching)
|
48
|
+
[#295](https://github.com/collectiveidea/audited/pull/295)
|
49
|
+
- Fix missing non_audited_columns= configuration setter
|
50
|
+
[#320](https://github.com/collectiveidea/audited/issues/320)
|
51
|
+
- Fix migration generators to specify AR migration version
|
52
|
+
[#329](https://github.com/collectiveidea/audited/issues/329)
|
53
|
+
|
54
|
+
## 4.3.0 (2016-09-17)
|
55
|
+
|
56
|
+
Breaking changes
|
57
|
+
|
58
|
+
- None
|
59
|
+
|
60
|
+
Added
|
61
|
+
|
62
|
+
- Support singular arguments for options: `on` and `only`
|
63
|
+
|
64
|
+
Fixed
|
65
|
+
|
66
|
+
- Fix auditing instance attributes if "only" option specified
|
67
|
+
- Allow private / protected callback declarations
|
68
|
+
- Do not eagerly connect to database
|
69
|
+
|
70
|
+
## 4.2.2 (2016-08-01)
|
71
|
+
|
72
|
+
- Correct auditing_enabled for STI models
|
73
|
+
- Properly set table name for mongomapper
|
74
|
+
|
75
|
+
## 4.2.1 (2016-07-29)
|
76
|
+
|
77
|
+
- Fix bug when only: is a single field.
|
78
|
+
- update gemspec to use mongomapper 0.13
|
79
|
+
- sweeper need not run observer for mongomapper
|
80
|
+
- Make temporary disabling of auditing threadsafe
|
81
|
+
- Centralize `Audited.store` as thread safe variable store
|
82
|
+
|
83
|
+
## 4.2.0 (2015-03-31)
|
84
|
+
|
85
|
+
Not yet documented.
|
86
|
+
|
87
|
+
## 4.0.0 (2014-09-04)
|
88
|
+
|
89
|
+
Not yet documented.
|
90
|
+
|
91
|
+
## 4.0.0.rc1 (2014-07-30)
|
92
|
+
|
93
|
+
Not yet documented.
|
94
|
+
|
95
|
+
## 3.0.0 (2012-09-25)
|
96
|
+
|
97
|
+
Not yet documented.
|
98
|
+
|
99
|
+
## 3.0.0.rc2 (2012-07-09)
|
100
|
+
|
101
|
+
Not yet documented.
|
102
|
+
|
103
|
+
## 3.0.0.rc1 (2012-04-25)
|
104
|
+
|
105
|
+
Not yet documented.
|
106
|
+
|
107
|
+
## 2012-04-10
|
108
|
+
|
109
|
+
- Add Audit scopes for creates, updates and destroys [chriswfx]
|
110
|
+
|
111
|
+
## 2011-10-25
|
112
|
+
|
113
|
+
- Made ignored_attributes configurable [senny]
|
114
|
+
|
115
|
+
## 2011-09-09
|
116
|
+
|
117
|
+
- Rails 3.x support
|
118
|
+
- Support for associated audits
|
119
|
+
- Support for remote IP address storage
|
120
|
+
- Plenty of bug fixes and refactoring
|
121
|
+
- [kennethkalmer, ineu, PatrickMa, jrozner, dwarburton, bsiggelkow, dgm]
|
122
|
+
|
123
|
+
## 2009-01-27
|
124
|
+
|
125
|
+
- Store old and new values for updates, and store all attributes on destroy.
|
126
|
+
- Refactored revisioning methods to work as expected
|
127
|
+
|
128
|
+
## 2008-10-10
|
129
|
+
|
130
|
+
- changed to make it work in development mode
|
131
|
+
|
132
|
+
## 2008-09-24
|
133
|
+
|
134
|
+
- Add ability to record parent record of the record being audited [Kenneth Kalmer]
|
135
|
+
|
136
|
+
## 2008-04-19
|
137
|
+
|
138
|
+
- refactored to make compatible with dirty tracking in edge rails
|
139
|
+
and to stop storing both old and new values in a single audit
|
140
|
+
|
141
|
+
## 2008-04-18
|
142
|
+
|
143
|
+
- Fix NoMethodError when trying to access the :previous revision
|
144
|
+
on a model that doesn't have previous revisions [Alex Soto]
|
145
|
+
|
146
|
+
## 2008-03-21
|
147
|
+
|
148
|
+
- added #changed_attributes to get access to the changes before a
|
149
|
+
save [Chris Parker]
|
150
|
+
|
151
|
+
## 2007-12-16
|
152
|
+
|
153
|
+
- Added #revision_at for retrieving a revision from a specific
|
154
|
+
time [Jacob Atzen]
|
155
|
+
|
156
|
+
## 2007-12-16
|
157
|
+
|
158
|
+
- Fix error when getting revision from audit with no changes
|
159
|
+
[Geoffrey Wiseman]
|
160
|
+
|
161
|
+
## 2007-12-16
|
162
|
+
|
163
|
+
- Remove dependency on acts_as_list
|
164
|
+
|
165
|
+
## 2007-06-17
|
166
|
+
|
167
|
+
- Added support getting previous revisions
|
168
|
+
|
169
|
+
## 2006-11-17
|
170
|
+
|
171
|
+
- Replaced use of singleton User.current_user with cache sweeper
|
172
|
+
implementation for auditing the user that made the change
|
173
|
+
|
174
|
+
## 2006-11-17
|
175
|
+
|
176
|
+
- added migration generator
|
177
|
+
|
178
|
+
## 2006-08-14
|
179
|
+
|
180
|
+
- incorporated changes from Michael Schuerig to write_attribute
|
181
|
+
that saves the new value after every change and not just the
|
182
|
+
first, and performs proper type-casting before doing comparisons
|
183
|
+
|
184
|
+
## 2006-08-14
|
185
|
+
|
186
|
+
- The "changes" are now saved as a serialized hash
|
187
|
+
|
188
|
+
## 2006-07-21
|
189
|
+
|
190
|
+
- initial version
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@ Audited [![Build Status](https://secure.travis-ci.org/collectiveidea/audited.svg
|
|
3
3
|
|
4
4
|
**Audited** (previously acts_as_audited) is an ORM extension that logs all changes to your models. Audited can also record who made those changes, save comments and associate models related to the changes.
|
5
5
|
|
6
|
-
Audited currently (4.x) works with Rails 5.0 and 4.2. It may work with 4.1 and 4.0, but this is not guaranteed.
|
6
|
+
Audited currently (4.x) works with Rails 5.1, 5.0 and 4.2. It may work with 4.1 and 4.0, but this is not guaranteed.
|
7
7
|
|
8
8
|
For Rails 3, use gem version 3.0 or see the [3.0-stable branch](https://github.com/collectiveidea/audited/tree/3.0-stable).
|
9
9
|
|
@@ -14,6 +14,7 @@ Audited supports and is [tested against](http://travis-ci.org/collectiveidea/aud
|
|
14
14
|
* 2.1.5
|
15
15
|
* 2.2.4
|
16
16
|
* 2.3.1
|
17
|
+
* 2.4.1
|
17
18
|
|
18
19
|
Audited may work just fine with a Ruby version not listed above, but we can't guarantee that it will. If you'd like to maintain a Ruby that isn't listed, please let us know with a [pull request](https://github.com/collectiveidea/audited/pulls).
|
19
20
|
|
@@ -26,12 +27,7 @@ Audited is currently ActiveRecord-only. In a previous life, Audited worked with
|
|
26
27
|
Add the gem to your Gemfile:
|
27
28
|
|
28
29
|
```ruby
|
29
|
-
gem "audited", "~> 4.
|
30
|
-
```
|
31
|
-
|
32
|
-
If you are using rails 5.0, you would also need the following line in your Gemfile.
|
33
|
-
```ruby
|
34
|
-
gem "rails-observers", github: 'rails/rails-observers'
|
30
|
+
gem "audited", "~> 4.4"
|
35
31
|
```
|
36
32
|
|
37
33
|
Then, from your Rails app directory, create the `audits` table:
|
@@ -41,6 +37,8 @@ $ rails generate audited:install
|
|
41
37
|
$ rake db:migrate
|
42
38
|
```
|
43
39
|
|
40
|
+
If you're using PostgreSQL, then you can use `rails generate audited:install --audited-changes-column-type jsonb` (or `json`) to store audit changes natively with its JSON column types.
|
41
|
+
|
44
42
|
#### Upgrading
|
45
43
|
|
46
44
|
If you're already using Audited (or acts_as_audited), your `audits` table may require additional columns. After every upgrade, please run:
|
@@ -166,7 +164,7 @@ Audited.current_user_method = :authenticated_user
|
|
166
164
|
Outside of a request, Audited can still record the user with the `as_user` method:
|
167
165
|
|
168
166
|
```ruby
|
169
|
-
Audited
|
167
|
+
Audited.audit_class.as_user(User.find(1)) do
|
170
168
|
post.update_attribute!(title: "Hello, world!")
|
171
169
|
end
|
172
170
|
post.audits.last.user # => #<User id: 1>
|
@@ -217,7 +215,7 @@ class Company < ActiveRecord::Base
|
|
217
215
|
end
|
218
216
|
```
|
219
217
|
|
220
|
-
Now, when
|
218
|
+
Now, when an audit is created for a user, that user's company is also saved alongside the audit. This makes it much easier (and faster) to access audits indirectly related to a company.
|
221
219
|
|
222
220
|
```ruby
|
223
221
|
company = Company.create!(name: "Collective Idea")
|
@@ -258,6 +256,26 @@ To disable auditing on an entire model:
|
|
258
256
|
User.auditing_enabled = false
|
259
257
|
```
|
260
258
|
|
259
|
+
### Custom `Audit` model
|
260
|
+
|
261
|
+
If you want to extend or modify the audit model, create a new class that
|
262
|
+
inherits from `Audited::Audit`:
|
263
|
+
```ruby
|
264
|
+
class CustomAudit < Audited::Audit
|
265
|
+
def some_custom_behavior
|
266
|
+
"Hiya!"
|
267
|
+
end
|
268
|
+
end
|
269
|
+
```
|
270
|
+
Then set it in an initializer:
|
271
|
+
```ruby
|
272
|
+
# config/initializers/audited.rb
|
273
|
+
|
274
|
+
Audited.config do |config|
|
275
|
+
config.audit_class = CustomAudit
|
276
|
+
end
|
277
|
+
```
|
278
|
+
|
261
279
|
## Gotchas
|
262
280
|
|
263
281
|
### Using attr_protected with Rails 4.x
|
data/gemfiles/rails50.gemfile
CHANGED
data/lib/audited.rb
CHANGED
@@ -1,19 +1,20 @@
|
|
1
|
-
require 'rails/observers/active_model/active_model'
|
2
1
|
require 'active_record'
|
3
2
|
|
4
3
|
module Audited
|
5
4
|
class << self
|
6
|
-
attr_accessor :ignored_attributes, :current_user_method
|
5
|
+
attr_accessor :ignored_attributes, :current_user_method, :audit_class
|
7
6
|
|
8
|
-
# Deprecate audit_class accessors in preperation of their removal
|
9
7
|
def audit_class
|
10
|
-
|
8
|
+
@audit_class || Audit
|
11
9
|
end
|
12
|
-
deprecate audit_class: "Audited.audit_class is now always Audited::Audit. This method will be removed."
|
13
10
|
|
14
11
|
def store
|
15
12
|
Thread.current[:audited_store] ||= {}
|
16
13
|
end
|
14
|
+
|
15
|
+
def config
|
16
|
+
yield(self)
|
17
|
+
end
|
17
18
|
end
|
18
19
|
|
19
20
|
@ignored_attributes = %w(lock_version created_at updated_at created_on updated_on)
|
data/lib/audited/audit.rb
CHANGED
@@ -6,25 +6,44 @@ module Audited
|
|
6
6
|
# * <tt>auditable</tt>: the ActiveRecord model that was changed
|
7
7
|
# * <tt>user</tt>: the user that performed the change; a string or an ActiveRecord model
|
8
8
|
# * <tt>action</tt>: one of create, update, or delete
|
9
|
-
# * <tt>audited_changes</tt>: a
|
9
|
+
# * <tt>audited_changes</tt>: a hash of all the changes
|
10
10
|
# * <tt>comment</tt>: a comment set with the audit
|
11
11
|
# * <tt>version</tt>: the version of the model
|
12
12
|
# * <tt>request_uuid</tt>: a uuid based that allows audits from the same controller request
|
13
13
|
# * <tt>created_at</tt>: Time that the change was performed
|
14
14
|
#
|
15
|
-
class Audit < ::ActiveRecord::Base
|
16
|
-
include ActiveModel::Observing
|
17
15
|
|
16
|
+
class YAMLIfTextColumnType
|
17
|
+
class << self
|
18
|
+
def load(obj)
|
19
|
+
if Audited.audit_class.columns_hash["audited_changes"].sql_type == "text"
|
20
|
+
ActiveRecord::Coders::YAMLColumn.new(Object).load(obj)
|
21
|
+
else
|
22
|
+
obj
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def dump(obj)
|
27
|
+
if Audited.audit_class.columns_hash["audited_changes"].sql_type == "text"
|
28
|
+
ActiveRecord::Coders::YAMLColumn.new(Object).dump(obj)
|
29
|
+
else
|
30
|
+
obj
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Audit < ::ActiveRecord::Base
|
18
37
|
belongs_to :auditable, polymorphic: true
|
19
38
|
belongs_to :user, polymorphic: true
|
20
39
|
belongs_to :associated, polymorphic: true
|
21
40
|
|
22
|
-
before_create :set_version_number, :set_audit_user, :set_request_uuid
|
41
|
+
before_create :set_version_number, :set_audit_user, :set_request_uuid, :set_remote_address
|
23
42
|
|
24
43
|
cattr_accessor :audited_class_names
|
25
44
|
self.audited_class_names = Set.new
|
26
45
|
|
27
|
-
serialize :audited_changes
|
46
|
+
serialize :audited_changes, YAMLIfTextColumnType
|
28
47
|
|
29
48
|
scope :ascending, ->{ reorder(version: :asc) }
|
30
49
|
scope :descending, ->{ reorder(version: :desc)}
|
@@ -95,10 +114,10 @@ module Audited
|
|
95
114
|
# by +user+. This method is hopefully threadsafe, making it ideal
|
96
115
|
# for background operations that require audit information.
|
97
116
|
def self.as_user(user, &block)
|
98
|
-
|
117
|
+
::Audited.store[:audited_user] = user
|
99
118
|
yield
|
100
119
|
ensure
|
101
|
-
|
120
|
+
::Audited.store[:audited_user] = nil
|
102
121
|
end
|
103
122
|
|
104
123
|
# @private
|
@@ -125,6 +144,11 @@ module Audited
|
|
125
144
|
record
|
126
145
|
end
|
127
146
|
|
147
|
+
# use created_at as timestamp cache key
|
148
|
+
def self.collection_cache_key(collection = all, timestamp_column = :created_at)
|
149
|
+
super(collection, :created_at)
|
150
|
+
end
|
151
|
+
|
128
152
|
private
|
129
153
|
|
130
154
|
def set_version_number
|
@@ -133,12 +157,18 @@ module Audited
|
|
133
157
|
end
|
134
158
|
|
135
159
|
def set_audit_user
|
136
|
-
self.user
|
160
|
+
self.user ||= ::Audited.store[:audited_user] # from .as_user
|
161
|
+
self.user ||= ::Audited.store[:current_user] # from Sweeper
|
137
162
|
nil # prevent stopping callback chains
|
138
163
|
end
|
139
164
|
|
140
165
|
def set_request_uuid
|
166
|
+
self.request_uuid ||= ::Audited.store[:current_request_uuid]
|
141
167
|
self.request_uuid ||= SecureRandom.uuid
|
142
168
|
end
|
169
|
+
|
170
|
+
def set_remote_address
|
171
|
+
self.remote_address ||= ::Audited.store[:current_remote_address]
|
172
|
+
end
|
143
173
|
end
|
144
174
|
end
|
data/lib/audited/auditor.rb
CHANGED
@@ -51,8 +51,8 @@ module Audited
|
|
51
51
|
|
52
52
|
attr_accessor :audit_comment
|
53
53
|
|
54
|
-
has_many :audits, -> { order(version: :asc) }, as: :auditable, class_name:
|
55
|
-
|
54
|
+
has_many :audits, -> { order(version: :asc) }, as: :auditable, class_name: Audited.audit_class.name
|
55
|
+
Audited.audit_class.audited_class_names << to_s
|
56
56
|
|
57
57
|
on = Array(options[:on])
|
58
58
|
after_create :audit_create if on.empty? || on.include?(:create)
|
@@ -75,7 +75,7 @@ module Audited
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def has_associated_audits
|
78
|
-
has_many :associated_audits, as: :associated, class_name:
|
78
|
+
has_many :associated_audits, as: :associated, class_name: Audited.audit_class.name
|
79
79
|
end
|
80
80
|
|
81
81
|
def default_ignored_attributes
|
@@ -118,13 +118,13 @@ module Audited
|
|
118
118
|
|
119
119
|
# Get a specific revision specified by the version number, or +:previous+
|
120
120
|
def revision(version)
|
121
|
-
revision_with
|
121
|
+
revision_with Audited.audit_class.reconstruct_attributes(audits_to(version))
|
122
122
|
end
|
123
123
|
|
124
124
|
# Find the oldest revision recorded prior to the date/time provided.
|
125
125
|
def revision_at(date_or_time)
|
126
126
|
audits = self.audits.up_until(date_or_time)
|
127
|
-
revision_with
|
127
|
+
revision_with Audited.audit_class.reconstruct_attributes(audits) unless audits.empty?
|
128
128
|
end
|
129
129
|
|
130
130
|
# List of attributes that are audited.
|
@@ -152,7 +152,7 @@ module Audited
|
|
152
152
|
revision.send :instance_variable_set, '@destroyed', false
|
153
153
|
revision.send :instance_variable_set, '@_destroyed', false
|
154
154
|
revision.send :instance_variable_set, '@marked_for_destruction', false
|
155
|
-
|
155
|
+
Audited.audit_class.assign_revision_attributes(revision, attributes)
|
156
156
|
|
157
157
|
# Remove any association proxies so that they will be recreated
|
158
158
|
# and reference the correct object for this revision. The only way
|
@@ -267,6 +267,10 @@ module Audited
|
|
267
267
|
end
|
268
268
|
end
|
269
269
|
|
270
|
+
def non_audited_columns=(columns)
|
271
|
+
@non_audited_columns = columns
|
272
|
+
end
|
273
|
+
|
270
274
|
# Executes the block with auditing disabled.
|
271
275
|
#
|
272
276
|
# Foo.without_auditing do
|
@@ -294,7 +298,7 @@ module Audited
|
|
294
298
|
# convenience wrapper around
|
295
299
|
# @see Audit#as_user.
|
296
300
|
def audit_as(user, &block)
|
297
|
-
|
301
|
+
Audited.audit_class.as_user(user, &block)
|
298
302
|
end
|
299
303
|
|
300
304
|
def auditing_enabled
|
data/lib/audited/sweeper.rb
CHANGED
@@ -1,60 +1,49 @@
|
|
1
|
-
require "rails/observers/activerecord/active_record"
|
2
|
-
require "rails/observers/action_controller/caching"
|
3
|
-
|
4
1
|
module Audited
|
5
|
-
class Sweeper
|
6
|
-
|
2
|
+
class Sweeper
|
3
|
+
STORED_DATA = {
|
4
|
+
current_remote_address: :remote_ip,
|
5
|
+
current_request_uuid: :request_uuid,
|
6
|
+
current_user: :current_user
|
7
|
+
}
|
8
|
+
|
9
|
+
delegate :store, to: ::Audited
|
7
10
|
|
8
11
|
def around(controller)
|
9
12
|
self.controller = controller
|
13
|
+
STORED_DATA.each { |k,m| store[k] = send(m) }
|
10
14
|
yield
|
11
15
|
ensure
|
12
16
|
self.controller = nil
|
13
|
-
|
14
|
-
|
15
|
-
def before_create(audit)
|
16
|
-
audit.user ||= current_user
|
17
|
-
audit.remote_address = controller.try(:request).try(:remote_ip)
|
18
|
-
audit.request_uuid = request_uuid if request_uuid
|
17
|
+
STORED_DATA.keys.each { |k| store.delete(k) }
|
19
18
|
end
|
20
19
|
|
21
20
|
def current_user
|
22
21
|
controller.send(Audited.current_user_method) if controller.respond_to?(Audited.current_user_method, true)
|
23
22
|
end
|
24
23
|
|
25
|
-
def
|
26
|
-
controller.try(:request).try(:
|
27
|
-
end
|
28
|
-
|
29
|
-
def add_observer!(klass)
|
30
|
-
super
|
31
|
-
define_callback(klass)
|
24
|
+
def remote_ip
|
25
|
+
controller.try(:request).try(:remote_ip)
|
32
26
|
end
|
33
27
|
|
34
|
-
def
|
35
|
-
|
36
|
-
callback_meth = :_notify_audited_sweeper
|
37
|
-
klass.send(:define_method, callback_meth) do
|
38
|
-
observer.update(:before_create, self)
|
39
|
-
end
|
40
|
-
klass.send(:before_create, callback_meth)
|
28
|
+
def request_uuid
|
29
|
+
controller.try(:request).try(:uuid)
|
41
30
|
end
|
42
31
|
|
43
32
|
def controller
|
44
|
-
|
33
|
+
store[:current_controller]
|
45
34
|
end
|
46
35
|
|
47
36
|
def controller=(value)
|
48
|
-
|
37
|
+
store[:current_controller] = value
|
49
38
|
end
|
50
39
|
end
|
51
40
|
end
|
52
41
|
|
53
42
|
ActiveSupport.on_load(:action_controller) do
|
54
43
|
if defined?(ActionController::Base)
|
55
|
-
ActionController::Base.around_action Audited::Sweeper.
|
44
|
+
ActionController::Base.around_action Audited::Sweeper.new
|
56
45
|
end
|
57
46
|
if defined?(ActionController::API)
|
58
|
-
ActionController::API.around_action Audited::Sweeper.
|
47
|
+
ActionController::API.around_action Audited::Sweeper.new
|
59
48
|
end
|
60
49
|
end
|
data/lib/audited/version.rb
CHANGED
@@ -3,13 +3,17 @@ require 'rails/generators/migration'
|
|
3
3
|
require 'active_record'
|
4
4
|
require 'rails/generators/active_record'
|
5
5
|
require 'generators/audited/migration'
|
6
|
+
require 'generators/audited/migration_helper'
|
6
7
|
|
7
8
|
module Audited
|
8
9
|
module Generators
|
9
10
|
class InstallGenerator < Rails::Generators::Base
|
10
11
|
include Rails::Generators::Migration
|
12
|
+
include Audited::Generators::MigrationHelper
|
11
13
|
extend Audited::Generators::Migration
|
12
14
|
|
15
|
+
class_option :audited_changes_column_type, type: :string, default: "text", required: false
|
16
|
+
|
13
17
|
source_root File.expand_path("../templates", __FILE__)
|
14
18
|
|
15
19
|
def copy_migration
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class <%= migration_class_name %> <
|
1
|
+
class <%= migration_class_name %> < <%= migration_parent %>
|
2
2
|
def self.up
|
3
3
|
create_table :audits, :force => true do |t|
|
4
4
|
t.column :auditable_id, :integer
|
@@ -9,7 +9,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration
|
|
9
9
|
t.column :user_type, :string
|
10
10
|
t.column :username, :string
|
11
11
|
t.column :action, :string
|
12
|
-
t.column :audited_changes, :
|
12
|
+
t.column :audited_changes, :<%= options[:audited_changes_column_type] %>
|
13
13
|
t.column :version, :integer, :default => 0
|
14
14
|
t.column :comment, :string
|
15
15
|
t.column :remote_address, :string
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class <%= migration_class_name %> <
|
1
|
+
class <%= migration_class_name %> < <%= migration_parent %>
|
2
2
|
def self.up
|
3
3
|
if index_exists? :audits, [:association_id, :association_type], :name => 'association_index'
|
4
4
|
remove_index :audits, :name => 'association_index'
|
@@ -3,11 +3,13 @@ require 'rails/generators/migration'
|
|
3
3
|
require 'active_record'
|
4
4
|
require 'rails/generators/active_record'
|
5
5
|
require 'generators/audited/migration'
|
6
|
+
require 'generators/audited/migration_helper'
|
6
7
|
|
7
8
|
module Audited
|
8
9
|
module Generators
|
9
10
|
class UpgradeGenerator < Rails::Generators::Base
|
10
11
|
include Rails::Generators::Migration
|
12
|
+
include Audited::Generators::MigrationHelper
|
11
13
|
extend Audited::Generators::Migration
|
12
14
|
|
13
15
|
source_root File.expand_path("../templates", __FILE__)
|
data/spec/audited/audit_spec.rb
CHANGED
@@ -3,6 +3,54 @@ require "spec_helper"
|
|
3
3
|
describe Audited::Audit do
|
4
4
|
let(:user) { Models::ActiveRecord::User.new name: "Testing" }
|
5
5
|
|
6
|
+
describe "audit class" do
|
7
|
+
around(:example) do |example|
|
8
|
+
original_audit_class = Audited.audit_class
|
9
|
+
|
10
|
+
class CustomAudit < Audited::Audit
|
11
|
+
def custom_method
|
12
|
+
"I'm custom!"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class TempModel < ::ActiveRecord::Base
|
17
|
+
self.table_name = :companies
|
18
|
+
end
|
19
|
+
|
20
|
+
example.run
|
21
|
+
|
22
|
+
Audited.config { |config| config.audit_class = original_audit_class }
|
23
|
+
Audited::Audit.audited_class_names.delete("TempModel")
|
24
|
+
Object.send(:remove_const, :TempModel)
|
25
|
+
Object.send(:remove_const, :CustomAudit)
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when a custom audit class is configured" do
|
29
|
+
it "should be used in place of #{described_class}" do
|
30
|
+
Audited.config { |config| config.audit_class = CustomAudit }
|
31
|
+
TempModel.audited
|
32
|
+
|
33
|
+
record = TempModel.create
|
34
|
+
|
35
|
+
audit = record.audits.first
|
36
|
+
expect(audit).to be_a CustomAudit
|
37
|
+
expect(audit.custom_method).to eq "I'm custom!"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when a custom audit class is not configured" do
|
42
|
+
it "should default to #{described_class}" do
|
43
|
+
TempModel.audited
|
44
|
+
|
45
|
+
record = TempModel.create
|
46
|
+
|
47
|
+
audit = record.audits.first
|
48
|
+
expect(audit).to be_a Audited::Audit
|
49
|
+
expect(audit.respond_to?(:custom_method)).to be false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
6
54
|
describe "user=" do
|
7
55
|
|
8
56
|
it "should be able to set the user to a model object" do
|
@@ -191,9 +239,8 @@ describe Audited::Audit do
|
|
191
239
|
raise StandardError.new('expected')
|
192
240
|
end
|
193
241
|
}.to raise_exception('expected')
|
194
|
-
expect(
|
242
|
+
expect(Audited.store[:audited_user]).to be_nil
|
195
243
|
end
|
196
244
|
|
197
245
|
end
|
198
|
-
|
199
246
|
end
|
@@ -17,7 +17,7 @@ describe Audited::Auditor do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
it "should be configurable which attributes are not audited" do
|
20
|
+
it "should be configurable which attributes are not audited via ignored_attributes" do
|
21
21
|
Audited.ignored_attributes = ['delta', 'top_secret', 'created_at']
|
22
22
|
class Secret < ::ActiveRecord::Base
|
23
23
|
audited
|
@@ -26,6 +26,15 @@ describe Audited::Auditor do
|
|
26
26
|
expect(Secret.non_audited_columns).to include('delta', 'top_secret', 'created_at')
|
27
27
|
end
|
28
28
|
|
29
|
+
it "should be configurable which attributes are not audited via non_audited_columns=" do
|
30
|
+
class Secret2 < ::ActiveRecord::Base
|
31
|
+
audited
|
32
|
+
self.non_audited_columns = ['delta', 'top_secret', 'created_at']
|
33
|
+
end
|
34
|
+
|
35
|
+
expect(Secret2.non_audited_columns).to include('delta', 'top_secret', 'created_at')
|
36
|
+
end
|
37
|
+
|
29
38
|
it "should not save non-audited columns" do
|
30
39
|
expect(create_user.audits.first.audited_changes.keys.any? { |col| ['created_at', 'updated_at', 'password'].include?( col ) }).to eq(false)
|
31
40
|
end
|
@@ -48,6 +57,38 @@ describe Audited::Auditor do
|
|
48
57
|
user.save!
|
49
58
|
expect(user.audits.last.audited_changes.keys).to eq(%w{password})
|
50
59
|
end
|
60
|
+
|
61
|
+
if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' && Rails.version >= "4.2.0.0" # Postgres json and jsonb support was added in Rails 4.2
|
62
|
+
describe "'json' and 'jsonb' audited_changes column type" do
|
63
|
+
let(:migrations_path) { SPEC_ROOT.join("support/active_record/postgres") }
|
64
|
+
|
65
|
+
after do
|
66
|
+
ActiveRecord::Migrator.rollback([migrations_path])
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should work if column type is 'json'" do
|
70
|
+
ActiveRecord::Migrator.up([migrations_path], 1)
|
71
|
+
Audited::Audit.reset_column_information
|
72
|
+
expect(Audited::Audit.columns_hash["audited_changes"].sql_type).to eq("json")
|
73
|
+
|
74
|
+
user = Models::ActiveRecord::User.create
|
75
|
+
user.name = "new name"
|
76
|
+
user.save!
|
77
|
+
expect(user.audits.last.audited_changes).to eq({"name" => [nil, "new name"]})
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should work if column type is 'jsonb'" do
|
81
|
+
ActiveRecord::Migrator.up([migrations_path], 2)
|
82
|
+
Audited::Audit.reset_column_information
|
83
|
+
expect(Audited::Audit.columns_hash["audited_changes"].sql_type).to eq("jsonb")
|
84
|
+
|
85
|
+
user = Models::ActiveRecord::User.create
|
86
|
+
user.name = "new name"
|
87
|
+
user.save!
|
88
|
+
expect(user.audits.last.audited_changes).to eq({"name" => [nil, "new name"]})
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
51
92
|
end
|
52
93
|
|
53
94
|
describe :new do
|
@@ -601,7 +642,7 @@ describe Audited::Auditor do
|
|
601
642
|
Models::ActiveRecord::Company.auditing_enabled = false
|
602
643
|
company.update_attributes name: 'STI auditors'
|
603
644
|
Models::ActiveRecord::Company.auditing_enabled = true
|
604
|
-
}.to_not change( Audited
|
645
|
+
}.to_not change( Audited::Audit, :count )
|
605
646
|
end
|
606
647
|
end
|
607
648
|
end
|
@@ -76,7 +76,7 @@ describe AuditsController do
|
|
76
76
|
controller.send(:current_user=, user)
|
77
77
|
|
78
78
|
expect {
|
79
|
-
put :update, id: 123
|
79
|
+
put :update, Rails::VERSION::MAJOR == 4 ? {id: 123} : {params: {id: 123}}
|
80
80
|
}.to_not change( Audited::Audit, :count )
|
81
81
|
end
|
82
82
|
end
|
@@ -86,21 +86,23 @@ end
|
|
86
86
|
describe Audited::Sweeper do
|
87
87
|
|
88
88
|
it "should be thread-safe" do
|
89
|
+
instance = Audited::Sweeper.new
|
90
|
+
|
89
91
|
t1 = Thread.new do
|
90
92
|
sleep 0.5
|
91
|
-
|
92
|
-
expect(
|
93
|
+
instance.controller = 'thread1 controller instance'
|
94
|
+
expect(instance.controller).to eq('thread1 controller instance')
|
93
95
|
end
|
94
96
|
|
95
97
|
t2 = Thread.new do
|
96
|
-
|
98
|
+
instance.controller = 'thread2 controller instance'
|
97
99
|
sleep 1
|
98
|
-
expect(
|
100
|
+
expect(instance.controller).to eq('thread2 controller instance')
|
99
101
|
end
|
100
102
|
|
101
103
|
t1.join; t2.join
|
102
104
|
|
103
|
-
expect(
|
105
|
+
expect(instance.controller).to be_nil
|
104
106
|
end
|
105
107
|
|
106
108
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
parent = Rails::VERSION::MAJOR == 4 ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
|
2
|
+
class ChangeAuditedChangesTypeToJson < parent
|
3
|
+
def self.up
|
4
|
+
remove_column :audits, :audited_changes
|
5
|
+
add_column :audits, :audited_changes, :json
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.down
|
9
|
+
remove_column :audits, :audited_changes
|
10
|
+
add_column :audits, :audited_changes, :text
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
parent = Rails::VERSION::MAJOR == 4 ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
|
2
|
+
class ChangeAuditedChangesTypeToJsonb < parent
|
3
|
+
def self.up
|
4
|
+
remove_column :audits, :audited_changes
|
5
|
+
add_column :audits, :audited_changes, :jsonb
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.down
|
9
|
+
remove_column :audits, :audited_changes
|
10
|
+
add_column :audits, :audited_changes, :text
|
11
|
+
end
|
12
|
+
end
|
@@ -7,11 +7,39 @@ class InstallGeneratorTest < Rails::Generators::TestCase
|
|
7
7
|
setup :prepare_destination
|
8
8
|
tests Audited::Generators::InstallGenerator
|
9
9
|
|
10
|
-
test "
|
11
|
-
run_generator
|
10
|
+
test "generate migration with 'text' type for audited_changes column" do
|
11
|
+
run_generator
|
12
12
|
|
13
13
|
assert_migration "db/migrate/install_audited.rb" do |content|
|
14
|
-
|
14
|
+
assert_includes(content, 'class InstallAudited')
|
15
|
+
assert_includes(content, 't.column :audited_changes, :text')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
test "generate migration with 'jsonb' type for audited_changes column" do
|
20
|
+
run_generator %w(--audited-changes-column-type jsonb)
|
21
|
+
|
22
|
+
assert_migration "db/migrate/install_audited.rb" do |content|
|
23
|
+
assert_includes(content, 'class InstallAudited')
|
24
|
+
assert_includes(content, 't.column :audited_changes, :jsonb')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
test "generate migration with 'json' type for audited_changes column" do
|
29
|
+
run_generator %w(--audited-changes-column-type json)
|
30
|
+
|
31
|
+
assert_migration "db/migrate/install_audited.rb" do |content|
|
32
|
+
assert_includes(content, 'class InstallAudited')
|
33
|
+
assert_includes(content, 't.column :audited_changes, :json')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
test "generate migration with correct AR migration parent" do
|
38
|
+
run_generator
|
39
|
+
|
40
|
+
assert_migration "db/migrate/install_audited.rb" do |content|
|
41
|
+
parent = Rails::VERSION::MAJOR == 4 ? 'ActiveRecord::Migration' : "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
|
42
|
+
assert_includes(content, "class InstallAudited < #{parent}\n")
|
15
43
|
end
|
16
44
|
end
|
17
45
|
end
|
@@ -6,7 +6,11 @@ class UpgradeGeneratorTest < Rails::Generators::TestCase
|
|
6
6
|
destination File.expand_path('../../tmp', __FILE__)
|
7
7
|
setup :prepare_destination
|
8
8
|
tests Audited::Generators::UpgradeGenerator
|
9
|
-
|
9
|
+
if Rails::VERSION::MAJOR == 4
|
10
|
+
self.use_transactional_fixtures = false
|
11
|
+
else
|
12
|
+
self.use_transactional_tests = false
|
13
|
+
end
|
10
14
|
|
11
15
|
test "should add 'comment' to audits table" do
|
12
16
|
load_schema 1
|
@@ -74,4 +78,15 @@ class UpgradeGeneratorTest < Rails::Generators::TestCase
|
|
74
78
|
assert_match(/add_index :audits, :request_uuid/, content)
|
75
79
|
end
|
76
80
|
end
|
81
|
+
|
82
|
+
test "generate migration with correct AR migration parent" do
|
83
|
+
load_schema 1
|
84
|
+
|
85
|
+
run_generator %w(upgrade)
|
86
|
+
|
87
|
+
assert_migration "db/migrate/add_comment_to_audits.rb" do |content|
|
88
|
+
parent = Rails::VERSION::MAJOR == 4 ? 'ActiveRecord::Migration' : "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
|
89
|
+
assert_includes(content, "class AddCommentToAudits < #{parent}\n")
|
90
|
+
end
|
91
|
+
end
|
77
92
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: audited
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Keepers
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date:
|
16
|
+
date: 2017-03-29 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: activerecord
|
@@ -35,20 +35,6 @@ dependencies:
|
|
35
35
|
- - "<"
|
36
36
|
- !ruby/object:Gem::Version
|
37
37
|
version: '5.1'
|
38
|
-
- !ruby/object:Gem::Dependency
|
39
|
-
name: rails-observers
|
40
|
-
requirement: !ruby/object:Gem::Requirement
|
41
|
-
requirements:
|
42
|
-
- - "~>"
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
version: 0.1.2
|
45
|
-
type: :runtime
|
46
|
-
prerelease: false
|
47
|
-
version_requirements: !ruby/object:Gem::Requirement
|
48
|
-
requirements:
|
49
|
-
- - "~>"
|
50
|
-
- !ruby/object:Gem::Version
|
51
|
-
version: 0.1.2
|
52
38
|
- !ruby/object:Gem::Dependency
|
53
39
|
name: appraisal
|
54
40
|
requirement: !ruby/object:Gem::Requirement
|
@@ -149,7 +135,7 @@ files:
|
|
149
135
|
- ".travis.yml"
|
150
136
|
- ".yardopts"
|
151
137
|
- Appraisals
|
152
|
-
- CHANGELOG
|
138
|
+
- CHANGELOG.md
|
153
139
|
- Gemfile
|
154
140
|
- LICENSE
|
155
141
|
- README.md
|
@@ -158,6 +144,7 @@ files:
|
|
158
144
|
- gemfiles/rails41.gemfile
|
159
145
|
- gemfiles/rails42.gemfile
|
160
146
|
- gemfiles/rails50.gemfile
|
147
|
+
- gemfiles/rails51.gemfile
|
161
148
|
- lib/audited-rspec.rb
|
162
149
|
- lib/audited.rb
|
163
150
|
- lib/audited/audit.rb
|
@@ -167,6 +154,7 @@ files:
|
|
167
154
|
- lib/audited/version.rb
|
168
155
|
- lib/generators/audited/install_generator.rb
|
169
156
|
- lib/generators/audited/migration.rb
|
157
|
+
- lib/generators/audited/migration_helper.rb
|
170
158
|
- lib/generators/audited/templates/add_association_to_audits.rb
|
171
159
|
- lib/generators/audited/templates/add_comment_to_audits.rb
|
172
160
|
- lib/generators/audited/templates/add_remote_address_to_audits.rb
|
@@ -192,6 +180,8 @@ files:
|
|
192
180
|
- spec/rails_app/config/routes.rb
|
193
181
|
- spec/spec_helper.rb
|
194
182
|
- spec/support/active_record/models.rb
|
183
|
+
- spec/support/active_record/postgres/1_change_audited_changes_type_to_json.rb
|
184
|
+
- spec/support/active_record/postgres/2_change_audited_changes_type_to_jsonb.rb
|
195
185
|
- spec/support/active_record/schema.rb
|
196
186
|
- test/db/version_1.rb
|
197
187
|
- test/db/version_2.rb
|
data/CHANGELOG
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
Audited ChangeLog
|
2
|
-
-------------------------------------------------------------------------------
|
3
|
-
* 2012-04-10 - Add Audit scopes for creates, updates and destroys [chriswfx]
|
4
|
-
* 2011-10-25 - Made ignored_attributes configurable [senny]
|
5
|
-
* 2011-09-09 - Rails 3.x support
|
6
|
-
Support for associated audits
|
7
|
-
Support for remote IP address storage
|
8
|
-
Plenty of bug fixes and refactoring
|
9
|
-
[kennethkalmer, ineu, PatrickMa, jrozner, dwarburton, bsiggelkow, dgm]
|
10
|
-
* 2009-01-27 - Store old and new values for updates, and store all attributes on destroy.
|
11
|
-
Refactored revisioning methods to work as expected
|
12
|
-
* 2008-10-10 - changed to make it work in development mode
|
13
|
-
* 2008-09-24 - Add ability to record parent record of the record being audited
|
14
|
-
[Kenneth Kalmer]
|
15
|
-
* 2008-04-19 - refactored to make compatible with dirty tracking in edge rails
|
16
|
-
and to stop storing both old and new values in a single audit
|
17
|
-
* 2008-04-18 - Fix NoMethodError when trying to access the :previous revision
|
18
|
-
on a model that doesn't have previous revisions [Alex Soto]
|
19
|
-
* 2008-03-21 - added #changed_attributes to get access to the changes before a
|
20
|
-
save [Chris Parker]
|
21
|
-
* 2007-12-16 - Added #revision_at for retrieving a revision from a specific
|
22
|
-
time [Jacob Atzen]
|
23
|
-
* 2007-12-16 - Fix error when getting revision from audit with no changes
|
24
|
-
[Geoffrey Wiseman]
|
25
|
-
* 2007-12-16 - Remove dependency on acts_as_list
|
26
|
-
* 2007-06-17 - Added support getting previous revisions
|
27
|
-
* 2006-11-17 - Replaced use of singleton User.current_user with cache sweeper
|
28
|
-
implementation for auditing the user that made the change
|
29
|
-
* 2006-11-17 - added migration generator
|
30
|
-
* 2006-08-14 - incorporated changes from Michael Schuerig to write_attribute
|
31
|
-
that saves the new value after every change and not just the
|
32
|
-
first, and performs proper type-casting before doing comparisons
|
33
|
-
* 2006-08-14 - The "changes" are now saved as a serialized hash
|
34
|
-
* 2006-07-21 - initial version
|