audited 4.9.0 → 5.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/buildlight.yml +15 -0
  3. data/.github/workflows/ci.yml +145 -0
  4. data/.github/workflows/publish_gem.yml +28 -0
  5. data/.standard.yml +5 -0
  6. data/Appraisals +35 -16
  7. data/CHANGELOG.md +162 -1
  8. data/Gemfile +1 -1
  9. data/README.md +73 -18
  10. data/Rakefile +5 -7
  11. data/gemfiles/rails50.gemfile +2 -0
  12. data/gemfiles/rails51.gemfile +2 -0
  13. data/gemfiles/rails52.gemfile +3 -1
  14. data/gemfiles/rails60.gemfile +1 -1
  15. data/gemfiles/rails61.gemfile +10 -0
  16. data/gemfiles/rails70.gemfile +10 -0
  17. data/gemfiles/rails71.gemfile +10 -0
  18. data/lib/audited/audit.rb +41 -29
  19. data/lib/audited/auditor.rb +134 -56
  20. data/lib/audited/railtie.rb +16 -0
  21. data/lib/audited/rspec_matchers.rb +5 -3
  22. data/lib/audited/sweeper.rb +3 -10
  23. data/lib/audited/version.rb +3 -1
  24. data/lib/audited-rspec.rb +3 -1
  25. data/lib/audited.rb +31 -9
  26. data/lib/generators/audited/install_generator.rb +9 -7
  27. data/lib/generators/audited/migration.rb +12 -2
  28. data/lib/generators/audited/migration_helper.rb +3 -1
  29. data/lib/generators/audited/templates/add_association_to_audits.rb +2 -0
  30. data/lib/generators/audited/templates/add_comment_to_audits.rb +2 -0
  31. data/lib/generators/audited/templates/add_remote_address_to_audits.rb +2 -0
  32. data/lib/generators/audited/templates/add_request_uuid_to_audits.rb +2 -0
  33. data/lib/generators/audited/templates/add_version_to_auditable_index.rb +2 -0
  34. data/lib/generators/audited/templates/install.rb +2 -0
  35. data/lib/generators/audited/templates/rename_association_to_associated.rb +2 -0
  36. data/lib/generators/audited/templates/rename_changes_to_audited_changes.rb +2 -0
  37. data/lib/generators/audited/templates/rename_parent_to_association.rb +2 -0
  38. data/lib/generators/audited/templates/revert_polymorphic_indexes_order.rb +2 -0
  39. data/lib/generators/audited/upgrade_generator.rb +16 -14
  40. data/spec/audited/audit_spec.rb +70 -48
  41. data/spec/audited/auditor_spec.rb +477 -246
  42. data/spec/audited/sweeper_spec.rb +19 -18
  43. data/spec/audited_spec.rb +14 -0
  44. data/spec/audited_spec_helpers.rb +11 -7
  45. data/spec/rails_app/app/assets/config/manifest.js +2 -0
  46. data/spec/rails_app/config/application.rb +32 -3
  47. data/spec/rails_app/config/database.yml +3 -2
  48. data/spec/rails_app/config/environment.rb +1 -1
  49. data/spec/rails_app/config/environments/test.rb +10 -5
  50. data/spec/rails_app/config/initializers/secret_token.rb +2 -2
  51. data/spec/spec_helper.rb +14 -14
  52. data/spec/support/active_record/models.rb +62 -13
  53. data/spec/support/active_record/postgres/1_change_audited_changes_type_to_json.rb +1 -2
  54. data/spec/support/active_record/postgres/2_change_audited_changes_type_to_jsonb.rb +1 -2
  55. data/spec/support/active_record/schema.rb +26 -19
  56. data/test/db/version_1.rb +2 -2
  57. data/test/db/version_2.rb +2 -2
  58. data/test/db/version_3.rb +2 -3
  59. data/test/db/version_4.rb +2 -3
  60. data/test/db/version_5.rb +0 -1
  61. data/test/db/version_6.rb +1 -1
  62. data/test/install_generator_test.rb +18 -19
  63. data/test/test_helper.rb +5 -5
  64. data/test/upgrade_generator_test.rb +13 -18
  65. metadata +49 -31
  66. data/.rubocop.yml +0 -25
  67. data/.travis.yml +0 -58
  68. data/gemfiles/rails42.gemfile +0 -11
  69. data/spec/rails_app/app/controllers/application_controller.rb +0 -2
  70. data/spec/rails_app/config/environments/development.rb +0 -21
  71. data/spec/rails_app/config/environments/production.rb +0 -35
@@ -1,19 +1,82 @@
1
1
  require "spec_helper"
2
2
 
3
- SingleCov.covered! uncovered: 13 # not testing proxy_respond_to? hack / 2 methods / deprecation of `version`
3
+ # not testing proxy_respond_to? hack / 2 methods / deprecation of `version`
4
+ # also, an additional 6 around `after_touch` for Versions before 6.
5
+ uncovered = (ActiveRecord::VERSION::MAJOR < 6) ? 15 : 9
6
+ SingleCov.covered! uncovered: uncovered
4
7
 
5
- describe Audited::Auditor do
8
+ class ConditionalPrivateCompany < ::ActiveRecord::Base
9
+ self.table_name = "companies"
10
+
11
+ audited if: :foo?
12
+
13
+ private def foo?
14
+ true
15
+ end
16
+ end
17
+
18
+ class ConditionalCompany < ::ActiveRecord::Base
19
+ self.table_name = "companies"
20
+
21
+ audited if: :public?
22
+
23
+ def public?
24
+ end
25
+ end
26
+
27
+ class ExclusiveCompany < ::ActiveRecord::Base
28
+ self.table_name = "companies"
29
+ audited if: proc { false }
30
+ end
31
+
32
+ class ExclusionaryCompany < ::ActiveRecord::Base
33
+ self.table_name = "companies"
34
+
35
+ audited unless: :non_profit?
36
+
37
+ def non_profit?
38
+ end
39
+ end
40
+
41
+ class ExclusionaryCompany2 < ::ActiveRecord::Base
42
+ self.table_name = "companies"
43
+ audited unless: proc { |c| c.exclusive? }
44
+
45
+ def exclusive?
46
+ true
47
+ end
48
+ end
6
49
 
50
+ class InclusiveCompany < ::ActiveRecord::Base
51
+ self.table_name = "companies"
52
+ audited if: proc { true }
53
+ end
54
+
55
+ class InclusiveCompany2 < ::ActiveRecord::Base
56
+ self.table_name = "companies"
57
+ audited unless: proc { false }
58
+ end
59
+
60
+ class Secret < ::ActiveRecord::Base
61
+ audited
62
+ end
63
+
64
+ class Secret2 < ::ActiveRecord::Base
65
+ audited
66
+ self.non_audited_columns = ["delta", "top_secret", "created_at"]
67
+ end
68
+
69
+ describe Audited::Auditor do
7
70
  describe "configuration" do
8
71
  it "should include instance methods" do
9
- expect(Models::ActiveRecord::User.new).to be_a_kind_of( Audited::Auditor::AuditedInstanceMethods)
72
+ expect(Models::ActiveRecord::User.new).to be_a_kind_of(Audited::Auditor::AuditedInstanceMethods)
10
73
  end
11
74
 
12
75
  it "should include class methods" do
13
- expect(Models::ActiveRecord::User).to be_a_kind_of( Audited::Auditor::AuditedClassMethods )
76
+ expect(Models::ActiveRecord::User).to be_a_kind_of(Audited::Auditor::AuditedClassMethods)
14
77
  end
15
78
 
16
- ['created_at', 'updated_at', 'created_on', 'updated_on', 'lock_version', 'id', 'password'].each do |column|
79
+ ["created_at", "updated_at", "created_on", "updated_on", "lock_version", "id", "password"].each do |column|
17
80
  it "should not audit #{column}" do
18
81
  expect(Models::ActiveRecord::User.non_audited_columns).to include(column)
19
82
  end
@@ -25,64 +88,29 @@ describe Audited::Auditor do
25
88
  context "when condition method is private" do
26
89
  subject { ConditionalPrivateCompany.new.send(:auditing_enabled) }
27
90
 
28
- before do
29
- class ConditionalPrivateCompany < ::ActiveRecord::Base
30
- self.table_name = 'companies'
31
-
32
- audited if: :foo?
33
-
34
- private def foo?
35
- true
36
- end
37
- end
38
- end
39
-
40
91
  it { is_expected.to be_truthy }
