audited 4.6.0 → 4.7.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 +14 -5
- data/Appraisals +1 -1
- data/CHANGELOG.md +32 -0
- data/README.md +58 -28
- data/gemfiles/rails52.gemfile +1 -1
- data/lib/audited.rb +1 -1
- data/lib/audited/auditor.rb +103 -16
- data/lib/audited/rspec_matchers.rb +70 -21
- data/lib/audited/version.rb +1 -1
- data/spec/audited/auditor_spec.rb +216 -9
- data/spec/audited/rspec_matchers_spec.rb +69 -0
- data/spec/audited_spec_helpers.rb +14 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/support/active_record/models.rb +28 -3
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a2d5a695157822691d7e8a980742c9dab27769c
|
4
|
+
data.tar.gz: 41262a1baa392f65fd172c6971985ca43ab53e92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4d0ebf2b9683b96d7954efb7e2ddab5c21e3c0cea29d9d7388334a9f9215f8729b337c850f60abf9b9084773158609d32e99ab580aec244393dc79d41846fad
|
7
|
+
data.tar.gz: 32a48ffa57d8ebd24ece8714b4c26c8c0a0af4ed7021f165a625a619c058c71749510e20417e9a15629385e72b999409b39186e050af10f5cf73ad36760b25b5
|
data/.travis.yml
CHANGED
@@ -2,9 +2,10 @@ language: ruby
|
|
2
2
|
cache: bundler
|
3
3
|
rvm:
|
4
4
|
- 2.1
|
5
|
-
- 2.2.
|
6
|
-
- 2.3.
|
7
|
-
- 2.4.
|
5
|
+
- 2.2.9
|
6
|
+
- 2.3.6
|
7
|
+
- 2.4.3
|
8
|
+
- 2.5.0
|
8
9
|
- ruby-head
|
9
10
|
env:
|
10
11
|
- DB=SQLITE
|
@@ -12,6 +13,10 @@ env:
|
|
12
13
|
- DB=MYSQL
|
13
14
|
addons:
|
14
15
|
postgresql: "9.4"
|
16
|
+
before_install:
|
17
|
+
# https://github.com/travis-ci/travis-ci/issues/8978
|
18
|
+
- "travis_retry gem update --system"
|
19
|
+
- "travis_retry gem install bundler"
|
15
20
|
gemfile:
|
16
21
|
- gemfiles/rails40.gemfile
|
17
22
|
- gemfiles/rails41.gemfile
|
@@ -29,9 +34,13 @@ matrix:
|
|
29
34
|
gemfile: gemfiles/rails51.gemfile
|
30
35
|
- rvm: 2.1
|
31
36
|
gemfile: gemfiles/rails52.gemfile
|
32
|
-
- rvm: 2.4.
|
37
|
+
- rvm: 2.4.3
|
33
38
|
gemfile: gemfiles/rails40.gemfile
|
34
|
-
- rvm: 2.4.
|
39
|
+
- rvm: 2.4.3
|
40
|
+
gemfile: gemfiles/rails41.gemfile
|
41
|
+
- rvm: 2.5.0
|
42
|
+
gemfile: gemfiles/rails40.gemfile
|
43
|
+
- rvm: 2.5.0
|
35
44
|
gemfile: gemfiles/rails41.gemfile
|
36
45
|
- rvm: ruby-head
|
37
46
|
gemfile: gemfiles/rails40.gemfile
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
@@ -18,6 +18,38 @@ Fixed
|
|
18
18
|
|
19
19
|
- None
|
20
20
|
|
21
|
+
## 4.7.0 (2018-03-14)
|
22
|
+
|
23
|
+
Breaking changes
|
24
|
+
|
25
|
+
- None
|
26
|
+
|
27
|
+
Added
|
28
|
+
|
29
|
+
- Add `inverse_of: auditable` definition to audit relation
|
30
|
+
[#413](https://github.com/collectiveidea/audited/pull/413)
|
31
|
+
- Add functionality to conditionally audit models
|
32
|
+
[#414](https://github.com/collectiveidea/audited/pull/414)
|
33
|
+
- Allow limiting number of audits stored
|
34
|
+
[#405](https://github.com/collectiveidea/audited/pull/405)
|
35
|
+
|
36
|
+
Changed
|
37
|
+
|
38
|
+
- Reduced db calls in `#revisions` method
|
39
|
+
[#402](https://github.com/collectiveidea/audited/pull/402)
|
40
|
+
[#403](https://github.com/collectiveidea/audited/pull/403)
|
41
|
+
- Update supported Ruby and Rails versions
|
42
|
+
[#404](https://github.com/collectiveidea/audited/pull/404)
|
43
|
+
[#409](https://github.com/collectiveidea/audited/pull/409)
|
44
|
+
[#415](https://github.com/collectiveidea/audited/pull/415)
|
45
|
+
[#416](https://github.com/collectiveidea/audited/pull/416)
|
46
|
+
|
47
|
+
Fixed
|
48
|
+
|
49
|
+
- Ensure that `on` and `except` options jive with `comment_required: true`
|
50
|
+
[#419](https://github.com/collectiveidea/audited/pull/419)
|
51
|
+
- Fix RSpec matchers
|
52
|
+
[#420](https://github.com/collectiveidea/audited/pull/420)
|
21
53
|
|
22
54
|
## 4.6.0 (2018-01-10)
|
23
55
|
|
data/README.md
CHANGED
@@ -12,9 +12,10 @@ For Rails 3, use gem version 3.0 or see the [3.0-stable branch](https://github.c
|
|
12
12
|
Audited supports and is [tested against](http://travis-ci.org/collectiveidea/audited) the following Ruby versions:
|
13
13
|
|
14
14
|
* 2.1.10
|
15
|
-
* 2.2.
|
16
|
-
* 2.3.
|
17
|
-
* 2.4.
|
15
|
+
* 2.2.9
|
16
|
+
* 2.3.6
|
17
|
+
* 2.4.3
|
18
|
+
* 2.5.0
|
18
19
|
|
19
20
|
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).
|
20
21
|
|
@@ -27,7 +28,7 @@ Audited is currently ActiveRecord-only. In a previous life, Audited worked with
|
|
27
28
|
Add the gem to your Gemfile:
|
28
29
|
|
29
30
|
```ruby
|
30
|
-
gem "audited", "~> 4.
|
31
|
+
gem "audited", "~> 4.7"
|
31
32
|
```
|
32
33
|
|
33
34
|
Then, from your Rails app directory, create the `audits` table:
|
@@ -141,6 +142,33 @@ class User < ActiveRecord::Base
|
|
141
142
|
end
|
142
143
|
```
|
143
144
|
|
145
|
+
### Limiting stored audits
|
146
|
+
|
147
|
+
You can limit the number of audits stored for your model. To configure limiting for all audited models, put the following in an initializer:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
Audited.max_audits = 10 # keep only 10 latest audits
|
151
|
+
```
|
152
|
+
|
153
|
+
or customize per model:
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
class User < ActiveRecord::Base
|
157
|
+
audited max_audits: 2
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
Whenever an object is updated or destroyed, extra audits are combined with newer ones and the old ones are destroyed.
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
user = User.create!(name: "Steve")
|
165
|
+
user.audits.count # => 1
|
166
|
+
user.update_attributes!(name: "Ryan")
|
167
|
+
user.audits.count # => 2
|
168
|
+
user.destroy
|
169
|
+
user.audits.count # => 2
|
170
|
+
```
|
171
|
+
|
144
172
|
### Current User Tracking
|
145
173
|
|
146
174
|
If you're using Audited in a Rails application, all audited changes made within a request will automatically be attributed to the current user. By default, Audited uses the `current_user` method in your controller.
|
@@ -227,6 +255,32 @@ user.audits.last.associated # => #<Company name: "Collective Idea">
|
|
227
255
|
company.associated_audits.last.auditable # => #<User name: "Steve Richert">
|
228
256
|
```
|
229
257
|
|
258
|
+
### Conditional auditing
|
259
|
+
|
260
|
+
If you want to audit only under specific conditions, you can provide conditional options (similar to ActiveModel callbacks) that will ensure your model is only audited for these conditions.
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
class User < ActiveRecord::Base
|
264
|
+
audited if: :active?
|
265
|
+
|
266
|
+
private
|
267
|
+
|
268
|
+
def active?
|
269
|
+
last_login > 6.months.ago
|
270
|
+
end
|
271
|
+
end
|
272
|
+
```
|
273
|
+
|
274
|
+
Just like in ActiveModel, you can use an inline Proc in your conditions:
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
class User < ActiveRecord::Base
|
278
|
+
audited unless: Proc.new { |u| u.ninja? }
|
279
|
+
end
|
280
|
+
```
|
281
|
+
|
282
|
+
In the above case, the user will only be audited when `User#ninja` is `false`.
|
283
|
+
|
230
284
|
### Disabling auditing
|
231
285
|
|
232
286
|
If you want to disable auditing temporarily doing certain tasks, there are a few
|
@@ -278,30 +332,6 @@ Audited.config do |config|
|
|
278
332
|
end
|
279
333
|
```
|
280
334
|
|
281
|
-
## Gotchas
|
282
|
-
|
283
|
-
### Using attr_protected with Rails 4.x
|
284
|
-
|
285
|
-
If you're using the `protected_attributes` gem with Rails 4.0, 4.1 or 4.2 (the gem isn't supported in Rails 5.0 or higher), you'll have to take an extra couple of steps to get `audited` working.
|
286
|
-
|
287
|
-
First be sure to add `allow_mass_assignment: true` to your `audited` call; otherwise Audited will
|
288
|
-
interfere with `protected_attributes` and none of your `save` calls will work.
|
289
|
-
|
290
|
-
```ruby
|
291
|
-
class User < ActiveRecord::Base
|
292
|
-
audited allow_mass_assignment: true
|
293
|
-
end
|
294
|
-
```
|
295
|
-
|
296
|
-
Second, be sure to add `audit_ids` to the list of protected attributes to prevent data loss.
|
297
|
-
|
298
|
-
```ruby
|
299
|
-
class User < ActiveRecord::Base
|
300
|
-
audited allow_mass_assignment: true
|
301
|
-
attr_protected :logins, :audit_ids
|
302
|
-
end
|
303
|
-
```
|
304
|
-
|
305
335
|
## Support
|
306
336
|
|
307
337
|
You can find documentation at: http://rdoc.info/github/collectiveidea/audited
|
data/gemfiles/rails52.gemfile
CHANGED
data/lib/audited.rb
CHANGED
data/lib/audited/auditor.rb
CHANGED
@@ -33,6 +33,18 @@ module Audited
|
|
33
33
|
#
|
34
34
|
# * +require_comment+ - Ensures that audit_comment is supplied before
|
35
35
|
# any create, update or destroy operation.
|
36
|
+
# * +max_audits+ - Limits the number of stored audits.
|
37
|
+
#
|
38
|
+
# * +if+ - Only audit the model when the given function returns true
|
39
|
+
# * +unless+ - Only audit the model when the given function returns false
|
40
|
+
#
|
41
|
+
# class User < ActiveRecord::Base
|
42
|
+
# audited :if => :active?
|
43
|
+
#
|
44
|
+
# def active?
|
45
|
+
# self.status == 'active'
|
46
|
+
# end
|
47
|
+
# end
|
36
48
|
#
|
37
49
|
def audited(options = {})
|
38
50
|
# don't allow multiple calls
|
@@ -41,7 +53,7 @@ module Audited
|
|
41
53
|
extend Audited::Auditor::AuditedClassMethods
|
42
54
|
include Audited::Auditor::AuditedInstanceMethods
|
43
55
|
|
44
|
-
class_attribute :audit_associated_with,
|
56
|
+
class_attribute :audit_associated_with, instance_writer: false
|
45
57
|
class_attribute :audited_options, instance_writer: false
|
46
58
|
attr_accessor :version, :audit_comment
|
47
59
|
|
@@ -51,11 +63,11 @@ module Audited
|
|
51
63
|
self.audit_associated_with = audited_options[:associated_with]
|
52
64
|
|
53
65
|
if audited_options[:comment_required]
|
54
|
-
|
55
|
-
before_destroy :require_comment
|
66
|
+
validate :presence_of_audit_comment
|
67
|
+
before_destroy :require_comment if audited_options[:on].include?(:destroy)
|
56
68
|
end
|
57
69
|
|
58
|
-
has_many :audits, -> { order(version: :asc) }, as: :auditable, class_name: Audited.audit_class.name
|
70
|
+
has_many :audits, -> { order(version: :asc) }, as: :auditable, class_name: Audited.audit_class.name, inverse_of: :auditable
|
59
71
|
Audited.audit_class.audited_class_names << to_s
|
60
72
|
|
61
73
|
after_create :audit_create if audited_options[:on].include?(:create)
|
@@ -101,9 +113,17 @@ module Audited
|
|
101
113
|
# end
|
102
114
|
#
|
103
115
|
def revisions(from_version = 1)
|
104
|
-
|
105
|
-
|
106
|
-
audits.
|
116
|
+
return [] unless audits.from_version(from_version).exists?
|
117
|
+
|
118
|
+
all_audits = audits.select([:audited_changes, :version]).to_a
|
119
|
+
targeted_audits = all_audits.select { |audit| audit.version >= from_version }
|
120
|
+
|
121
|
+
previous_attributes = reconstruct_attributes(all_audits - targeted_audits)
|
122
|
+
|
123
|
+
targeted_audits.map do |audit|
|
124
|
+
previous_attributes.merge!(audit.new_attributes)
|
125
|
+
revision_with(previous_attributes.merge!(version: audit.version))
|
126
|
+
end
|
107
127
|
end
|
108
128
|
|
109
129
|
# Get a specific revision specified by the version number, or +:previous+
|
@@ -125,6 +145,18 @@ module Audited
|
|
125
145
|
attributes.except(*non_audited_columns)
|
126
146
|
end
|
127
147
|
|
148
|
+
# Combine multiple audits into one.
|
149
|
+
def combine_audits(audits_to_combine)
|
150
|
+
combine_target = audits_to_combine.last
|
151
|
+
combine_target.audited_changes = audits_to_combine.pluck(:audited_changes).reduce(&:merge)
|
152
|
+
combine_target.comment = "#{combine_target.comment}\nThis audit is the result of multiple audits being combined."
|
153
|
+
|
154
|
+
transaction do
|
155
|
+
combine_target.save!
|
156
|
+
audits_to_combine.unscope(:limit).where("version < ?", combine_target.version).delete_all
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
128
160
|
protected
|
129
161
|
|
130
162
|
def non_audited_columns
|
@@ -208,14 +240,41 @@ module Audited
|
|
208
240
|
def write_audit(attrs)
|
209
241
|
attrs[:associated] = send(audit_associated_with) unless audit_associated_with.nil?
|
210
242
|
self.audit_comment = nil
|
211
|
-
|
243
|
+
|
244
|
+
if auditing_enabled
|
245
|
+
run_callbacks(:audit) {
|
246
|
+
audit = audits.create(attrs)
|
247
|
+
combine_audits_if_needed if attrs[:action] != 'create'
|
248
|
+
audit
|
249
|
+
}
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def presence_of_audit_comment
|
254
|
+
if comment_required_state?
|
255
|
+
errors.add(:audit_comment, "Comment can't be blank!") unless audit_comment.present?
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def comment_required_state?
|
260
|
+
auditing_enabled &&
|
261
|
+
((audited_options[:on].include?(:create) && self.new_record?) ||
|
262
|
+
(audited_options[:on].include?(:update) && self.persisted? && self.changed?))
|
263
|
+
end
|
264
|
+
|
265
|
+
def combine_audits_if_needed
|
266
|
+
max_audits = audited_options[:max_audits]
|
267
|
+
if max_audits && (extra_count = audits.count - max_audits) > 0
|
268
|
+
audits_to_combine = audits.limit(extra_count + 1)
|
269
|
+
combine_audits(audits_to_combine)
|
270
|
+
end
|
212
271
|
end
|
213
272
|
|
214
273
|
def require_comment
|
215
274
|
if auditing_enabled && audit_comment.blank?
|
216
|
-
errors.add(:audit_comment, "Comment
|
275
|
+
errors.add(:audit_comment, "Comment can't be blank!")
|
217
276
|
return false if Rails.version.start_with?('4.')
|
218
|
-
throw
|
277
|
+
throw(:abort)
|
219
278
|
end
|
220
279
|
end
|
221
280
|
|
@@ -224,12 +283,29 @@ module Audited
|
|
224
283
|
end
|
225
284
|
|
226
285
|
def auditing_enabled
|
227
|
-
|
286
|
+
return run_conditional_check(audited_options[:if]) &&
|
287
|
+
run_conditional_check(audited_options[:unless], matching: false) &&
|
288
|
+
self.class.auditing_enabled
|
289
|
+
end
|
290
|
+
|
291
|
+
def run_conditional_check(condition, matching: true)
|
292
|
+
return true if condition.blank?
|
293
|
+
|
294
|
+
return condition.call(self) == matching if condition.respond_to?(:call)
|
295
|
+
return send(condition) == matching if respond_to?(condition.to_sym)
|
296
|
+
|
297
|
+
true
|
228
298
|
end
|
229
299
|
|
230
300
|
def auditing_enabled=(val)
|
231
301
|
self.class.auditing_enabled = val
|
232
302
|
end
|
303
|
+
|
304
|
+
def reconstruct_attributes(audits)
|
305
|
+
attributes = {}
|
306
|
+
audits.each { |audit| attributes.merge!(audit.new_attributes) }
|
307
|
+
attributes
|
308
|
+
end
|
233
309
|
end # InstanceMethods
|
234
310
|
|
235
311
|
module AuditedClassMethods
|
@@ -240,9 +316,7 @@ module Audited
|
|
240
316
|
|
241
317
|
# We have to calculate this here since column_names may not be available when `audited` is called
|
242
318
|
def non_audited_columns
|
243
|
-
@non_audited_columns ||=
|
244
|
-
column_names - audited_options[:only] :
|
245
|
-
default_ignored_attributes | audited_options[:except]
|
319
|
+
@non_audited_columns ||= calculate_non_audited_columns
|
246
320
|
end
|
247
321
|
|
248
322
|
def non_audited_columns=(columns)
|
@@ -288,16 +362,29 @@ module Audited
|
|
288
362
|
Audited.store["#{table_name}_auditing_enabled"] = val
|
289
363
|
end
|
290
364
|
|
291
|
-
protected
|
292
365
|
def default_ignored_attributes
|
293
|
-
[primary_key, inheritance_column]
|
366
|
+
[primary_key, inheritance_column] | Audited.ignored_attributes
|
294
367
|
end
|
295
368
|
|
369
|
+
protected
|
370
|
+
|
296
371
|
def normalize_audited_options
|
297
372
|
audited_options[:on] = Array.wrap(audited_options[:on])
|
298
373
|
audited_options[:on] = [:create, :update, :destroy] if audited_options[:on].empty?
|
299
374
|
audited_options[:only] = Array.wrap(audited_options[:only]).map(&:to_s)
|
300
375
|
audited_options[:except] = Array.wrap(audited_options[:except]).map(&:to_s)
|
376
|
+
max_audits = audited_options[:max_audits] || Audited.max_audits
|
377
|
+
audited_options[:max_audits] = Integer(max_audits).abs if max_audits
|
378
|
+
end
|
379
|
+
|
380
|
+
def calculate_non_audited_columns
|
381
|
+
if audited_options[:only].present?
|
382
|
+
(column_names | default_ignored_attributes) - audited_options[:only]
|
383
|
+
elsif audited_options[:except].present?
|
384
|
+
default_ignored_attributes | audited_options[:except]
|
385
|
+
else
|
386
|
+
default_ignored_attributes
|
387
|
+
end
|
301
388
|
end
|
302
389
|
end
|
303
390
|
end
|
@@ -41,12 +41,12 @@ module Audited
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def only(*fields)
|
44
|
-
@options[:only] = fields.flatten
|
44
|
+
@options[:only] = fields.flatten.map(&:to_s)
|
45
45
|
self
|
46
46
|
end
|
47
47
|
|
48
48
|
def except(*fields)
|
49
|
-
@options[:except] = fields.flatten
|
49
|
+
@options[:except] = fields.flatten.map(&:to_s)
|
50
50
|
self
|
51
51
|
end
|
52
52
|
|
@@ -56,16 +56,13 @@ module Audited
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def on(*actions)
|
59
|
-
@options[:on] = actions.flatten
|
59
|
+
@options[:on] = actions.flatten.map(&:to_sym)
|
60
60
|
self
|
61
61
|
end
|
62
62
|
|
63
63
|
def matches?(subject)
|
64
64
|
@subject = subject
|
65
|
-
auditing_enabled? &&
|
66
|
-
associated_with_model? &&
|
67
|
-
records_changes_to_specified_fields? &&
|
68
|
-
comment_required_valid?
|
65
|
+
auditing_enabled? && required_checks_for_options_satisfied?
|
69
66
|
end
|
70
67
|
|
71
68
|
def failure_message
|
@@ -109,31 +106,83 @@ module Audited
|
|
109
106
|
end
|
110
107
|
|
111
108
|
def records_changes_to_specified_fields?
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
109
|
+
ignored_fields = build_ignored_fields_from_options
|
110
|
+
|
111
|
+
expects "non audited columns (#{model_class.non_audited_columns.inspect}) to match (#{ignored_fields})"
|
112
|
+
model_class.non_audited_columns.to_set == ignored_fields.to_set
|
113
|
+
end
|
114
|
+
|
115
|
+
def comment_required_valid?
|
116
|
+
expects "to require audit_comment before #{model_class.audited_options[:on]} when comment required"
|
117
|
+
validate_callbacks_include_presence_of_comment? && destroy_callbacks_include_comment_required?
|
118
|
+
end
|
119
119
|
|
120
|
-
|
121
|
-
|
120
|
+
def only_audit_on_designated_callbacks?
|
121
|
+
{
|
122
|
+
create: [:after, :audit_create],
|
123
|
+
update: [:before, :audit_update],
|
124
|
+
destroy: [:before, :audit_destroy]
|
125
|
+
}.map do |(action, kind_callback)|
|
126
|
+
kind, callback = kind_callback
|
127
|
+
callbacks_for(action, kind: kind).include?(callback) if @options[:on].include?(action)
|
128
|
+
end.compact.all?
|
129
|
+
end
|
130
|
+
|
131
|
+
def validate_callbacks_include_presence_of_comment?
|
132
|
+
if @options[:comment_required] && audited_on_create_or_update?
|
133
|
+
callbacks_for(:validate).include?(:presence_of_audit_comment)
|
122
134
|
else
|
123
135
|
true
|
124
136
|
end
|
125
137
|
end
|
126
138
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
139
|
+
def audited_on_create_or_update?
|
140
|
+
model_class.audited_options[:on].include?(:create) || model_class.audited_options[:on].include?(:update)
|
141
|
+
end
|
130
142
|
|
131
|
-
|
132
|
-
|
143
|
+
def destroy_callbacks_include_comment_required?
|
144
|
+
if @options[:comment_required] && model_class.audited_options[:on].include?(:destroy)
|
145
|
+
callbacks_for(:destroy).include?(:require_comment)
|
133
146
|
else
|
134
147
|
true
|
135
148
|
end
|
136
149
|
end
|
150
|
+
|
151
|
+
def requires_comment_before_callbacks?
|
152
|
+
[:create, :update, :destroy].map do |action|
|
153
|
+
if @options[:comment_required] && model_class.audited_options[:on].include?(action)
|
154
|
+
callbacks_for(action).include?(:require_comment)
|
155
|
+
end
|
156
|
+
end.compact.all?
|
157
|
+
end
|
158
|
+
|
159
|
+
def callbacks_for(action, kind: :before)
|
160
|
+
model_class.send("_#{action}_callbacks").select { |cb| cb.kind == kind }.map(&:filter)
|
161
|
+
end
|
162
|
+
|
163
|
+
def build_ignored_fields_from_options
|
164
|
+
default_ignored_attributes = model_class.default_ignored_attributes
|
165
|
+
|
166
|
+
if @options[:only].present?
|
167
|
+
(default_ignored_attributes | model_class.column_names) - @options[:only]
|
168
|
+
elsif @options[:except].present?
|
169
|
+
default_ignored_attributes | @options[:except]
|
170
|
+
else
|
171
|
+
default_ignored_attributes
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def required_checks_for_options_satisfied?
|
176
|
+
{
|
177
|
+
only: :records_changes_to_specified_fields?,
|
178
|
+
except: :records_changes_to_specified_fields?,
|
179
|
+
comment_required: :comment_required_valid?,
|
180
|
+
associated_with: :associated_with_model?,
|
181
|
+
on: :only_audit_on_designated_callbacks?
|
182
|
+
}.map do |(option, check)|
|
183
|
+
send(check) if @options[option].present?
|
184
|
+
end.compact.all?
|
185
|
+
end
|
137
186
|
end
|
138
187
|
|
139
188
|
class AssociatedAuditMatcher # :nodoc:
|
data/lib/audited/version.rb
CHANGED
@@ -17,6 +17,114 @@ describe Audited::Auditor do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
context "should be configurable which conditions are audited" do
|
21
|
+
subject { ConditionalCompany.new.send(:auditing_enabled) }
|
22
|
+
|
23
|
+
context "when passing a method name" do
|
24
|
+
before do
|
25
|
+
class ConditionalCompany < ::ActiveRecord::Base
|
26
|
+
self.table_name = 'companies'
|
27
|
+
|
28
|
+
audited if: :public?
|
29
|
+
|
30
|
+
def public?; end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when conditions are true" do
|
35
|
+
before { allow_any_instance_of(ConditionalCompany).to receive(:public?).and_return(true) }
|
36
|
+
it { is_expected.to be_truthy }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when conditions are false" do
|
40
|
+
before { allow_any_instance_of(ConditionalCompany).to receive(:public?).and_return(false) }
|
41
|
+
it { is_expected.to be_falsey }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when passing a Proc" do
|
46
|
+
context "when conditions are true" do
|
47
|
+
before do
|
48
|
+
class InclusiveCompany < ::ActiveRecord::Base
|
49
|
+
self.table_name = 'companies'
|
50
|
+
audited if: Proc.new { true }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
subject { InclusiveCompany.new.send(:auditing_enabled) }
|
55
|
+
|
56
|
+
it { is_expected.to be_truthy }
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when conditions are false" do
|
60
|
+
before do
|
61
|
+
class ExclusiveCompany < ::ActiveRecord::Base
|
62
|
+
self.table_name = 'companies'
|
63
|
+
audited if: Proc.new { false }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
subject { ExclusiveCompany.new.send(:auditing_enabled) }
|
67
|
+
it { is_expected.to be_falsey }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "should be configurable which conditions aren't audited" do
|
73
|
+
context "when using a method name" do
|
74
|
+
before do
|
75
|
+
class ExclusionaryCompany < ::ActiveRecord::Base
|
76
|
+
self.table_name = 'companies'
|
77
|
+
|
78
|
+
audited unless: :non_profit?
|
79
|
+
|
80
|
+
def non_profit?; end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
subject { ExclusionaryCompany.new.send(:auditing_enabled) }
|
85
|
+
|
86
|
+
context "when conditions are true" do
|
87
|
+
before { allow_any_instance_of(ExclusionaryCompany).to receive(:non_profit?).and_return(true) }
|
88
|
+
it { is_expected.to be_falsey }
|
89
|
+
end
|
90
|
+
|
91
|
+
context "when conditions are false" do
|
92
|
+
before { allow_any_instance_of(ExclusionaryCompany).to receive(:non_profit?).and_return(false) }
|
93
|
+
it { is_expected.to be_truthy }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when using a proc" do
|
98
|
+
context "when conditions are true" do
|
99
|
+
before do
|
100
|
+
class ExclusionaryCompany < ::ActiveRecord::Base
|
101
|
+
self.table_name = 'companies'
|
102
|
+
audited unless: Proc.new { |c| c.exclusive? }
|
103
|
+
|
104
|
+
def exclusive?
|
105
|
+
true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
subject { ExclusionaryCompany.new.send(:auditing_enabled) }
|
111
|
+
it { is_expected.to be_falsey }
|
112
|
+
end
|
113
|
+
|
114
|
+
context "when conditions are false" do
|
115
|
+
before do
|
116
|
+
class InclusiveCompany < ::ActiveRecord::Base
|
117
|
+
self.table_name = 'companies'
|
118
|
+
audited unless: Proc.new { false }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
subject { InclusiveCompany.new.send(:auditing_enabled) }
|
123
|
+
it { is_expected.to be_truthy }
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
20
128
|
it "should be configurable which attributes are not audited via ignored_attributes" do
|
21
129
|
Audited.ignored_attributes = ['delta', 'top_secret', 'created_at']
|
22
130
|
class Secret < ::ActiveRecord::Base
|
@@ -36,9 +144,14 @@ describe Audited::Auditor do
|
|
36
144
|
end
|
37
145
|
|
38
146
|
it "should not save non-audited columns" do
|
39
|
-
|
147
|
+
previous = Models::ActiveRecord::User.non_audited_columns
|
148
|
+
begin
|
149
|
+
Models::ActiveRecord::User.non_audited_columns += [:favourite_device]
|
40
150
|
|
41
|
-
|
151
|
+
expect(create_user.audits.first.audited_changes.keys.any? { |col| ['favourite_device', 'created_at', 'updated_at', 'password'].include?( col ) }).to eq(false)
|
152
|
+
ensure
|
153
|
+
Models::ActiveRecord::User.non_audited_columns = previous
|
154
|
+
end
|
42
155
|
end
|
43
156
|
|
44
157
|
it "should not save other columns than specified in 'only' option" do
|
@@ -84,11 +197,11 @@ describe Audited::Auditor do
|
|
84
197
|
let(:migrations_path) { SPEC_ROOT.join("support/active_record/postgres") }
|
85
198
|
|
86
199
|
after do
|
87
|
-
|
200
|
+
run_migrations(:down, migrations_path)
|
88
201
|
end
|
89
202
|
|
90
203
|
it "should work if column type is 'json'" do
|
91
|
-
|
204
|
+
run_migrations(:up, migrations_path, 1)
|
92
205
|
Audited::Audit.reset_column_information
|
93
206
|
expect(Audited::Audit.columns_hash["audited_changes"].sql_type).to eq("json")
|
94
207
|
|
@@ -99,7 +212,7 @@ describe Audited::Auditor do
|
|
99
212
|
end
|
100
213
|
|
101
214
|
it "should work if column type is 'jsonb'" do
|
102
|
-
|
215
|
+
run_migrations(:up, migrations_path, 2)
|
103
216
|
Audited::Audit.reset_column_information
|
104
217
|
expect(Audited::Audit.columns_hash["audited_changes"].sql_type).to eq("jsonb")
|
105
218
|
|
@@ -329,6 +442,77 @@ describe Audited::Auditor do
|
|
329
442
|
end
|
330
443
|
end
|
331
444
|
|
445
|
+
describe "max_audits" do
|
446
|
+
it "should respect global setting" do
|
447
|
+
stub_global_max_audits(10) do
|
448
|
+
expect(Models::ActiveRecord::User.audited_options[:max_audits]).to eq(10)
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
it "should respect per model setting" do
|
453
|
+
stub_global_max_audits(10) do
|
454
|
+
expect(Models::ActiveRecord::MaxAuditsUser.audited_options[:max_audits]).to eq(5)
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
it "should delete old audits when keeped amount exceeded" do
|
459
|
+
stub_global_max_audits(2) do
|
460
|
+
user = create_versions(2)
|
461
|
+
user.update(name: 'John')
|
462
|
+
expect(user.audits.pluck(:version)).to eq([2, 3])
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
it "should not delete old audits when keeped amount not exceeded" do
|
467
|
+
stub_global_max_audits(3) do
|
468
|
+
user = create_versions(2)
|
469
|
+
user.update(name: 'John')
|
470
|
+
expect(user.audits.pluck(:version)).to eq([1, 2, 3])
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
it "should delete old extra audits after introducing limit" do
|
475
|
+
stub_global_max_audits(nil) do
|
476
|
+
user = Models::ActiveRecord::User.create!(name: 'Brandon', username: 'brandon')
|
477
|
+
user.update_attributes(name: 'Foobar')
|
478
|
+
user.update_attributes(name: 'Awesome', username: 'keepers')
|
479
|
+
user.update_attributes(activated: true)
|
480
|
+
|
481
|
+
Audited.max_audits = 3
|
482
|
+
Models::ActiveRecord::User.send(:normalize_audited_options)
|
483
|
+
user.update_attributes(favourite_device: 'Android Phone')
|
484
|
+
audits = user.audits
|
485
|
+
|
486
|
+
expect(audits.count).to eq(3)
|
487
|
+
expect(audits[0].audited_changes).to include({'name' => ['Foobar', 'Awesome'], 'username' => ['brandon', 'keepers']})
|
488
|
+
expect(audits[1].audited_changes).to eq({'activated' => [nil, true]})
|
489
|
+
expect(audits[2].audited_changes).to eq({'favourite_device' => [nil, 'Android Phone']})
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
it "should add comment line for combined audit" do
|
494
|
+
stub_global_max_audits(2) do
|
495
|
+
user = Models::ActiveRecord::User.create!(name: 'Foobar 1')
|
496
|
+
user.update(name: 'Foobar 2', audit_comment: 'First audit comment')
|
497
|
+
user.update(name: 'Foobar 3', audit_comment: 'Second audit comment')
|
498
|
+
expect(user.audits.first.comment).to match(/First audit comment.+is the result of multiple/m)
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
def stub_global_max_audits(max_audits)
|
503
|
+
previous_max_audits = Audited.max_audits
|
504
|
+
previous_user_audited_options = Models::ActiveRecord::User.audited_options.dup
|
505
|
+
begin
|
506
|
+
Audited.max_audits = max_audits
|
507
|
+
Models::ActiveRecord::User.send(:normalize_audited_options) # reloads audited_options
|
508
|
+
yield
|
509
|
+
ensure
|
510
|
+
Audited.max_audits = previous_max_audits
|
511
|
+
Models::ActiveRecord::User.audited_options = previous_user_audited_options
|
512
|
+
end
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
332
516
|
describe "revisions" do
|
333
517
|
let( :user ) { create_versions }
|
334
518
|
|
@@ -544,28 +728,44 @@ describe Audited::Auditor do
|
|
544
728
|
describe "comment required" do
|
545
729
|
|
546
730
|
describe "on create" do
|
547
|
-
it "should not validate when audit_comment is not supplied" do
|
548
|
-
expect(Models::ActiveRecord::CommentRequiredUser.new).not_to be_valid
|
731
|
+
it "should not validate when audit_comment is not supplied when initialized" do
|
732
|
+
expect(Models::ActiveRecord::CommentRequiredUser.new(name: 'Foo')).not_to be_valid
|
733
|
+
end
|
734
|
+
|
735
|
+
it "should not validate when audit_comment is not supplied trying to create" do
|
736
|
+
expect(Models::ActiveRecord::CommentRequiredUser.create(name: 'Foo')).not_to be_valid
|
549
737
|
end
|
550
738
|
|
551
739
|
it "should validate when audit_comment is supplied" do
|
552
|
-
expect(Models::ActiveRecord::CommentRequiredUser.
|
740
|
+
expect(Models::ActiveRecord::CommentRequiredUser.create(name: 'Foo', audit_comment: 'Create')).to be_valid
|
741
|
+
end
|
742
|
+
|
743
|
+
it "should validate when audit_comment is not supplied, and creating is not being audited" do
|
744
|
+
expect(Models::ActiveRecord::OnUpdateCommentRequiredUser.create(name: 'Foo')).to be_valid
|
745
|
+
expect(Models::ActiveRecord::OnDestroyCommentRequiredUser.create(name: 'Foo')).to be_valid
|
553
746
|
end
|
554
747
|
|
555
748
|
it "should validate when audit_comment is not supplied, and auditing is disabled" do
|
556
749
|
Models::ActiveRecord::CommentRequiredUser.disable_auditing
|
557
|
-
expect(Models::ActiveRecord::CommentRequiredUser.
|
750
|
+
expect(Models::ActiveRecord::CommentRequiredUser.create(name: 'Foo')).to be_valid
|
558
751
|
Models::ActiveRecord::CommentRequiredUser.enable_auditing
|
559
752
|
end
|
560
753
|
end
|
561
754
|
|
562
755
|
describe "on update" do
|
563
756
|
let( :user ) { Models::ActiveRecord::CommentRequiredUser.create!( audit_comment: 'Create' ) }
|
757
|
+
let( :on_create_user ) { Models::ActiveRecord::OnDestroyCommentRequiredUser.create }
|
758
|
+
let( :on_destroy_user ) { Models::ActiveRecord::OnDestroyCommentRequiredUser.create }
|
564
759
|
|
565
760
|
it "should not validate when audit_comment is not supplied" do
|
566
761
|
expect(user.update_attributes(name: 'Test')).to eq(false)
|
567
762
|
end
|
568
763
|
|
764
|
+
it "should validate when audit_comment is not supplied, and updating is not being audited" do
|
765
|
+
expect(on_create_user.update_attributes(name: 'Test')).to eq(true)
|
766
|
+
expect(on_destroy_user.update_attributes(name: 'Test')).to eq(true)
|
767
|
+
end
|
768
|
+
|
569
769
|
it "should validate when audit_comment is supplied" do
|
570
770
|
expect(user.update_attributes(name: 'Test', audit_comment: 'Update')).to eq(true)
|
571
771
|
end
|
@@ -579,6 +779,8 @@ describe Audited::Auditor do
|
|
579
779
|
|
580
780
|
describe "on destroy" do
|
581
781
|
let( :user ) { Models::ActiveRecord::CommentRequiredUser.create!( audit_comment: 'Create' )}
|
782
|
+
let( :on_create_user ) { Models::ActiveRecord::OnCreateCommentRequiredUser.create!( audit_comment: 'Create' ) }
|
783
|
+
let( :on_update_user ) { Models::ActiveRecord::OnUpdateCommentRequiredUser.create }
|
582
784
|
|
583
785
|
it "should not validate when audit_comment is not supplied" do
|
584
786
|
expect(user.destroy).to eq(false)
|
@@ -589,6 +791,11 @@ describe Audited::Auditor do
|
|
589
791
|
expect(user.destroy).to eq(user)
|
590
792
|
end
|
591
793
|
|
794
|
+
it "should validate when audit_comment is not supplied, and destroying is not being audited" do
|
795
|
+
expect(on_create_user.destroy).to eq(on_create_user)
|
796
|
+
expect(on_update_user.destroy).to eq(on_update_user)
|
797
|
+
end
|
798
|
+
|
592
799
|
it "should validate when audit_comment is not supplied, and auditing is disabled" do
|
593
800
|
Models::ActiveRecord::CommentRequiredUser.disable_auditing
|
594
801
|
expect(user.destroy).to eq(user)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Models::ActiveRecord::UserExceptPassword do
|
4
|
+
let(:non_audited_columns) { subject.class.non_audited_columns }
|
5
|
+
|
6
|
+
it { should_not be_audited.only(non_audited_columns) }
|
7
|
+
it { should be_audited.except(:password) }
|
8
|
+
it { should_not be_audited.requires_comment }
|
9
|
+
it { should be_audited.on(:create, :update, :destroy) }
|
10
|
+
# test chaining
|
11
|
+
it { should be_audited.except(:password).on(:create, :update, :destroy) }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe Models::ActiveRecord::UserOnlyPassword do
|
15
|
+
let(:audited_columns) { subject.class.audited_columns }
|
16
|
+
|
17
|
+
it { should be_audited.only(:password) }
|
18
|
+
it { should_not be_audited.except(audited_columns) }
|
19
|
+
it { should_not be_audited.requires_comment }
|
20
|
+
it { should be_audited.on(:create, :update, :destroy) }
|
21
|
+
it { should be_audited.only(:password).on(:create, :update, :destroy) }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Models::ActiveRecord::CommentRequiredUser do
|
25
|
+
let(:audited_columns) { subject.class.audited_columns }
|
26
|
+
let(:non_audited_columns) { subject.class.non_audited_columns }
|
27
|
+
|
28
|
+
it { should_not be_audited.only(non_audited_columns) }
|
29
|
+
it { should_not be_audited.except(audited_columns) }
|
30
|
+
it { should be_audited.requires_comment }
|
31
|
+
it { should be_audited.on(:create, :update, :destroy) }
|
32
|
+
it { should be_audited.requires_comment.on(:create, :update, :destroy) }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe Models::ActiveRecord::OnCreateCommentRequiredUser do
|
36
|
+
let(:audited_columns) { subject.class.audited_columns }
|
37
|
+
let(:non_audited_columns) { subject.class.non_audited_columns }
|
38
|
+
|
39
|
+
it { should_not be_audited.only(non_audited_columns) }
|
40
|
+
it { should_not be_audited.except(audited_columns) }
|
41
|
+
it { should be_audited.requires_comment }
|
42
|
+
it { should be_audited.on(:create) }
|
43
|
+
it { should_not be_audited.on(:update, :destroy) }
|
44
|
+
it { should be_audited.requires_comment.on(:create) }
|
45
|
+
end
|
46
|
+
|
47
|
+
describe Models::ActiveRecord::OnUpdateCommentRequiredUser do
|
48
|
+
let(:audited_columns) { subject.class.audited_columns }
|
49
|
+
let(:non_audited_columns) { subject.class.non_audited_columns }
|
50
|
+
|
51
|
+
it { should_not be_audited.only(non_audited_columns) }
|
52
|
+
it { should_not be_audited.except(audited_columns) }
|
53
|
+
it { should be_audited.requires_comment }
|
54
|
+
it { should be_audited.on(:update) }
|
55
|
+
it { should_not be_audited.on(:create, :destroy) }
|
56
|
+
it { should be_audited.requires_comment.on(:update) }
|
57
|
+
end
|
58
|
+
|
59
|
+
describe Models::ActiveRecord::OnDestroyCommentRequiredUser do
|
60
|
+
let(:audited_columns) { subject.class.audited_columns }
|
61
|
+
let(:non_audited_columns) { subject.class.non_audited_columns }
|
62
|
+
|
63
|
+
it { should_not be_audited.only(non_audited_columns) }
|
64
|
+
it { should_not be_audited.except(audited_columns) }
|
65
|
+
it { should be_audited.requires_comment }
|
66
|
+
it { should be_audited.on(:destroy) }
|
67
|
+
it { should_not be_audited.on(:create, :update) }
|
68
|
+
it { should be_audited.requires_comment.on(:destroy) }
|
69
|
+
end
|
@@ -8,8 +8,8 @@ module AuditedSpecHelpers
|
|
8
8
|
Models::ActiveRecord::User.new({name: 'darth', username: 'darth', password: 'noooooooo'}.merge(attrs))
|
9
9
|
end
|
10
10
|
|
11
|
-
def create_versions(n = 2)
|
12
|
-
Models::ActiveRecord::User.create(name: 'Foobar 1').tap do |u|
|
11
|
+
def create_versions(n = 2, attrs = {})
|
12
|
+
Models::ActiveRecord::User.create(name: 'Foobar 1', **attrs).tap do |u|
|
13
13
|
(n - 1).times do |i|
|
14
14
|
u.update_attribute :name, "Foobar #{i + 2}"
|
15
15
|
end
|
@@ -17,4 +17,16 @@ module AuditedSpecHelpers
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
def run_migrations(direction, migrations_paths, target_version = nil)
|
21
|
+
if rails_below?('5.2.0.rc1')
|
22
|
+
ActiveRecord::Migrator.send(direction, migrations_paths, target_version)
|
23
|
+
else
|
24
|
+
ActiveRecord::MigrationContext.new(migrations_paths).send(direction, target_version)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def rails_below?(rails_version)
|
29
|
+
Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new(rails_version)
|
30
|
+
end
|
31
|
+
|
20
32
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,7 +4,7 @@ require File.expand_path('../schema', __FILE__)
|
|
4
4
|
module Models
|
5
5
|
module ActiveRecord
|
6
6
|
class User < ::ActiveRecord::Base
|
7
|
-
audited
|
7
|
+
audited except: :password
|
8
8
|
attribute :non_column_attr if Rails.version >= '5.1'
|
9
9
|
attr_protected :logins if respond_to?(:attr_protected)
|
10
10
|
|
@@ -13,10 +13,15 @@ module Models
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
class UserExceptPassword < ::ActiveRecord::Base
|
17
|
+
self.table_name = :users
|
18
|
+
audited except: :password
|
19
|
+
end
|
20
|
+
|
16
21
|
class UserOnlyPassword < ::ActiveRecord::Base
|
17
22
|
self.table_name = :users
|
18
23
|
attribute :non_column_attr if Rails.version >= '5.1'
|
19
|
-
audited
|
24
|
+
audited only: :password
|
20
25
|
end
|
21
26
|
|
22
27
|
class CommentRequiredUser < ::ActiveRecord::Base
|
@@ -24,6 +29,21 @@ module Models
|
|
24
29
|
audited comment_required: true
|
25
30
|
end
|
26
31
|
|
32
|
+
class OnCreateCommentRequiredUser < ::ActiveRecord::Base
|
33
|
+
self.table_name = :users
|
34
|
+
audited comment_required: true, on: :create
|
35
|
+
end
|
36
|
+
|
37
|
+
class OnUpdateCommentRequiredUser < ::ActiveRecord::Base
|
38
|
+
self.table_name = :users
|
39
|
+
audited comment_required: true, on: :update
|
40
|
+
end
|
41
|
+
|
42
|
+
class OnDestroyCommentRequiredUser < ::ActiveRecord::Base
|
43
|
+
self.table_name = :users
|
44
|
+
audited comment_required: true, on: :destroy
|
45
|
+
end
|
46
|
+
|
27
47
|
class AccessibleAfterDeclarationUser < ::ActiveRecord::Base
|
28
48
|
self.table_name = :users
|
29
49
|
audited
|
@@ -38,7 +58,7 @@ module Models
|
|
38
58
|
|
39
59
|
class NoAttributeProtectionUser < ::ActiveRecord::Base
|
40
60
|
self.table_name = :users
|
41
|
-
audited
|
61
|
+
audited
|
42
62
|
end
|
43
63
|
|
44
64
|
class UserWithAfterAudit < ::ActiveRecord::Base
|
@@ -57,6 +77,11 @@ module Models
|
|
57
77
|
end
|
58
78
|
end
|
59
79
|
|
80
|
+
class MaxAuditsUser < ::ActiveRecord::Base
|
81
|
+
self.table_name = :users
|
82
|
+
audited max_audits: 5
|
83
|
+
end
|
84
|
+
|
60
85
|
class Company < ::ActiveRecord::Base
|
61
86
|
audited
|
62
87
|
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.7.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: 2018-
|
16
|
+
date: 2018-03-14 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: activerecord
|
@@ -168,6 +168,7 @@ files:
|
|
168
168
|
- lib/generators/audited/upgrade_generator.rb
|
169
169
|
- spec/audited/audit_spec.rb
|
170
170
|
- spec/audited/auditor_spec.rb
|
171
|
+
- spec/audited/rspec_matchers_spec.rb
|
171
172
|
- spec/audited/sweeper_spec.rb
|
172
173
|
- spec/audited_spec_helpers.rb
|
173
174
|
- spec/rails_app/config/application.rb
|