audited 4.7.0 → 5.0.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.

Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -1
  3. data/.standard.yml +5 -0
  4. data/.travis.yml +35 -26
  5. data/Appraisals +27 -18
  6. data/CHANGELOG.md +106 -2
  7. data/Gemfile +1 -1
  8. data/README.md +88 -19
  9. data/Rakefile +6 -6
  10. data/gemfiles/rails50.gemfile +3 -0
  11. data/gemfiles/rails51.gemfile +3 -0
  12. data/gemfiles/rails52.gemfile +4 -2
  13. data/gemfiles/rails60.gemfile +10 -0
  14. data/gemfiles/rails61.gemfile +10 -0
  15. data/lib/audited-rspec.rb +3 -1
  16. data/lib/audited.rb +26 -8
  17. data/lib/audited/audit.rb +48 -43
  18. data/lib/audited/auditor.rb +135 -56
  19. data/lib/audited/railtie.rb +16 -0
  20. data/lib/audited/rspec_matchers.rb +5 -3
  21. data/lib/audited/sweeper.rb +3 -10
  22. data/lib/audited/version.rb +3 -1
  23. data/lib/generators/audited/install_generator.rb +9 -7
  24. data/lib/generators/audited/migration.rb +2 -0
  25. data/lib/generators/audited/migration_helper.rb +3 -1
  26. data/lib/generators/audited/templates/add_association_to_audits.rb +2 -0
  27. data/lib/generators/audited/templates/add_comment_to_audits.rb +2 -0
  28. data/lib/generators/audited/templates/add_remote_address_to_audits.rb +2 -0
  29. data/lib/generators/audited/templates/add_request_uuid_to_audits.rb +2 -0
  30. data/lib/generators/audited/templates/add_version_to_auditable_index.rb +23 -0
  31. data/lib/generators/audited/templates/install.rb +3 -1
  32. data/lib/generators/audited/templates/rename_association_to_associated.rb +2 -0
  33. data/lib/generators/audited/templates/rename_changes_to_audited_changes.rb +2 -0
  34. data/lib/generators/audited/templates/rename_parent_to_association.rb +2 -0
  35. data/lib/generators/audited/templates/revert_polymorphic_indexes_order.rb +2 -0
  36. data/lib/generators/audited/upgrade_generator.rb +20 -14
  37. data/spec/audited/audit_spec.rb +151 -62
  38. data/spec/audited/auditor_spec.rb +456 -239
  39. data/spec/audited/sweeper_spec.rb +29 -20
  40. data/spec/audited_spec.rb +18 -0
  41. data/spec/audited_spec_helpers.rb +7 -7
  42. data/spec/rails_app/app/assets/config/manifest.js +2 -0
  43. data/spec/rails_app/config/application.rb +7 -2
  44. data/spec/rails_app/config/database.yml +1 -0
  45. data/spec/rails_app/config/environment.rb +1 -1
  46. data/spec/rails_app/config/environments/test.rb +5 -5
  47. data/spec/rails_app/config/initializers/secret_token.rb +2 -2
  48. data/spec/spec_helper.rb +15 -13
  49. data/spec/support/active_record/models.rb +37 -11
  50. data/spec/support/active_record/postgres/1_change_audited_changes_type_to_json.rb +1 -2
  51. data/spec/support/active_record/postgres/2_change_audited_changes_type_to_jsonb.rb +1 -2
  52. data/spec/support/active_record/schema.rb +28 -20
  53. data/test/db/version_1.rb +2 -2
  54. data/test/db/version_2.rb +2 -2
  55. data/test/db/version_3.rb +2 -3
  56. data/test/db/version_4.rb +2 -3
  57. data/test/db/version_5.rb +0 -1
  58. data/test/db/version_6.rb +2 -0
  59. data/test/install_generator_test.rb +18 -19
  60. data/test/test_helper.rb +6 -7
  61. data/test/upgrade_generator_test.rb +22 -17
  62. metadata +64 -29
  63. data/gemfiles/rails40.gemfile +0 -9
  64. data/gemfiles/rails41.gemfile +0 -8
  65. data/gemfiles/rails42.gemfile +0 -8
  66. data/spec/rails_app/config/environments/development.rb +0 -21
  67. data/spec/rails_app/config/environments/production.rb +0 -35
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audited
4
+ class Railtie < Rails::Railtie
5
+ initializer "audited.sweeper" do
6
+ ActiveSupport.on_load(:action_controller) do
7
+ if defined?(ActionController::Base)
8
+ ActionController::Base.around_action Audited::Sweeper.new
9
+ end
10
+ if defined?(ActionController::API)
11
+ ActionController::API.around_action Audited::Sweeper.new
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Audited
2
4
  module RspecMatchers