41
92
  end
42
93
 
43
94
  context "when passing a method name" do
44
- before do
45
- class ConditionalCompany < ::ActiveRecord::Base
46
- self.table_name = 'companies'
47
-
48
- audited if: :public?
49
-
50
- def public?; end
51
- end
52
- end
53
-
54
95
  context "when conditions are true" do
55
96
  before { allow_any_instance_of(ConditionalCompany).to receive(:public?).and_return(true) }
56
- it { is_expected.to be_truthy }
97
+ it { is_expected.to be_truthy }
57
98
  end
58
99
 
59
100
  context "when conditions are false" do
60
101
  before { allow_any_instance_of(ConditionalCompany).to receive(:public?).and_return(false) }
61
- it { is_expected.to be_falsey }
102
+ it { is_expected.to be_falsey }
62
103
  end
63
104
  end
64
105
 
65
106
  context "when passing a Proc" do
66
107
  context "when conditions are true" do
67
- before do
68
- class InclusiveCompany < ::ActiveRecord::Base
69
- self.table_name = 'companies'
70
- audited if: Proc.new { true }
71
- end
72
- end
73
-
74
108
  subject { InclusiveCompany.new.send(:auditing_enabled) }
75
109
 
76
110
  it { is_expected.to be_truthy }
77
111
  end
78
112
 
79
113
  context "when conditions are false" do
80
- before do
81
- class ExclusiveCompany < ::ActiveRecord::Base
82
- self.table_name = 'companies'
83
- audited if: Proc.new { false }
84
- end
85
- end
86
114
  subject { ExclusiveCompany.new.send(:auditing_enabled) }
87
115
  it { is_expected.to be_falsey }
88
116
  end
@@ -91,76 +119,40 @@ describe Audited::Auditor do
91
119
 
92
120
  context "should be configurable which conditions aren't audited" do
93
121
  context "when using a method name" do
94
- before do
95
- class ExclusionaryCompany < ::ActiveRecord::Base
96
- self.table_name = 'companies'
97
-
98
- audited unless: :non_profit?
99
-
100
- def non_profit?; end
101
- end
102
- end
103
-
104
122
  subject { ExclusionaryCompany.new.send(:auditing_enabled) }
105
123
 
106
124
  context "when conditions are true" do
107
125
  before { allow_any_instance_of(ExclusionaryCompany).to receive(:non_profit?).and_return(true) }
108
- it { is_expected.to be_falsey }
126
+ it { is_expected.to be_falsey }
109
127
  end
110
128
 
111
129
  context "when conditions are false" do
112
130
  before { allow_any_instance_of(ExclusionaryCompany).to receive(:non_profit?).and_return(false) }
113
- it { is_expected.to be_truthy }
131
+ it { is_expected.to be_truthy }
114
132
  end
115
133
  end
116
134
 
117
135
  context "when using a proc" do
118
136
  context "when conditions are true" do
119
- before do
120
- class ExclusionaryCompany < ::ActiveRecord::Base
121
- self.table_name = 'companies'
122
- audited unless: Proc.new { |c| c.exclusive? }
123
-
124
- def exclusive?
125
- true
126
- end
127
- end
128
- end
129
-
130
- subject { ExclusionaryCompany.new.send(:auditing_enabled) }
131
- it { is_expected.to be_falsey }
137
+ subject { ExclusionaryCompany2.new.send(:auditing_enabled) }
138
+ it { is_expected.to be_falsey }
132
139
  end
133
140
 
134
141
  context "when conditions are false" do
135
- before do
136
- class InclusiveCompany < ::ActiveRecord::Base
137
- self.table_name = 'companies'
138
- audited unless: Proc.new { false }
139
- end
140
- end
141
-
142
- subject { InclusiveCompany.new.send(:auditing_enabled) }
143
- it { is_expected.to be_truthy }
142
+ subject { InclusiveCompany2.new.send(:auditing_enabled) }
143
+ it { is_expected.to be_truthy }
144
144
  end
145
145
  end
146
146
  end
147
147
 
148
148
  it "should be configurable which attributes are not audited via ignored_attributes" do
149
- Audited.ignored_attributes = ['delta', 'top_secret', 'created_at']
150
- class Secret < ::ActiveRecord::Base
151
- audited
152
- end
149
+ Audited.ignored_attributes = ["delta", "top_secret", "created_at", "updated_at"]
153
150
 
154
- expect(Secret.non_audited_columns).to include('delta', 'top_secret', 'created_at')
151
+ expect(Secret.non_audited_columns).to include("delta", "top_secret", "created_at")
155
152
  end
156
153
 
157
154
  it "should be configurable which attributes are not audited via non_audited_columns=" do
158
- class Secret2 < ::ActiveRecord::Base
159
- audited
160
- self.non_audited_columns = ['delta', 'top_secret', 'created_at']
161
- end
162
-
163
- expect(Secret2.non_audited_columns).to include('delta', 'top_secret', 'created_at')
155
+ expect(Secret2.non_audited_columns).to include("delta", "top_secret", "created_at")
164
156
  end
165
157
 
166
158
  it "should not save non-audited columns" do
@@ -168,7 +160,7 @@ describe Audited::Auditor do
168
160
  begin
169
161
  Models::ActiveRecord::User.non_audited_columns += [:favourite_device]
170
162
 
171
- expect(create_user.audits.first.audited_changes.keys.any? { |col| ['favourite_device', 'created_at', 'updated_at', 'password'].include?( col ) }).to eq(false)
163
+ expect(create_user.audits.first.audited_changes.keys.any? { |col| ["favourite_device", "created_at", "updated_at", "password"].include?(col) }).to eq(false)
172
164
  ensure
173
165
  Models::ActiveRecord::User.non_audited_columns = previous
174
166
  end
@@ -190,7 +182,7 @@ describe Audited::Auditor do
190
182
  user.password = "password"
191
183
  user.non_column_attr = "some value"
192
184
  user.save!
193
- expect(user.audits.last.audited_changes.keys).to eq(%w{password})
185
+ expect(user.audits.last.audited_changes.keys).to eq(%w[password])
194
186
  end
195
187
 
196
188
  it "should save attributes not specified in 'except' option" do
@@ -209,10 +201,80 @@ describe Audited::Auditor do
209
201
  user.password = "password"
210
202
  user.non_column_attr = "some value"
211
203
  user.save!
212
- expect(user.audits.last.audited_changes.keys).to eq(%w{non_column_attr})
204
+ expect(user.audits.last.audited_changes.keys).to eq(%w[non_column_attr])
205
+ end
206
+
207
+ it "should redact columns specified in 'redacted' option" do
208
+ redacted = Audited::Auditor::AuditedInstanceMethods::REDACTED
209
+ user = Models::ActiveRecord::UserRedactedPassword.create(password: "password")
210
+ user.save!
211
+ expect(user.audits.last.audited_changes["password"]).to eq(redacted)
212
+ user.password = "new_password"
213
+ user.save!
214
+ expect(user.audits.last.audited_changes["password"]).to eq([redacted, redacted])
215
+ end
216
+
217
+ it "should redact columns specified in 'redacted' option when there are multiple specified" do
218
+ redacted = Audited::Auditor::AuditedInstanceMethods::REDACTED
219
+ user =
220
+ Models::ActiveRecord::UserMultipleRedactedAttributes.create(
221
+ password: "password"
222
+ )
223
+ user.save!
224
+ expect(user.audits.last.audited_changes["password"]).to eq(redacted)
225
+ # Saving '[REDACTED]' value for 'ssn' even if value wasn't set explicitly when record was created
226
+ expect(user.audits.last.audited_changes["ssn"]).to eq(redacted)
227
+
228
+ user.password = "new_password"
229
+ user.ssn = 987654321
230
+ user.save!
231
+ expect(user.audits.last.audited_changes["password"]).to eq([redacted, redacted])
232
+ expect(user.audits.last.audited_changes["ssn"]).to eq([redacted, redacted])
233
+
234
+ # If we haven't changed any attrs from 'redacted' list, audit should not contain these keys
235
+ user.name = "new name"
236
+ user.save!
237
+ expect(user.audits.last.audited_changes).to have_key("name")
238
+ expect(user.audits.last.audited_changes).not_to have_key("password")
239
+ expect(user.audits.last.audited_changes).not_to have_key("ssn")
240
+ end
241
+
242
+ it "should redact columns in 'redacted' column with custom option" do
243
+ user = Models::ActiveRecord::UserRedactedPasswordCustomRedaction.create(password: "password")
244
+ user.save!
245
+ expect(user.audits.last.audited_changes["password"]).to eq(["My", "Custom", "Value", 7])
246
+ end
247
+
248
+ context "when ignored_default_callbacks is set" do
249
+ before { Audited.ignored_default_callbacks = [:create] }
250
+ after { Audited.ignored_default_callbacks = [] }
251
+
252
+ it "should remove create callback" do
253
+ class DefaultCallback < ::ActiveRecord::Base
254
+ audited
255
+ end
256
+
257
+ expect(DefaultCallback.audited_options[:on]).to eq([:update, :touch, :destroy])
258
+ end
259
+
260
+ it "should keep create callback if specified" do
261
+ class CallbacksSpecified < ::ActiveRecord::Base
262
+ audited on: [:create, :update, :destroy]
263
+ end
264
+
265
+ expect(CallbacksSpecified.audited_options[:on]).to eq([:create, :update, :destroy])
266
+ end
213
267
  end
214
268
 
215
- if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
269
+ if ::ActiveRecord::VERSION::MAJOR >= 7
270
+ it "should filter encrypted attributes" do
271
+ user = Models::ActiveRecord::UserWithEncryptedPassword.create(password: "password")
272
+ user.save
273
+ expect(user.audits.last.audited_changes["password"]).to eq("[FILTERED]")
274
+ end
275
+ end
276
+
277
+ if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
216
278
  describe "'json' and 'jsonb' audited_changes column type" do
217
279
  let(:migrations_path) { SPEC_ROOT.join("support/active_record/postgres") }
218
280
 
@@ -249,16 +311,16 @@ describe Audited::Auditor do
249
311
  it "should allow mass assignment of all unprotected attributes" do
250
312
  yesterday = 1.day.ago
251
313
 
252
- u = Models::ActiveRecord::NoAttributeProtectionUser.new(name: 'name',
253
- username: 'username',
254
- password: 'password',
255
- activated: true,
256
- suspended_at: yesterday,
257
- logins: 2)
314
+ u = Models::ActiveRecord::NoAttributeProtectionUser.new(name: "name",
315
+ username: "username",
316
+ password: "password",
317
+ activated: true,
318
+ suspended_at: yesterday,
319
+ logins: 2)
258
320
 
259
- expect(u.name).to eq('name')
260
- expect(u.username).to eq('username')
261
- expect(u.password).to eq('password')
321
+ expect(u.name).to eq("name")
322
+ expect(u.username).to eq("username")
323
+ expect(u.password).to eq("password")
262
324
  expect(u.activated).to eq(true)
263
325
  expect(u.suspended_at.to_i).to eq(yesterday.to_i)
264
326
  expect(u.logins).to eq(2)
@@ -266,12 +328,12 @@ describe Audited::Auditor do
266
328
  end
267
329
 
268
330
  describe "on create" do
269
- let( :user ) { create_user status: :reliable, audit_comment: "Create" }
331
+ let(:user) { create_user status: :reliable, audit_comment: "Create" }
270
332
 
271
333
  it "should change the audit count" do
272
334
  expect {
273
335
  user
274
- }.to change( Audited::Audit, :count ).by(1)
336
+ }.to change(Audited::Audit, :count).by(1)
275
337
  end
276
338
 
277
339
  it "should create associated audit" do
@@ -279,7 +341,7 @@ describe Audited::Auditor do
279
341
  end
280
342
 
281
343
  it "should set the action to create" do
282
- expect(user.audits.first.action).to eq('create')
344
+ expect(user.audits.first.action).to eq("create")
283
345
  expect(Audited::Audit.creates.order(:id).last).to eq(user.audits.first)
284
346
  expect(user.audits.creates.count).to eq(1)
285
347
  expect(user.audits.updates.count).to eq(0)
@@ -294,46 +356,61 @@ describe Audited::Auditor do
294
356
  expect(user.audits.first.audited_changes["status"]).to eq(1)
295
357
  end
296
358
 
359
+ context "when store_synthesized_enums is set to true" do
360
+ before { Audited.store_synthesized_enums = true }
361
+ after { Audited.store_synthesized_enums = false }
362
+
363
+ it "should store enum value as Rails synthesized value" do
364
+ expect(user.audits.first.audited_changes["status"]).to eq("reliable")
365
+ end
366
+ end
367
+
297
368
  it "should store comment" do
298
- expect(user.audits.first.comment).to eq('Create')
369
+ expect(user.audits.first.comment).to eq("Create")
299
370
  end
300
371
 
301
372
  it "should not audit an attribute which is excepted if specified on create or destroy" do
302
- on_create_destroy_except_name = Models::ActiveRecord::OnCreateDestroyExceptName.create(name: 'Bart')
303
- expect(on_create_destroy_except_name.audits.first.audited_changes.keys.any?{|col| ['name'].include? col}).to eq(false)
373
+ on_create_destroy_except_name = Models::ActiveRecord::OnCreateDestroyExceptName.create(name: "Bart")
374
+ expect(on_create_destroy_except_name.audits.first.audited_changes.keys.any? { |col| ["name"].include? col }).to eq(false)
304
375
  end
305
376
 
306
377
  it "should not save an audit if only specified on update/destroy" do
307
378
  expect {
308
- Models::ActiveRecord::OnUpdateDestroy.create!( name: 'Bart' )
309
- }.to_not change( Audited::Audit, :count )
379
+ Models::ActiveRecord::OnUpdateDestroy.create!(name: "Bart")
380
+ }.to_not change(Audited::Audit, :count)
381
+ end
382
+
383
+ it "should save readonly columns" do
384
+ expect {
385
+ Models::ActiveRecord::UserWithReadOnlyAttrs.create!(name: "Bart")
386
+ }.to change(Audited::Audit, :count)
310
387
  end
311
388
  end
312
389
 
313
390
  describe "on update" do
314
391
  before do
315
- @user = create_user( name: 'Brandon', status: :active, audit_comment: 'Update' )
392
+ @user = create_user(name: "Brandon", status: :active, audit_comment: "Update")
316
393
  end
317
394
 
318
395
  it "should save an audit" do
319
396
  expect {
320
397
  @user.update_attribute(:name, "Someone")
321
- }.to change( Audited::Audit, :count ).by(1)
398
+ }.to change(Audited::Audit, :count).by(1)
322
399
  expect {
323
400
  @user.update_attribute(:name, "Someone else")
324
- }.to change( Audited::Audit, :count ).by(1)
401
+ }.to change(Audited::Audit, :count).by(1)
325
402
  end
326
403
 
327
404
  it "should set the action to 'update'" do
328
- @user.update! name: 'Changed'
329
- expect(@user.audits.last.action).to eq('update')
405
+ @user.update! name: "Changed"
406
+ expect(@user.audits.last.action).to eq("update")
330
407
  expect(Audited::Audit.updates.order(:id).last).to eq(@user.audits.last)
331
408
  expect(@user.audits.updates.last).to eq(@user.audits.last)
332
409
  end
333
410
 
334
411
  it "should store the changed attributes" do
335
- @user.update! name: 'Changed'
336
- expect(@user.audits.last.audited_changes).to eq({ 'name' => ['Brandon', 'Changed'] })
412
+ @user.update! name: "Changed"
413
+ expect(@user.audits.last.audited_changes).to eq({"name" => ["Brandon", "Changed"]})
337
414
  end
338
415
 
339
416
  it "should store changed enum values" do
@@ -342,35 +419,138 @@ describe Audited::Auditor do
342
419
  end
343
420
 
344
421
  it "should store audit comment" do
345
- expect(@user.audits.last.comment).to eq('Update')
422
+ expect(@user.audits.last.comment).to eq("Update")
346
423
  end
347
424
 
348
425
  it "should not save an audit if only specified on create/destroy" do
349
- on_create_destroy = Models::ActiveRecord::OnCreateDestroy.create( name: 'Bart' )
426
+ on_create_destroy = Models::ActiveRecord::OnCreateDestroy.create(name: "Bart")
350
427
  expect {
351
- on_create_destroy.update! name: 'Changed'
352
- }.to_not change( Audited::Audit, :count )
428
+ on_create_destroy.update! name: "Changed"
429
+ }.to_not change(Audited::Audit, :count)
353
430
  end