3
5
  # Ensure that the model is audited.
@@ -78,9 +80,9 @@ module Audited
78
80
  def description
79
81
  description = "audited"
80
82
  description += " associated with #{@options[:associated_with]}" if @options.key?(:associated_with)
81
- description += " only => #{@options[:only].join ', '}" if @options.key?(:only)
82
- description += " except => #{@options[:except].join(', ')}" if @options.key?(:except)
83
- description += " requires audit_comment" if @options.key?(:comment_required)
83
+ description += " only => #{@options[:only].join ", "}" if @options.key?(:only)
84
+ description += " except => #{@options[:except].join(", ")}" if @options.key?(:except)
85
+ description += " requires audit_comment" if @options.key?(:comment_required)
84
86
 
85
87
  description
86
88
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Audited
2
4
  class Sweeper
3
5
  STORED_DATA = {
@@ -10,7 +12,7 @@ module Audited
10
12
 
11
13
  def around(controller)
12
14
  self.controller = controller
13
- STORED_DATA.each { |k,m| store[k] = send(m) }
15
+ STORED_DATA.each { |k, m| store[k] = send(m) }
14
16
  yield
15
17
  ensure
16
18
  self.controller = nil
@@ -38,12 +40,3 @@ module Audited
38
40
  end
39
41
  end
40
42
  end
41
-
42
- ActiveSupport.on_load(:action_controller) do
43
- if defined?(ActionController::Base)
44
- ActionController::Base.around_action Audited::Sweeper.new
45
- end
46
- if defined?(ActionController::API)
47
- ActionController::API.around_action Audited::Sweeper.new
48
- end
49
- end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Audited
2
- VERSION = "4.7.0"
4
+ VERSION = "5.0.0"
3
5
  end
@@ -1,9 +1,11 @@
1
- require 'rails/generators'
2
- require 'rails/generators/migration'
3
- require 'active_record'
4
- require 'rails/generators/active_record'
5
- require 'generators/audited/migration'
6
- require 'generators/audited/migration_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/migration"
5
+ require "active_record"
6
+ require "rails/generators/active_record"
7
+ require "generators/audited/migration"
8
+ require "generators/audited/migration_helper"
7
9
 
8
10
  module Audited
9
11
  module Generators
@@ -18,7 +20,7 @@ module Audited
18
20
  source_root File.expand_path("../templates", __FILE__)
19
21
 
20
22
  def copy_migration
21
- migration_template 'install.rb', 'db/migrate/install_audited.rb'
23
+ migration_template "install.rb", "db/migrate/install_audited.rb"
22
24
  end
23
25
  end
24
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Audited
2
4
  module Generators
3
5
  module Migration
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Audited
2
4
  module Generators
3
5
  module MigrationHelper
4
6
  def migration_parent
5
- Rails::VERSION::MAJOR == 4 ? 'ActiveRecord::Migration' : "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
7
+ "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
6
8
  end
7
9
  end
8
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_parent %>
2
4
  def self.up
3
5
  add_column :audits, :association_id, :integer
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_parent %>
2
4
  def self.up
3
5
  add_column :audits, :comment, :string
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_parent %>
2
4
  def self.up
3
5
  add_column :audits, :remote_address, :string
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_parent %>
2
4
  def self.up
3
5
  add_column :audits, :request_uuid, :string
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ if index_exists?(:audits, [:auditable_type, :auditable_id], name: index_name)
6
+ remove_index :audits, name: index_name
7
+ add_index :audits, [:auditable_type, :auditable_id, :version], name: index_name
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ if index_exists?(:audits, [:auditable_type, :auditable_id, :version], name: index_name)
13
+ remove_index :audits, name: index_name
14
+ add_index :audits, [:auditable_type, :auditable_id], name: index_name
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def index_name
21
+ 'auditable_index'
22
+ end
23
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_parent %>
2
4
  def self.up
3
5
  create_table :audits, :force => true do |t|
@@ -17,7 +19,7 @@ class <%= migration_class_name %> < <%= migration_parent %>
17
19
  t.column :created_at, :datetime
18
20
  end
19
21
 
20
- add_index :audits, [:auditable_type, :auditable_id], :name => 'auditable_index'
22
+ add_index :audits, [:auditable_type, :auditable_id, :version], :name => 'auditable_index'
21
23
  add_index :audits, [:associated_type, :associated_id], :name => 'associated_index'
22
24
  add_index :audits, [:user_id, :user_type], :name => 'user_index'
23
25
  add_index :audits, :request_uuid
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_parent %>
2
4
  def self.up
3
5
  if index_exists? :audits, [:association_id, :association_type], :name => 'association_index'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_parent %>
2
4
  def self.up
3
5
  rename_column :audits, :changes, :audited_changes
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_parent %>
2
4
  def self.up
3
5
  rename_column :audits, :auditable_parent_id, :association_id
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class <%= migration_class_name %> < <%= migration_parent %>
2
4
  def self.up
3
5
  fix_index_order_for [:associated_id, :associated_type], 'associated_index'
@@ -1,9 +1,11 @@
1
- require 'rails/generators'
2
- require 'rails/generators/migration'
3
- require 'active_record'
4
- require 'rails/generators/active_record'
5
- require 'generators/audited/migration'
6
- require 'generators/audited/migration_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/migration"
5
+ require "active_record"
6
+ require "rails/generators/active_record"
7
+ require "generators/audited/migration"
8
+ require "generators/audited/migration_helper"
7
9
 
8
10
  module Audited
9
11
  module Generators
@@ -27,37 +29,41 @@ module Audited
27
29
  columns = Audited::Audit.columns.map(&:name)
28
30
  indexes = Audited::Audit.connection.indexes(Audited::Audit.table_name)
29
31
 
30
- yield :add_comment_to_audits unless columns.include?('comment')
32
+ yield :add_comment_to_audits unless columns.include?("comment")
31
33
 
32
- if columns.include?('changes')
34
+ if columns.include?("changes")
33
35
  yield :rename_changes_to_audited_changes
34
36
  end
35
37
 
36
- unless columns.include?('remote_address')
38
+ unless columns.include?("remote_address")
37
39
  yield :add_remote_address_to_audits
38
40
  end
39
41
 
40
- unless columns.include?('request_uuid')
42
+ unless columns.include?("request_uuid")
41
43
  yield :add_request_uuid_to_audits
42
44
  end
43
45
 
44
- unless columns.include?('association_id')
45
- if columns.include?('auditable_parent_id')
46
+ unless columns.include?("association_id")
47
+ if columns.include?("auditable_parent_id")
46
48
  yield :rename_parent_to_association
47
49
  else
48
- unless columns.include?('associated_id')
50
+ unless columns.include?("associated_id")
49
51
  yield :add_association_to_audits
50
52
  end
51
53
  end
52
54
  end
53
55
 
54
- if columns.include?('association_id')
56
+ if columns.include?("association_id")
55
57
  yield :rename_association_to_associated
56
58
  end
57
59
 
58
60
  if indexes.any? { |i| i.columns == %w[associated_id associated_type] }
59
61
  yield :revert_polymorphic_indexes_order
60
62
  end
63
+
64
+ if indexes.any? { |i| i.columns == %w[auditable_type auditable_id] }
65
+ yield :add_version_to_auditable_index
66
+ end
61
67
  end
62
68
  end
63
69
  end
@@ -1,5 +1,28 @@
1
1
  require "spec_helper"
2
2
 
3
+ SingleCov.covered! uncovered: 1 # Rails version check
4
+
5
+ class CustomAudit < Audited::Audit
6
+ def custom_method
7
+ "I'm custom!"
8
+ end
9
+ end
10
+
11
+ class TempModel1 < ::ActiveRecord::Base
12
+ self.table_name = :companies
13
+ end
14
+
15
+ class TempModel2 < ::ActiveRecord::Base
16
+ self.table_name = :companies
17
+ end
18
+
19
+ class Models::ActiveRecord::CustomUser < ::ActiveRecord::Base
20
+ end
21
+
22
+ class Models::ActiveRecord::CustomUserSubclass < Models::ActiveRecord::CustomUser
23
+ audited
24
+ end
25
+
3
26
  describe Audited::Audit do
4
27
  let(:user) { Models::ActiveRecord::User.new name: "Testing" }
5
28
 
@@ -7,30 +30,17 @@ describe Audited::Audit do
7
30
  around(:example) do |example|
8
31
  original_audit_class = Audited.audit_class
9
32
 
10
- class CustomAudit < Audited::Audit
11
- def custom_method
12
- "I'm custom!"
13
- end
14
- end
15
-
16
- class TempModel < ::ActiveRecord::Base
17
- self.table_name = :companies
18
- end
19
-
20
33
  example.run
21
34
 
22
35
  Audited.config { |config| config.audit_class = original_audit_class }
23
- Audited::Audit.audited_class_names.delete("TempModel")
24
- Object.send(:remove_const, :TempModel)
25
- Object.send(:remove_const, :CustomAudit)
26
36
  end
27
37
 
28
38
  context "when a custom audit class is configured" do
29
39
  it "should be used in place of #{described_class}" do
30
40
  Audited.config { |config| config.audit_class = CustomAudit }
31
- TempModel.audited
41
+ TempModel1.audited
32
42
 
33
- record = TempModel.create
43
+ record = TempModel1.create
34
44
 
35
45
  audit = record.audits.first
36
46
  expect(audit).to be_a CustomAudit
@@ -38,43 +48,64 @@ describe Audited::Audit do
38
48
  end
39
49
  end
40
50
 
41
- it "should undo changes" do
42
- user = Models::ActiveRecord::User.create(name: "John")
43
- user.update_attribute(:name, 'Joe')
51
+ context "when a custom audit class is not configured" do
52
+ it "should default to #{described_class}" do
53
+ TempModel2.audited
54
+
55
+ record = TempModel2.create
56
+
57
+ audit = record.audits.first
58
+ expect(audit).to be_a Audited::Audit
59
+ expect(audit.respond_to?(:custom_method)).to be false
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#audited_changes" do
65
+ let(:audit) { Audited.audit_class.new }
66
+
67
+ it "can unserialize yaml from text columns" do
68
+ audit.audited_changes = {foo: "bar"}
69
+ expect(audit.audited_changes).to eq foo: "bar"
70
+ end
71
+
72
+ it "does not unserialize from binary columns" do
73
+ allow(Audited::YAMLIfTextColumnType).to receive(:text_column?).and_return(false)
74
+ audit.audited_changes = {foo: "bar"}
75
+ expect(audit.audited_changes).to eq "{:foo=>\"bar\"}"
76
+ end
77
+ end
78
+
79
+ describe "#undo" do
80
+ let(:user) { Models::ActiveRecord::User.create(name: "John") }
81
+
82
+ it "undos changes" do
83
+ user.update_attribute(:name, "Joe")
44
84
  user.audits.last.undo
45
85
  user.reload
46
-
47
86
  expect(user.name).to eq("John")
48
87
  end
49
88
 
50
- it "should undo destroyed model" do
51
- user = Models::ActiveRecord::User.create(name: "John")
89
+ it "undos destroy" do
52
90
  user.destroy
53
91
  user.audits.last.undo
54
92
  user = Models::ActiveRecord::User.find_by(name: "John")
55
93
  expect(user.name).to eq("John")
56
94
  end
57
95
 
58
- it "should undo created model" do
59
- user = Models::ActiveRecord::User.create(name: "John")
60
- expect {user.audits.last.undo}.to change(Models::ActiveRecord::User, :count).by(-1)
96
+ it "undos creation" do
97
+ user # trigger create
98
+ expect { user.audits.last.undo }.to change(Models::ActiveRecord::User, :count).by(-1)
61
99
  end
62
100
 
63
- context "when a custom audit class is not configured" do
64
- it "should default to #{described_class}" do
65
- TempModel.audited
66
-
67
- record = TempModel.create
68
-
69
- audit = record.audits.first
70
- expect(audit).to be_a Audited::Audit
71
- expect(audit.respond_to?(:custom_method)).to be false
72
- end
101
+ it "fails when trying to undo unknown" do
102
+ audit = user.audits.last
103
+ audit.action = "oops"
104
+ expect { audit.undo }.to raise_error("invalid action given oops")
73
105
  end
74
106
  end
75
107
 
76
108
  describe "user=" do
77
-
78
109
  it "should be able to set the user to a model object" do
79
110
  subject.user = user
80
111
  expect(subject.user).to eq(user)
@@ -82,8 +113,8 @@ describe Audited::Audit do
82
113
 
83
114
  it "should be able to set the user to nil" do
84
115
  subject.user_id = 1
85
- subject.user_type = 'Models::ActiveRecord::User'
86
- subject.username = 'joe'
116
+ subject.user_type = "Models::ActiveRecord::User"
117
+ subject.username = "joe"
87
118
 
88
119
  subject.user = nil
89
120
 
@@ -94,30 +125,28 @@ describe Audited::Audit do
94
125
  end
95
126
 
96
127
  it "should be able to set the user to a string" do
97
- subject.user = 'test'
98
- expect(subject.user).to eq('test')
128
+ subject.user = "test"
129
+ expect(subject.user).to eq("test")
99
130
  end
100
131
 
101
132
  it "should clear model when setting to a string" do
102
133
  subject.user = user
103
- subject.user = 'testing'
134
+ subject.user = "testing"
104
135
  expect(subject.user_id).to be_nil
105
136
  expect(subject.user_type).to be_nil
106
137
  end
107
138
 
108
139
  it "should clear the username when setting to a model" do
109
- subject.username = 'test'
140
+ subject.username = "test"
110
141
  subject.user = user
111
142
  expect(subject.username).to be_nil
112
143
  end
113
-
114
144
  end
115
145
 
116
146
  describe "revision" do
117
-
118
147
  it "should recreate attributes" do
119
148
  user = Models::ActiveRecord::User.create name: "1"
120
- 5.times {|i| user.update_attribute :name, (i + 2).to_s }
149
+ 5.times { |i| user.update_attribute :name, (i + 2).to_s }
121
150
 
122
151
  user.audits.each do |audit|
123
152
  expect(audit.revision.name).to eq(audit.version.to_s)
@@ -148,6 +177,34 @@ describe Audited::Audit do
148
177
  end
149
178
  end
150
179
 
180
+ describe ".collection_cache_key" do
181
+ if ActiveRecord::VERSION::MAJOR >= 5
182
+ it "uses created at" do
183
+ Audited::Audit.delete_all
184
+ audit = Models::ActiveRecord::User.create(name: "John").audits.last
185
+ audit.update_columns(created_at: Time.zone.parse("2018-01-01"))
186
+ expect(Audited::Audit.collection_cache_key).to match(/-20180101\d+$/)
187
+ end
188
+ else
189
+ it "is not defined" do
190
+ expect { Audited::Audit.collection_cache_key }.to raise_error(NoMethodError)
191
+ end
192
+ end
193
+ end
194
+
195
+ describe ".assign_revision_attributes" do
196
+ it "dups when frozen" do
197
+ user.freeze
198
+ assigned = Audited::Audit.assign_revision_attributes(user, name: "Bar")
199
+ expect(assigned.name).to eq "Bar"
200
+ end
201
+
202
+ it "ignores unassignable attributes" do
203
+ assigned = Audited::Audit.assign_revision_attributes(user, oops: "Bar")
204
+ expect(assigned.name).to eq "Testing"
205
+ end
206
+ end
207
+
151
208
  it "should set the version number on create" do
152
209
  user = Models::ActiveRecord::User.create! name: "Set Version Number"
153
210
  expect(user.audits.first.version).to eq(1)
@@ -171,12 +228,6 @@ describe Audited::Audit do
171
228
  end
172
229
 
173
230
  describe "audited_classes" do
174
- class Models::ActiveRecord::CustomUser < ::ActiveRecord::Base
175
- end
176
- class Models::ActiveRecord::CustomUserSubclass < Models::ActiveRecord::CustomUser
177
- audited
178
- end
179
-
180
231
  it "should include audited classes" do
181
232
  expect(Audited::Audit.audited_classes).to include(Models::ActiveRecord::User)
182
233
  end
@@ -187,17 +238,37 @@ describe Audited::Audit do
187
238
  end
188
239
 
189
240
  describe "new_attributes" do
190
- it "should return a hash of the new values" do
191
- new_attributes = Audited::Audit.new(audited_changes: {a: [1, 2], b: [3, 4]}).new_attributes
241
+ it "should return the audited_changes without modification for create" do
242
+ new_attributes = Audited::Audit.new(audited_changes: {int: 1, array: [1]}, action: :create).new_attributes
243
+ expect(new_attributes).to eq({"int" => 1, "array" => [1]})
244
+ end
245
+
246
+ it "should return a hash that contains the after values of each attribute" do
247
+ new_attributes = Audited::Audit.new(audited_changes: {a: [1, 2], b: [3, 4]}, action: :update).new_attributes
192
248
  expect(new_attributes).to eq({"a" => 2, "b" => 4})
193
249
  end
250
+
251
+ it "should return the audited_changes without modification for destroy" do
252
+ new_attributes = Audited::Audit.new(audited_changes: {int: 1, array: [1]}, action: :destroy).new_attributes
253
+ expect(new_attributes).to eq({"int" => 1, "array" => [1]})
254
+ end
194
255
  end
195
256
 
196
257
  describe "old_attributes" do
197
- it "should return a hash of the old values" do
198
- old_attributes = Audited::Audit.new(audited_changes: {a: [1, 2], b: [3, 4]}).old_attributes
258
+ it "should return the audited_changes without modification for create" do
259
+ old_attributes = Audited::Audit.new(audited_changes: {int: 1, array: [1]}, action: :create).new_attributes
260
+ expect(old_attributes).to eq({"int" => 1, "array" => [1]})
261
+ end
262
+
263
+ it "should return a hash that contains the before values of each attribute" do
264
+ old_attributes = Audited::Audit.new(audited_changes: {a: [1, 2], b: [3, 4]}, action: :update).old_attributes
199
265
  expect(old_attributes).to eq({"a" => 1, "b" => 3})
200
266
  end
267
+
268
+ it "should return the audited_changes without modification for destroy" do
269
+ old_attributes = Audited::Audit.new(audited_changes: {int: 1, array: [1]}, action: :destroy).old_attributes
270
+ expect(old_attributes).to eq({"int" => 1, "array" => [1]})
271
+ end
201
272
  end
202
273
 
203
274
  describe "as_user" do
@@ -213,6 +284,25 @@ describe Audited::Audit do
213
284
  end
214
285
  end
215
286
 
287
+ it "should support nested as_user" do
288
+ Audited::Audit.as_user("sidekiq") do
289
+ company = Models::ActiveRecord::Company.create name: "The auditors"
290
+ company.name = "The Auditors, Inc"
291
+ company.save
292
+ expect(company.audits[-1].user).to eq("sidekiq")
293
+
294
+ Audited::Audit.as_user(user) do
295
+ company.name = "NEW Auditors, Inc"
296
+ company.save
297
+ expect(company.audits[-1].user).to eq(user)
298
+ end
299
+
300
+ company.name = "LAST Auditors, Inc"
301
+ company.save
302
+ expect(company.audits[-1].user).to eq("sidekiq")
303
+ end
304
+ end
305
+
216
306
  it "should record usernames" do
217
307
  Audited::Audit.as_user(user.name) do
218
308
  company = Models::ActiveRecord::Company.create name: "The auditors"
@@ -225,8 +315,8 @@ describe Audited::Audit do
225
315
  end
226
316
  end
227
317
 
228
- it "should be thread safe" do
229
- begin
318
+ if ActiveRecord::Base.connection.adapter_name != "SQLite"
319
+ it "should be thread safe" do
230
320
  expect(user.save).to eq(true)
231
321
 
232
322
  t1 = Thread.new do
@@ -246,10 +336,10 @@ describe Audited::Audit do
246
336
  t1.join
247
337
  t2.join
248
338
  end
249
- end if ActiveRecord::Base.connection.adapter_name != 'SQLite'
339
+ end
250
340
 
251
341
  it "should return the value from the yield block" do
252
- result = Audited::Audit.as_user('foo') do
342
+ result = Audited::Audit.as_user("foo") do
253
343
  42
254
344
  end
255
345
  expect(result).to eq(42)
@@ -257,12 +347,11 @@ describe Audited::Audit do
257
347
 
258
348
  it "should reset audited_user when the yield block raises an exception" do
259
349
  expect {
260
- Audited::Audit.as_user('foo') do
261
- raise StandardError.new('expected')
350
+ Audited::Audit.as_user("foo") do
351
+ raise StandardError.new("expected")
262
352
  end
263
- }.to raise_exception('expected')
353
+ }.to raise_exception("expected")
264
354
  expect(Audited.store[:audited_user]).to be_nil
265
355
  end
266
-
267
356
  end
268
357
  end