354
431
 
355
432
  it "should not save an audit if the value doesn't change after type casting" do
356
433
  @user.update! logins: 0, activated: true
357
- expect { @user.update_attribute :logins, '0' }.to_not change( Audited::Audit, :count )
358
- expect { @user.update_attribute :activated, 1 }.to_not change( Audited::Audit, :count )
359
- expect { @user.update_attribute :activated, '1' }.to_not change( Audited::Audit, :count )
434
+ expect { @user.update_attribute :logins, "0" }.to_not change(Audited::Audit, :count)
435
+ expect { @user.update_attribute :activated, 1 }.to_not change(Audited::Audit, :count)
436
+ expect { @user.update_attribute :activated, "1" }.to_not change(Audited::Audit, :count)
437
+ end
438
+
439
+ context "with readonly attributes" do
440
+ before do
441
+ @user = create_user_with_readonly_attrs(status: "active")
442
+ end
443
+
444
+ it "should not save readonly columns" do
445
+ expect { @user.update! status: "banned" }.to_not change(Audited::Audit, :count)
446
+ end
360
447
  end
361
448
 
362
449
  describe "with no dirty changes" do
363
450
  it "does not create an audit if the record is not changed" do
364
451
  expect {
365
452
  @user.save!
366
- }.to_not change( Audited::Audit, :count )
453
+ }.to_not change(Audited::Audit, :count)
367
454
  end
368
455
 
369
456
  it "creates an audit when an audit comment is present" do
370
457
  expect {
371
458
  @user.audit_comment = "Comment"
372
459
  @user.save!
373
- }.to change( Audited::Audit, :count )
460
+ }.to change(Audited::Audit, :count)
461
+ end
462
+ end
463
+ end
464
+
465
+ if ::ActiveRecord::VERSION::MAJOR >= 6
466
+ describe "on touch" do
467
+ before do
468
+ @user = create_user(name: "Brandon", status: :active)
469
+ end
470
+
471
+ it "should save an audit" do
472
+ expect { @user.touch(:suspended_at) }.to change(Audited::Audit, :count).by(1)
473
+ end
474
+
475
+ it "should set the action to 'update'" do
476
+ @user.touch(:suspended_at)
477
+ expect(@user.audits.last.action).to eq("update")
478
+ expect(Audited::Audit.updates.order(:id).last).to eq(@user.audits.last)
479
+ expect(@user.audits.updates.last).to eq(@user.audits.last)
480
+ end
481
+
482
+ it "should store the changed attributes" do
483
+ @user.touch(:suspended_at)
484
+ expect(@user.audits.last.audited_changes["suspended_at"][0]).to be_nil
485
+ expect(Time.parse(@user.audits.last.audited_changes["suspended_at"][1].to_s)).to be_within(2.seconds).of(Time.current)
486
+ end
487
+
488
+ it "should store audit comment" do
489
+ @user.audit_comment = "Here exists a touch comment"
490
+ @user.touch(:suspended_at)
491
+ expect(@user.audits.last.action).to eq("update")
492
+ expect(@user.audits.last.comment).to eq("Here exists a touch comment")
493
+ end
494
+
495
+ it "should not save an audit if only specified on create/destroy" do
496
+ on_create_destroy = Models::ActiveRecord::OnCreateDestroyUser.create(name: "Bart")
497
+ expect {
498
+ on_create_destroy.touch(:suspended_at)
499
+ }.to_not change(Audited::Audit, :count)
500
+ end
501
+
502
+ it "should store an audit if touch is the only audit" do
503
+ on_touch = Models::ActiveRecord::OnTouchOnly.create(name: "Bart")
504
+ expect {
505
+ on_touch.update(name: "NotBart")
506
+ }.to_not change(Audited::Audit, :count)
507
+ expect {
508
+ on_touch.touch(:suspended_at)
509
+ }.to change(on_touch.audits, :count).from(0).to(1)
510
+
511
+ @user.audits.destroy_all
512
+ expect(@user.audits).to be_empty
513
+ expect {
514
+ @user.touch(:suspended_at)
515
+ }.to change(@user.audits, :count).from(0).to(1)
516
+ end
517
+
518
+ context "don't double audit" do
519
+ let(:user) { Models::ActiveRecord::Owner.create(name: "OwnerUser", suspended_at: 1.month.ago, companies_attributes: [{name: "OwnedCompany"}]) }
520
+ let(:company) { user.companies.first }
521
+
522
+ it "should only create 1 (create) audit for object" do
523
+ expect(user.audits.count).to eq(1)
524
+ expect(user.audits.first.action).to eq("create")
525
+ end
526
+
527
+ it "should only create 1 (create) audit for nested resource" do
528
+ expect(company.audits.count).to eq(1)
529
+ expect(company.audits.first.action).to eq("create")
530
+ end
531
+
532
+ context "after creating" do
533
+ it "updating / touching nested resource shouldn't save touch audit on parent object" do
534
+ expect { company.touch(:type) }.not_to change(user.audits, :count)
535
+ expect { company.update(type: "test") }.not_to change(user.audits, :count)
536
+ end
537
+
538
+ it "updating / touching parent object shouldn't save previous data" do
539
+ expect { user.touch(:suspended_at) }.to change(user.audits, :count).from(1).to(2)
540
+ expect(user.audits.last.action).to eq("update")
541
+ expect(user.audits.last.audited_changes.keys).to eq(%w[suspended_at])
542
+ end
543
+ end
544
+
545
+ context "after updating" do
546
+ it "changing nested resource shouldn't audit owner" do
547
+ expect { user.update(username: "test") }.to change(user.audits, :count).from(1).to(2)
548
+ expect { company.update(type: "test") }.not_to change(user.audits, :count)
549
+
550
+ expect { user.touch(:suspended_at) }.to change(user.audits, :count).from(2).to(3)
551
+ expect { company.update(type: "another_test") }.not_to change(user.audits, :count)
552
+ end
553
+ end
374
554
  end
375
555
  end
376
556
  end
@@ -383,7 +563,7 @@ describe Audited::Auditor do
383
563
  it "should save an audit" do
384
564
  expect {
385
565
  @user.destroy
386
- }.to change( Audited::Audit, :count )
566
+ }.to change(Audited::Audit, :count)
387
567
 
388
568
  expect(@user.audits.size).to eq(2)
389
569
  end
@@ -391,7 +571,7 @@ describe Audited::Auditor do
391
571
  it "should set the action to 'destroy'" do
392
572
  @user.destroy
393
573
 
394
- expect(@user.audits.last.action).to eq('destroy')
574
+ expect(@user.audits.last.action).to eq("destroy")
395
575
  expect(Audited::Audit.destroys.order(:id).last).to eq(@user.audits.last)
396
576
  expect(@user.audits.destroys.last).to eq(@user.audits.last)
397
577
  end
@@ -416,11 +596,11 @@ describe Audited::Auditor do
416
596
  end
417
597
 
418
598
  it "should not save an audit if only specified on create/update" do
419
- on_create_update = Models::ActiveRecord::OnCreateUpdate.create!( name: 'Bart' )
599
+ on_create_update = Models::ActiveRecord::OnCreateUpdate.create!(name: "Bart")
420
600
 
421
601
  expect {
422
602
  on_create_update.destroy
423
- }.to_not change( Audited::Audit, :count )
603
+ }.to_not change(Audited::Audit, :count)
424
604
  end
425
605
 
426
606
  it "should audit dependent destructions" do
@@ -429,9 +609,9 @@ describe Audited::Auditor do
429
609
 
430
610
  expect {
431
611
  owner.destroy
432
- }.to change( Audited::Audit, :count )
612
+ }.to change(Audited::Audit, :count)
433
613
 
434
- expect(company.audits.map { |a| a.action }).to eq(['create', 'destroy'])
614
+ expect(company.audits.map { |a| a.action }).to eq(["create", "destroy"])
435
615
  end
436
616
  end
437
617
 
@@ -443,20 +623,20 @@ describe Audited::Auditor do
443
623
  user.destroy
444
624
  }.to_not raise_error
445
625
 
446
- expect( user.audits ).to be_empty
626
+ expect(user.audits).to be_empty
447
627
  end
448
628
  end
449
629
 
450
630
  describe "associated with" do
451
- let(:owner) { Models::ActiveRecord::Owner.create(name: 'Models::ActiveRecord::Owner') }
452
- let(:owned_company) { Models::ActiveRecord::OwnedCompany.create!(name: 'The auditors', owner: owner) }
631
+ let(:owner) { Models::ActiveRecord::Owner.create(name: "Models::ActiveRecord::Owner") }
632
+ let(:owned_company) { Models::ActiveRecord::OwnedCompany.create!(name: "The auditors", owner: owner) }
453
633
 
454
634
  it "should record the associated object on create" do
455
635
  expect(owned_company.audits.first.associated).to eq(owner)
456
636
  end
457
637
 
458
638
  it "should store the associated object on update" do
459
- owned_company.update_attribute(:name, 'The Auditors')
639
+ owned_company.update_attribute(:name, "The Auditors")
460
640
  expect(owned_company.audits.last.associated).to eq(owner)
461
641
  end
462
642
 
@@ -467,8 +647,8 @@ describe Audited::Auditor do
467
647
  end
468
648
 
469
649
  describe "has associated audits" do
470
- let!(:owner) { Models::ActiveRecord::Owner.create!(name: 'Models::ActiveRecord::Owner') }
471
- let!(:owned_company) { Models::ActiveRecord::OwnedCompany.create!(name: 'The auditors', owner: owner) }
650
+ let!(:owner) { Models::ActiveRecord::Owner.create!(name: "Models::ActiveRecord::Owner") }
651
+ let!(:owned_company) { Models::ActiveRecord::OwnedCompany.create!(name: "The auditors", owner: owner) }
472
652
 
473
653
  it "should list the associated audits" do
474
654
  expect(owner.associated_audits.length).to eq(1)
@@ -492,7 +672,7 @@ describe Audited::Auditor do
492
672
  it "should delete old audits when keeped amount exceeded" do
493
673
  stub_global_max_audits(2) do
494
674
  user = create_versions(2)
495
- user.update(name: 'John')
675
+ user.update(name: "John")
496
676
  expect(user.audits.pluck(:version)).to eq([2, 3])
497
677
  end
498
678
  end
@@ -500,35 +680,35 @@ describe Audited::Auditor do
500
680
  it "should not delete old audits when keeped amount not exceeded" do
501
681
  stub_global_max_audits(3) do
502
682
  user = create_versions(2)
503
- user.update(name: 'John')
683
+ user.update(name: "John")
504
684
  expect(user.audits.pluck(:version)).to eq([1, 2, 3])
505
685
  end
506
686
  end
507
687
 
508
688
  it "should delete old extra audits after introducing limit" do
509
689
  stub_global_max_audits(nil) do
510
- user = Models::ActiveRecord::User.create!(name: 'Brandon', username: 'brandon')
511
- user.update!(name: 'Foobar')
512
- user.update!(name: 'Awesome', username: 'keepers')
690
+ user = Models::ActiveRecord::User.create!(name: "Brandon", username: "brandon")
691
+ user.update!(name: "Foobar")
692
+ user.update!(name: "Awesome", username: "keepers")
513
693
  user.update!(activated: true)
514
694
 
515
695
  Audited.max_audits = 3
516
696
  Models::ActiveRecord::User.send(:normalize_audited_options)
517
- user.update!(favourite_device: 'Android Phone')
697
+ user.update!(favourite_device: "Android Phone")
518
698
  audits = user.audits
519
699
 
520
700
  expect(audits.count).to eq(3)
521
- expect(audits[0].audited_changes).to include({'name' => ['Foobar', 'Awesome'], 'username' => ['brandon', 'keepers']})
522
- expect(audits[1].audited_changes).to eq({'activated' => [nil, true]})
523
- expect(audits[2].audited_changes).to eq({'favourite_device' => [nil, 'Android Phone']})
701
+ expect(audits[0].audited_changes).to include({"name" => ["Foobar", "Awesome"], "username" => ["brandon", "keepers"]})
702
+ expect(audits[1].audited_changes).to eq({"activated" => [nil, true]})
703
+ expect(audits[2].audited_changes).to eq({"favourite_device" => [nil, "Android Phone"]})
524
704
  end
525
705
  end
526
706
 
527
707
  it "should add comment line for combined audit" do
528
708
  stub_global_max_audits(2) do
529
- user = Models::ActiveRecord::User.create!(name: 'Foobar 1')
530
- user.update(name: 'Foobar 2', audit_comment: 'First audit comment')
531
- user.update(name: 'Foobar 3', audit_comment: 'Second audit comment')
709
+ user = Models::ActiveRecord::User.create!(name: "Foobar 1")
710
+ user.update(name: "Foobar 2", audit_comment: "First audit comment")
711
+ user.update(name: "Foobar 3", audit_comment: "Second audit comment")
532
712
  expect(user.audits.first.comment).to match(/First audit comment.+is the result of multiple/m)
533
713
  end
534
714
  end
@@ -548,10 +728,10 @@ describe Audited::Auditor do
548
728
  end
549
729
 
550
730
  describe "revisions" do
551
- let( :user ) { create_versions }
731
+ let(:user) { create_versions }
552
732
 
553
733
  it "should return an Array of Users" do
554
- expect(user.revisions).to be_a_kind_of( Array )
734
+ expect(user.revisions).to be_a_kind_of(Array)
555
735
  user.revisions.each { |version| expect(version).to be_a_kind_of Models::ActiveRecord::User }
556
736
  end
557
737
 
@@ -560,38 +740,38 @@ describe Audited::Auditor do
560
740
  end
561
741
 
562
742
  it "should have one revision for each audit" do
563
- expect(user.audits.size).to eql( user.revisions.size )
743
+ expect(user.audits.size).to eql(user.revisions.size)
564
744
  end
565
745
 
566
746
  it "should set the attributes for each revision" do
567
- u = Models::ActiveRecord::User.create(name: 'Brandon', username: 'brandon')
568
- u.update! name: 'Foobar'
569
- u.update! name: 'Awesome', username: 'keepers'
747
+ u = Models::ActiveRecord::User.create(name: "Brandon", username: "brandon")
748
+ u.update! name: "Foobar"
749
+ u.update! name: "Awesome", username: "keepers"
570
750
 
571
751
  expect(u.revisions.size).to eql(3)
572
752
 
573
- expect(u.revisions[0].name).to eql('Brandon')
574
- expect(u.revisions[0].username).to eql('brandon')
753
+ expect(u.revisions[0].name).to eql("Brandon")
754
+ expect(u.revisions[0].username).to eql("brandon")
575
755
 
576
- expect(u.revisions[1].name).to eql('Foobar')
577
- expect(u.revisions[1].username).to eql('brandon')
756
+ expect(u.revisions[1].name).to eql("Foobar")
757
+ expect(u.revisions[1].username).to eql("brandon")
578
758
 
579
- expect(u.revisions[2].name).to eql('Awesome')
580
- expect(u.revisions[2].username).to eql('keepers')
759
+ expect(u.revisions[2].name).to eql("Awesome")
760
+ expect(u.revisions[2].username).to eql("keepers")
581
761
  end
582
762
 
583
763
  it "access to only recent revisions" do
584
- u = Models::ActiveRecord::User.create(name: 'Brandon', username: 'brandon')
585
- u.update! name: 'Foobar'
586
- u.update! name: 'Awesome', username: 'keepers'
764
+ u = Models::ActiveRecord::User.create(name: "Brandon", username: "brandon")
765
+ u.update! name: "Foobar"
766
+ u.update! name: "Awesome", username: "keepers"
587
767
 
588
768
  expect(u.revisions(2).size).to eq(2)
589
769
 
590
- expect(u.revisions(2)[0].name).to eq('Foobar')
591
- expect(u.revisions(2)[0].username).to eq('brandon')
770
+ expect(u.revisions(2)[0].name).to eq("Foobar")
771
+ expect(u.revisions(2)[0].username).to eq("brandon")
592
772
 
593
- expect(u.revisions(2)[1].name).to eq('Awesome')
594
- expect(u.revisions(2)[1].username).to eq('keepers')
773
+ expect(u.revisions(2)[1].name).to eq("Awesome")
774
+ expect(u.revisions(2)[1].username).to eq("keepers")
595
775
  end
596
776
 
597
777
  it "should be empty if no audits exist" do
@@ -600,13 +780,13 @@ describe Audited::Auditor do
600
780
  end
601
781
 
602
782
  it "should ignore attributes that have been deleted" do
603
- user.audits.last.update! audited_changes: {old_attribute: 'old value'}
783
+ user.audits.last.update! audited_changes: {old_attribute: "old value"}
604
784
  expect { user.revisions }.to_not raise_error
605
785
  end
606
786
  end
607
787
 
608
788
  describe "revisions" do
609
- let( :user ) { create_versions(5) }
789
+ let(:user) { create_versions(5) }
610
790
 
611
791
  it "should maintain identity" do
612
792
  expect(user.revision(1)).to eq(user)
@@ -614,15 +794,15 @@ describe Audited::Auditor do
614
794
 
615
795
  it "should find the given revision" do
616
796
  revision = user.revision(3)
617
- expect(revision).to be_a_kind_of( Models::ActiveRecord::User )
797
+ expect(revision).to be_a_kind_of(Models::ActiveRecord::User)
618
798
  expect(revision.audit_version).to eq(3)
619
- expect(revision.name).to eq('Foobar 3')
799
+ expect(revision.name).to eq("Foobar 3")
620
800
  end
621
801
 
622
802
  it "should find the previous revision with :previous" do
623
803
  revision = user.revision(:previous)
624
804
  expect(revision.audit_version).to eq(4)
625
- #expect(revision).to eq(user.revision(4))
805
+ # expect(revision).to eq(user.revision(4))
626
806
  expect(revision.attributes).to eq(user.revision(4).attributes)
627
807
  end
628
808
 
@@ -633,7 +813,7 @@ describe Audited::Auditor do
633
813
  end
634
814
 
635
815
  it "should be able to set protected attributes" do
636
- u = Models::ActiveRecord::User.create(name: 'Brandon')
816
+ u = Models::ActiveRecord::User.create(name: "Brandon")
637
817
  u.update_attribute :logins, 1
638
818
  u.update_attribute :logins, 2
639
819
 
@@ -643,23 +823,23 @@ describe Audited::Auditor do
643
823
  end
644
824
 
645
825
  it "should set attributes directly" do
646
- u = Models::ActiveRecord::User.create(name: '<Joe>')
647
- expect(u.revision(1).name).to eq('&lt;Joe&gt;')
826
+ u = Models::ActiveRecord::User.create(name: "<Joe>")
827
+ expect(u.revision(1).name).to eq("&lt;Joe&gt;")
648
828
  end
649
829
 
650
830
  it "should set the attributes for each revision" do
651
- u = Models::ActiveRecord::User.create(name: 'Brandon', username: 'brandon')
652
- u.update! name: 'Foobar'
653
- u.update! name: 'Awesome', username: 'keepers'
831
+ u = Models::ActiveRecord::User.create(name: "Brandon", username: "brandon")
832
+ u.update! name: "Foobar"
833
+ u.update! name: "Awesome", username: "keepers"
654
834
 
655
- expect(u.revision(3).name).to eq('Awesome')
656
- expect(u.revision(3).username).to eq('keepers')
835
+ expect(u.revision(3).name).to eq("Awesome")
836
+ expect(u.revision(3).username).to eq("keepers")
657
837
 
658
- expect(u.revision(2).name).to eq('Foobar')
659
- expect(u.revision(2).username).to eq('brandon')
838
+ expect(u.revision(2).name).to eq("Foobar")
839
+ expect(u.revision(2).username).to eq("brandon")
660
840
 
661
- expect(u.revision(1).name).to eq('Brandon')
662
- expect(u.revision(1).username).to eq('brandon')
841
+ expect(u.revision(1).name).to eq("Brandon")
842
+ expect(u.revision(1).username).to eq("brandon")
663
843
  end
664
844
 
665
845
  it "should correctly restore revision with enum" do
@@ -690,34 +870,42 @@ describe Audited::Auditor do
690
870
  it "should record new audit when saving revision" do
691
871
  expect {
692
872
  user.revision(1).save!
693
- }.to change( user.audits, :count ).by(1)
873
+ }.to change(user.audits, :count).by(1)
694
874
  end
695
875
 
696
876
  it "should re-insert destroyed records" do
697
877
  user.destroy
698
878
  expect {
699
879
  user.revision(1).save!
700
- }.to change( Models::ActiveRecord::User, :count ).by(1)
880
+ }.to change(Models::ActiveRecord::User, :count).by(1)
701
881
  end
702
882
 
703
883
  it "should return nil for values greater than the number of revisions" do
704
884
  expect(user.revision(user.revisions.count + 1)).to be_nil
705
885
  end
886
+
887
+ it "should work with array attributes" do
888
+ u = Models::ActiveRecord::User.create!(phone_numbers: ["+1 800-444-4444"])
889
+ u.update!(phone_numbers: ["+1 804-222-1111", "+1 317 222-2222"])
890
+
891
+ expect(u.revision(0).phone_numbers).to eq(["+1 804-222-1111", "+1 317 222-2222"])
892
+ expect(u.revision(1).phone_numbers).to eq(["+1 800-444-4444"])
893
+ end
706
894
  end
707
895
 
708
896
  describe "revision_at" do
709
- let( :user ) { create_user }
897
+ let(:user) { create_user }
710
898
 
711
899
  it "should find the latest revision before the given time" do
712
900
  audit = user.audits.first
713
901
  audit.created_at = 1.hour.ago
714
902
  audit.save!
715
- user.update! name: 'updated'
716
- expect(user.revision_at( 2.minutes.ago ).audit_version).to eq(1)
903
+ user.update! name: "updated"
904
+ expect(user.revision_at(2.minutes.ago).audit_version).to eq(1)
717
905
  end
718
906
 
719
907
  it "should be nil if given a time before audits" do
720
- expect(user.revision_at( 1.week.ago )).to be_nil
908
+ expect(user.revision_at(1.week.ago)).to be_nil
721
909
  end
722
910
  end
723
911
 
@@ -733,6 +921,19 @@ describe Audited::Auditor do
733
921
  expect(owner.own_and_associated_audits).to match_array(owner.audits + company.audits)
734
922
  end
735
923
 
924
+ it "should return audits for STI classes" do
925
+ # Where parent is STI
926
+ sti_company = Models::ActiveRecord::Company::STICompany.create!
927
+ sti_company.update!(name: "Collective Idea")
928
+ expect(sti_company.own_and_associated_audits).to match_array(sti_company.audits)
929
+
930
+ # Where associated is STI
931
+ owner = Models::ActiveRecord::Owner.create!
932
+ company = owner.companies.create! type: "Models::ActiveRecord::OwnedCompany::STICompany"
933
+ company.update!(name: "Collective Idea")
934
+ expect(owner.own_and_associated_audits).to match_array(owner.audits + company.audits)
935
+ end
936
+
736
937
  it "should order audits by creation time" do
737
938
  owner = Models::ActiveRecord::Owner.create!
738
939
  first_audit = owner.audits.first
@@ -751,19 +952,32 @@ describe Audited::Auditor do
751
952
  describe "without auditing" do
752
953
  it "should not save an audit when calling #save_without_auditing" do
753
954
  expect {
754
- u = Models::ActiveRecord::User.new(name: 'Brandon')
955
+ u = Models::ActiveRecord::User.new(name: "Brandon")
755
956
  expect(u.save_without_auditing).to eq(true)
756
- }.to_not change( Audited::Audit, :count )
957
+ }.to_not change(Audited::Audit, :count)
757
958
  end
758
959
 
759
960
  it "should not save an audit inside of the #without_auditing block" do
760
961
  expect {
761
- Models::ActiveRecord::User.without_auditing { Models::ActiveRecord::User.create!( name: 'Brandon' ) }
762
- }.to_not change( Audited::Audit, :count )
962
+ Models::ActiveRecord::User.without_auditing { Models::ActiveRecord::User.create!(name: "Brandon") }
963
+ }.to_not change(Audited::Audit, :count)
964
+ end
965
+
966
+ context "when global audits are disabled" do
967
+ it "should re-enable class audits after #without_auditing block" do
968
+ Audited.auditing_enabled = false
969
+ Models::ActiveRecord::User.without_auditing {}
970
+ Audited.auditing_enabled = true
971
+ expect(Models::ActiveRecord::User.auditing_enabled).to eql(true)
972
+ end
763
973
  end
764
974
 
765
975
  it "should reset auditing status even it raises an exception" do
766
- Models::ActiveRecord::User.without_auditing { raise } rescue nil
976
+ begin
977
+ Models::ActiveRecord::User.without_auditing { raise }
978
+ rescue
979
+ nil
980
+ end
767
981
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(true)
768
982
  end
769
983
 
@@ -774,7 +988,7 @@ describe Audited::Auditor do
774
988
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(true)
775
989
  Models::ActiveRecord::User.without_auditing do
776
990
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(false)
777
- Models::ActiveRecord::User.create!( name: 'Bart' )
991
+ Models::ActiveRecord::User.create!(name: "Bart")
778
992
  sleep 1
779
993
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(false)
780
994
  end
@@ -784,13 +998,13 @@ describe Audited::Auditor do
784
998
  t2 = Thread.new do
785
999
  sleep 0.5
786
1000
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(true)
787
- Models::ActiveRecord::User.create!( name: 'Lisa' )
1001
+ Models::ActiveRecord::User.create!(name: "Lisa")
788
1002
  end
789
1003
  t1.join
790
1004
  t2.join
791
1005
 
792
- expect(Models::ActiveRecord::User.find_by_name('Bart').audits.count).to eq(0)
793
- expect(Models::ActiveRecord::User.find_by_name('Lisa').audits.count).to eq(1)
1006
+ expect(Models::ActiveRecord::User.find_by_name("Bart").audits.count).to eq(0)
1007
+ expect(Models::ActiveRecord::User.find_by_name("Lisa").audits.count).to eq(1)
794
1008
  end
795
1009
 
796
1010
  it "should not save an audit when auditing is globally disabled" do
@@ -804,7 +1018,7 @@ describe Audited::Auditor do
804
1018
  Audited.auditing_enabled = true
805
1019
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(true)
806
1020
 
807
- user.update!(name: 'Test')
1021
+ user.update!(name: "Test")
808
1022
  expect(user.audits.count).to eq(1)
809
1023
  Models::ActiveRecord::User.enable_auditing
810
1024
  end
@@ -813,24 +1027,37 @@ describe Audited::Auditor do
813
1027
  describe "with auditing" do
814
1028
  it "should save an audit when calling #save_with_auditing" do
815
1029
  expect {
816
- u = Models::ActiveRecord::User.new(name: 'Brandon')
1030
+ u = Models::ActiveRecord::User.new(name: "Brandon")
817
1031
  Models::ActiveRecord::User.auditing_enabled = false
818
1032
  expect(u.save_with_auditing).to eq(true)
819
1033
  Models::ActiveRecord::User.auditing_enabled = true
820
- }.to change( Audited::Audit, :count ).by(1)
1034
+ }.to change(Audited::Audit, :count).by(1)
821
1035
  end
822
1036
 
823
1037
  it "should save an audit inside of the #with_auditing block" do
824
1038
  expect {
825
1039
  Models::ActiveRecord::User.auditing_enabled = false
826
- Models::ActiveRecord::User.with_auditing { Models::ActiveRecord::User.create!( name: 'Brandon' ) }
1040
+ Models::ActiveRecord::User.with_auditing { Models::ActiveRecord::User.create!(name: "Brandon") }
827
1041
  Models::ActiveRecord::User.auditing_enabled = true
828
- }.to change( Audited::Audit, :count ).by(1)
1042
+ }.to change(Audited::Audit, :count).by(1)
1043
+ end
1044
+
1045
+ context "when global audits are disabled" do
1046
+ it "should re-enable class audits after #with_auditing block" do
1047
+ Audited.auditing_enabled = false
1048
+ Models::ActiveRecord::User.with_auditing {}
1049
+ Audited.auditing_enabled = true
1050
+ expect(Models::ActiveRecord::User.auditing_enabled).to eql(true)
1051
+ end
829
1052
  end
830
1053
 
831
1054
  it "should reset auditing status even it raises an exception" do
832
1055
  Models::ActiveRecord::User.disable_auditing
833
- Models::ActiveRecord::User.with_auditing { raise } rescue nil
1056
+ begin
1057
+ Models::ActiveRecord::User.with_auditing { raise }
1058
+ rescue
1059
+ nil
1060
+ end
834
1061
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(false)
835
1062
  Models::ActiveRecord::User.enable_auditing
836
1063
  end
@@ -844,7 +1071,7 @@ describe Audited::Auditor do
844
1071
  Models::ActiveRecord::User.with_auditing do
845
1072
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(true)
846
1073
 
847
- Models::ActiveRecord::User.create!( name: 'Shaggy' )
1074
+ Models::ActiveRecord::User.create!(name: "Shaggy")
848
1075
  sleep 1
849
1076
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(true)
850
1077
  end
@@ -856,74 +1083,81 @@ describe Audited::Auditor do
856
1083
  sleep 0.5
857
1084
  Models::ActiveRecord::User.disable_auditing
858
1085
  expect(Models::ActiveRecord::User.auditing_enabled).to eq(false)
859
- Models::ActiveRecord::User.create!( name: 'Scooby' )
1086
+ Models::ActiveRecord::User.create!(name: "Scooby")
860
1087
  Models::ActiveRecord::User.enable_auditing
861
1088
  end
862
1089
  t1.join
863
1090
  t2.join
864
1091
 
865
1092
  Models::ActiveRecord::User.enable_auditing
866
- expect(Models::ActiveRecord::User.find_by_name('Shaggy').audits.count).to eq(1)
867
- expect(Models::ActiveRecord::User.find_by_name('Scooby').audits.count).to eq(0)
1093
+ expect(Models::ActiveRecord::User.find_by_name("Shaggy").audits.count).to eq(1)
1094
+ expect(Models::ActiveRecord::User.find_by_name("Scooby").audits.count).to eq(0)
868
1095
  end
869
1096
  end
870
1097
 
871
1098
  describe "comment required" do
872
-
873
1099
  describe "on create" do
874
1100
  it "should not validate when audit_comment is not supplied when initialized" do
875
- expect(Models::ActiveRecord::CommentRequiredUser.new(name: 'Foo')).not_to be_valid
1101
+ expect(Models::ActiveRecord::CommentRequiredUser.new(name: "Foo")).not_to be_valid
876
1102
  end
877
1103
 
878
1104
  it "should not validate when audit_comment is not supplied trying to create" do
879
- expect(Models::ActiveRecord::CommentRequiredUser.create(name: 'Foo')).not_to be_valid
1105
+ expect(Models::ActiveRecord::CommentRequiredUser.create(name: "Foo")).not_to be_valid
880
1106
  end
881
1107
 
882
1108
  it "should validate when audit_comment is supplied" do
883
- expect(Models::ActiveRecord::CommentRequiredUser.create(name: 'Foo', audit_comment: 'Create')).to be_valid
1109
+ expect(Models::ActiveRecord::CommentRequiredUser.create(name: "Foo", audit_comment: "Create")).to be_valid
884
1110
  end
885
1111
 
886
1112
  it "should validate when audit_comment is not supplied, and creating is not being audited" do
887
- expect(Models::ActiveRecord::OnUpdateCommentRequiredUser.create(name: 'Foo')).to be_valid
888
- expect(Models::ActiveRecord::OnDestroyCommentRequiredUser.create(name: 'Foo')).to be_valid
1113
+ expect(Models::ActiveRecord::OnUpdateCommentRequiredUser.create(name: "Foo")).to be_valid
1114
+ expect(Models::ActiveRecord::OnDestroyCommentRequiredUser.create(name: "Foo")).to be_valid
889
1115
  end
890
1116
 
891
1117
  it "should validate when audit_comment is not supplied, and auditing is disabled" do
892
1118
  Models::ActiveRecord::CommentRequiredUser.disable_auditing
893
- expect(Models::ActiveRecord::CommentRequiredUser.create(name: 'Foo')).to be_valid
1119
+ expect(Models::ActiveRecord::CommentRequiredUser.create(name: "Foo")).to be_valid
894
1120
  Models::ActiveRecord::CommentRequiredUser.enable_auditing
895
1121
  end
1122
+
1123
+ it "should validate when audit_comment is not supplied, and only excluded attributes changed" do
1124
+ expect(Models::ActiveRecord::CommentRequiredUser.new(password: "Foo")).to be_valid
1125
+ end
896
1126
  end
897
1127
 
898
1128
  describe "on update" do
899
- let( :user ) { Models::ActiveRecord::CommentRequiredUser.create!( audit_comment: 'Create' ) }
900
- let( :on_create_user ) { Models::ActiveRecord::OnDestroyCommentRequiredUser.create }
901
- let( :on_destroy_user ) { Models::ActiveRecord::OnDestroyCommentRequiredUser.create }
1129
+ let(:user) { Models::ActiveRecord::CommentRequiredUser.create!(audit_comment: "Create") }
1130
+ let(:on_create_user) { Models::ActiveRecord::OnDestroyCommentRequiredUser.create }
1131
+ let(:on_destroy_user) { Models::ActiveRecord::OnDestroyCommentRequiredUser.create }
902
1132
 
903
1133
  it "should not validate when audit_comment is not supplied" do
904
- expect(user.update(name: 'Test')).to eq(false)
1134
+ expect(user.update(name: "Test")).to eq(false)
905
1135
  end
906
1136
 
907
1137
  it "should validate when audit_comment is not supplied, and updating is not being audited" do
908
- expect(on_create_user.update(name: 'Test')).to eq(true)
909
- expect(on_destroy_user.update(name: 'Test')).to eq(true)
1138
+ expect(on_create_user.update(name: "Test")).to eq(true)
1139
+ expect(on_destroy_user.update(name: "Test")).to eq(true)
910
1140
  end
911
1141
 
912
1142
  it "should validate when audit_comment is supplied" do
913
- expect(user.update(name: 'Test', audit_comment: 'Update')).to eq(true)
1143
+ expect(user.update(name: "Test", audit_comment: "Update")).to eq(true)
914
1144
  end
915
1145
 
916
1146
  it "should validate when audit_comment is not supplied, and auditing is disabled" do
917
1147
  Models::ActiveRecord::CommentRequiredUser.disable_auditing
918
- expect(user.update(name: 'Test')).to eq(true)
1148
+ expect(user.update(name: "Test")).to eq(true)
919
1149
  Models::ActiveRecord::CommentRequiredUser.enable_auditing
920
1150
  end
1151
+
1152
+ it "should validate when audit_comment is not supplied, and only excluded attributes changed" do
1153
+ expect(user.update(password: "Test")).to eq(true)
1154
+ end
921
1155
  end
922
1156
 
923
1157
  describe "on destroy" do
924
- let( :user ) { Models::ActiveRecord::CommentRequiredUser.create!( audit_comment: 'Create' )}
925
- let( :on_create_user ) { Models::ActiveRecord::OnCreateCommentRequiredUser.create!( audit_comment: 'Create' ) }
926
- let( :on_update_user ) { Models::ActiveRecord::OnUpdateCommentRequiredUser.create }
1158
+ let(:user) { Models::ActiveRecord::CommentRequiredUser.create!(audit_comment: "Create") }
1159
+ let(:on_create_user) { Models::ActiveRecord::OnCreateCommentRequiredUser.create!(audit_comment: "Create") }
1160
+ let(:on_update_user) { Models::ActiveRecord::OnUpdateCommentRequiredUser.create }
927
1161
 
928
1162
  it "should not validate when audit_comment is not supplied" do
929
1163
  expect(user.destroy).to eq(false)
@@ -945,41 +1179,38 @@ describe Audited::Auditor do
945
1179
  Models::ActiveRecord::CommentRequiredUser.enable_auditing
946
1180
  end
947
1181
  end
948
-
949
1182
  end
950
1183
 
951
1184
  describe "no update with comment only" do
952
- let( :user ) { Models::ActiveRecord::NoUpdateWithCommentOnlyUser.create }
1185
+ let(:user) { Models::ActiveRecord::NoUpdateWithCommentOnlyUser.create }
953
1186
 
954
1187
  it "does not create an audit when only an audit_comment is present" do
955
1188
  user.audit_comment = "Comment"
956
- expect { user.save! }.to_not change( Audited::Audit, :count )
1189
+ expect { user.save! }.to_not change(Audited::Audit, :count)
957
1190
  end
958
-
959
1191
  end
960
1192
 
961
1193
  describe "attr_protected and attr_accessible" do
962
-
963
1194
  it "should not raise error when attr_accessible is set and protected is false" do
964
1195
  expect {
965
- Models::ActiveRecord::AccessibleAfterDeclarationUser.new(name: 'No fail!')
1196
+ Models::ActiveRecord::AccessibleAfterDeclarationUser.new(name: "No fail!")
966
1197
  }.to_not raise_error
967
1198
  end
968
1199
 
969
1200
  it "should not rause an error when attr_accessible is declared before audited" do
970
1201
  expect {
971
- Models::ActiveRecord::AccessibleAfterDeclarationUser.new(name: 'No fail!')
1202
+ Models::ActiveRecord::AccessibleAfterDeclarationUser.new(name: "No fail!")
972
1203
  }.to_not raise_error
973
1204
  end
974
1205
  end
975
1206
 
976
1207
  describe "audit_as" do
977
- let( :user ) { Models::ActiveRecord::User.create name: 'Testing' }
1208
+ let(:user) { Models::ActiveRecord::User.create name: "Testing" }
978
1209
 
979
1210
  it "should record user objects" do
980
- Models::ActiveRecord::Company.audit_as( user ) do
981
- company = Models::ActiveRecord::Company.create name: 'The auditors'
982
- company.update! name: 'The Auditors'
1211
+ Models::ActiveRecord::Company.audit_as(user) do
1212
+ company = Models::ActiveRecord::Company.create name: "The auditors"
1213
+ company.update! name: "The Auditors"
983
1214
 
984
1215
  company.audits.each do |audit|
985
1216
  expect(audit.user).to eq(user)
@@ -988,9 +1219,9 @@ describe Audited::Auditor do
988
1219
  end
989
1220
 
990
1221
  it "should record usernames" do
991
- Models::ActiveRecord::Company.audit_as( user.name ) do
992
- company = Models::ActiveRecord::Company.create name: 'The auditors'
993
- company.update! name: 'The Auditors'
1222
+ Models::ActiveRecord::Company.audit_as(user.name) do
1223
+ company = Models::ActiveRecord::Company.create name: "The auditors"
1224
+ company.update! name: "The Auditors"
994
1225
 
995
1226
  company.audits.each do |audit|
996
1227
  expect(audit.user).to eq(user.name)
@@ -1000,7 +1231,7 @@ describe Audited::Auditor do
1000
1231
  end
1001
1232
 
1002
1233
  describe "after_audit" do
1003
- let( :user ) { Models::ActiveRecord::UserWithAfterAudit.new }
1234
+ let(:user) { Models::ActiveRecord::UserWithAfterAudit.new }
1004
1235
 
1005
1236
  it "should invoke after_audit callback on create" do
1006
1237
  expect(user.bogus_attr).to be_nil
@@ -1010,7 +1241,7 @@ describe Audited::Auditor do
1010
1241
  end
1011
1242
 
1012
1243
  describe "around_audit" do
1013
- let( :user ) { Models::ActiveRecord::UserWithAfterAudit.new }
1244
+ let(:user) { Models::ActiveRecord::UserWithAfterAudit.new }
1014
1245
 
1015
1246
  it "should invoke around_audit callback on create" do
1016
1247
  expect(user.around_attr).to be_nil
@@ -1021,13 +1252,13 @@ describe Audited::Auditor do
1021
1252
 
1022
1253
  describe "STI auditing" do
1023
1254
  it "should correctly disable auditing when using STI" do
1024
- company = Models::ActiveRecord::Company::STICompany.create name: 'The auditors'
1255
+ company = Models::ActiveRecord::Company::STICompany.create name: "The auditors"
1025
1256
  expect(company.type).to eq("Models::ActiveRecord::Company::STICompany")
1026
1257
  expect {
1027
1258
  Models::ActiveRecord::Company.auditing_enabled = false
1028
- company.update! name: 'STI auditors'
1259
+ company.update! name: "STI auditors"
1029
1260
  Models::ActiveRecord::Company.auditing_enabled = true
1030
- }.to_not change( Audited::Audit, :count )
1261
+ }.to_not change(Audited::Audit, :count)
1031
1262
  end
1032
1263
  end
1033
1264
  end