velocity_audited 5.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +115 -0
  3. data/.gitignore +17 -0
  4. data/.standard.yml +5 -0
  5. data/.yardopts +3 -0
  6. data/Appraisals +44 -0
  7. data/CHANGELOG.md +419 -0
  8. data/Gemfile +3 -0
  9. data/LICENSE +19 -0
  10. data/README.md +433 -0
  11. data/Rakefile +18 -0
  12. data/gemfiles/rails50.gemfile +10 -0
  13. data/gemfiles/rails51.gemfile +10 -0
  14. data/gemfiles/rails52.gemfile +10 -0
  15. data/gemfiles/rails60.gemfile +10 -0
  16. data/gemfiles/rails61.gemfile +10 -0
  17. data/gemfiles/rails70.gemfile +10 -0
  18. data/lib/audited/audit.rb +198 -0
  19. data/lib/audited/auditor.rb +476 -0
  20. data/lib/audited/railtie.rb +16 -0
  21. data/lib/audited/rspec_matchers.rb +228 -0
  22. data/lib/audited/sweeper.rb +67 -0
  23. data/lib/audited/version.rb +5 -0
  24. data/lib/audited-rspec.rb +6 -0
  25. data/lib/audited.rb +49 -0
  26. data/lib/generators/audited/install_generator.rb +27 -0
  27. data/lib/generators/audited/migration.rb +17 -0
  28. data/lib/generators/audited/migration_helper.rb +11 -0
  29. data/lib/generators/audited/templates/add_association_to_audits.rb +13 -0
  30. data/lib/generators/audited/templates/add_comment_to_audits.rb +11 -0
  31. data/lib/generators/audited/templates/add_remote_address_to_audits.rb +12 -0
  32. data/lib/generators/audited/templates/add_request_uuid_to_audits.rb +12 -0
  33. data/lib/generators/audited/templates/add_version_to_auditable_index.rb +23 -0
  34. data/lib/generators/audited/templates/install.rb +32 -0
  35. data/lib/generators/audited/templates/rename_association_to_associated.rb +25 -0
  36. data/lib/generators/audited/templates/rename_changes_to_audited_changes.rb +11 -0
  37. data/lib/generators/audited/templates/rename_parent_to_association.rb +13 -0
  38. data/lib/generators/audited/templates/revert_polymorphic_indexes_order.rb +22 -0
  39. data/lib/generators/audited/upgrade_generator.rb +70 -0
  40. data/lib/velocity_audited.rb +5 -0
  41. data/spec/audited/audit_spec.rb +357 -0
  42. data/spec/audited/auditor_spec.rb +1097 -0
  43. data/spec/audited/rspec_matchers_spec.rb +69 -0
  44. data/spec/audited/sweeper_spec.rb +133 -0
  45. data/spec/audited_spec.rb +18 -0
  46. data/spec/audited_spec_helpers.rb +32 -0
  47. data/spec/rails_app/app/assets/config/manifest.js +2 -0
  48. data/spec/rails_app/config/application.rb +13 -0
  49. data/spec/rails_app/config/database.yml +26 -0
  50. data/spec/rails_app/config/environment.rb +5 -0
  51. data/spec/rails_app/config/environments/test.rb +47 -0
  52. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  53. data/spec/rails_app/config/initializers/inflections.rb +2 -0
  54. data/spec/rails_app/config/initializers/secret_token.rb +3 -0
  55. data/spec/rails_app/config/routes.rb +3 -0
  56. data/spec/spec_helper.rb +24 -0
  57. data/spec/support/active_record/models.rb +151 -0
  58. data/spec/support/active_record/postgres/1_change_audited_changes_type_to_json.rb +11 -0
  59. data/spec/support/active_record/postgres/2_change_audited_changes_type_to_jsonb.rb +11 -0
  60. data/spec/support/active_record/schema.rb +90 -0
  61. data/test/db/version_1.rb +17 -0
  62. data/test/db/version_2.rb +18 -0
  63. data/test/db/version_3.rb +18 -0
  64. data/test/db/version_4.rb +19 -0
  65. data/test/db/version_5.rb +17 -0
  66. data/test/db/version_6.rb +19 -0
  67. data/test/install_generator_test.rb +62 -0
  68. data/test/test_helper.rb +18 -0
  69. data/test/upgrade_generator_test.rb +97 -0
  70. metadata +260 -0
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audited
4
+ module RspecMatchers
5
+ # Ensure that the model is audited.
6
+ #
7
+ # Options:
8
+ # * <tt>associated_with</tt> - tests that the audit makes use of the associated_with option
9
+ # * <tt>only</tt> - tests that the audit makes use of the only option *Overrides <tt>except</tt> option*
10
+ # * <tt>except</tt> - tests that the audit makes use of the except option
11
+ # * <tt>requires_comment</tt> - if specified, then the audit must require comments through the <tt>audit_comment</tt> attribute
12
+ # * <tt>on</tt> - tests that the audit makes use of the on option with specified parameters
13
+ #
14
+ # Example:
15
+ # it { should be_audited }
16
+ # it { should be_audited.associated_with(:user) }
17
+ # it { should be_audited.only(:field_name) }
18
+ # it { should be_audited.except(:password) }
19
+ # it { should be_audited.requires_comment }
20
+ # it { should be_audited.on(:create).associated_with(:user).except(:password) }
21
+ #
22
+ def be_audited
23
+ AuditMatcher.new
24
+ end
25
+
26
+ # Ensure that the model has associated audits
27
+ #
28
+ # Example:
29
+ # it { should have_associated_audits }
30
+ #
31
+ def have_associated_audits
32
+ AssociatedAuditMatcher.new
33
+ end
34
+
35
+ class AuditMatcher # :nodoc:
36
+ def initialize
37
+ @options = {}
38
+ end
39
+
40
+ def associated_with(model)
41
+ @options[:associated_with] = model
42
+ self
43
+ end
44
+
45
+ def only(*fields)
46
+ @options[:only] = fields.flatten.map(&:to_s)
47
+ self
48
+ end
49
+
50
+ def except(*fields)
51
+ @options[:except] = fields.flatten.map(&:to_s)
52
+ self
53
+ end
54
+
55
+ def requires_comment
56
+ @options[:comment_required] = true
57
+ self
58
+ end
59
+
60
+ def on(*actions)
61
+ @options[:on] = actions.flatten.map(&:to_sym)
62
+ self
63
+ end
64
+
65
+ def matches?(subject)
66
+ @subject = subject
67
+ auditing_enabled? && required_checks_for_options_satisfied?
68
+ end
69
+
70
+ def failure_message
71
+ "Expected #{@expectation}"
72
+ end
73
+
74
+ def negative_failure_message
75
+ "Did not expect #{@expectation}"
76
+ end
77
+
78
+ alias_method :failure_message_when_negated, :negative_failure_message
79
+
80
+ def description
81
+ description = "audited"
82
+ description += " associated with #{@options[:associated_with]}" if @options.key?(:associated_with)
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)
86
+
87
+ description
88
+ end
89
+
90
+ protected
91
+
92
+ def expects(message)
93
+ @expectation = message
94
+ end
95
+
96
+ def auditing_enabled?
97
+ expects "#{model_class} to be audited"
98
+ model_class.respond_to?(:auditing_enabled) && model_class.auditing_enabled
99
+ end
100
+
101
+ def model_class
102
+ @subject.class
103
+ end
104
+
105
+ def associated_with_model?
106
+ expects "#{model_class} to record audits to associated model #{@options[:associated_with]}"
107
+ model_class.audit_associated_with == @options[:associated_with]
108
+ end
109
+
110
+ def records_changes_to_specified_fields?
111
+ ignored_fields = build_ignored_fields_from_options
112
+
113
+ expects "non audited columns (#{model_class.non_audited_columns.inspect}) to match (#{ignored_fields})"
114
+ model_class.non_audited_columns.to_set == ignored_fields.to_set
115
+ end
116
+
117
+ def comment_required_valid?
118
+ expects "to require audit_comment before #{model_class.audited_options[:on]} when comment required"
119
+ validate_callbacks_include_presence_of_comment? && destroy_callbacks_include_comment_required?
120
+ end
121
+
122
+ def only_audit_on_designated_callbacks?
123
+ {
124
+ create: [:after, :audit_create],
125
+ update: [:before, :audit_update],
126
+ destroy: [:before, :audit_destroy]
127
+ }.map do |(action, kind_callback)|
128
+ kind, callback = kind_callback
129
+ callbacks_for(action, kind: kind).include?(callback) if @options[:on].include?(action)
130
+ end.compact.all?
131
+ end
132
+
133
+ def validate_callbacks_include_presence_of_comment?
134
+ if @options[:comment_required] && audited_on_create_or_update?
135
+ callbacks_for(:validate).include?(:presence_of_audit_comment)
136
+ else
137
+ true
138
+ end
139
+ end
140
+
141
+ def audited_on_create_or_update?
142
+ model_class.audited_options[:on].include?(:create) || model_class.audited_options[:on].include?(:update)
143
+ end
144
+
145
+ def destroy_callbacks_include_comment_required?
146
+ if @options[:comment_required] && model_class.audited_options[:on].include?(:destroy)
147
+ callbacks_for(:destroy).include?(:require_comment)
148
+ else
149
+ true
150
+ end
151
+ end
152
+
153
+ def requires_comment_before_callbacks?
154
+ [:create, :update, :destroy].map do |action|
155
+ if @options[:comment_required] && model_class.audited_options[:on].include?(action)
156
+ callbacks_for(action).include?(:require_comment)
157
+ end
158
+ end.compact.all?
159
+ end
160
+
161
+ def callbacks_for(action, kind: :before)
162
+ model_class.send("_#{action}_callbacks").select { |cb| cb.kind == kind }.map(&:filter)
163
+ end
164
+
165
+ def build_ignored_fields_from_options
166
+ default_ignored_attributes = model_class.default_ignored_attributes
167
+
168
+ if @options[:only].present?
169
+ (default_ignored_attributes | model_class.column_names) - @options[:only]
170
+ elsif @options[:except].present?
171
+ default_ignored_attributes | @options[:except]
172
+ else
173
+ default_ignored_attributes
174
+ end
175
+ end
176
+
177
+ def required_checks_for_options_satisfied?
178
+ {
179
+ only: :records_changes_to_specified_fields?,
180
+ except: :records_changes_to_specified_fields?,
181
+ comment_required: :comment_required_valid?,
182
+ associated_with: :associated_with_model?,
183
+ on: :only_audit_on_designated_callbacks?
184
+ }.map do |(option, check)|
185
+ send(check) if @options[option].present?
186
+ end.compact.all?
187
+ end
188
+ end
189
+
190
+ class AssociatedAuditMatcher # :nodoc:
191
+ def matches?(subject)
192
+ @subject = subject
193
+
194
+ association_exists?
195
+ end
196
+
197
+ def failure_message
198
+ "Expected #{model_class} to have associated audits"
199
+ end
200
+
201
+ def negative_failure_message
202
+ "Expected #{model_class} to not have associated audits"
203
+ end
204
+
205
+ alias_method :failure_message_when_negated, :negative_failure_message
206
+
207
+ def description
208
+ "has associated audits"
209
+ end
210
+
211
+ protected
212
+
213
+ def model_class
214
+ @subject.class
215
+ end
216
+
217
+ def reflection
218
+ model_class.reflect_on_association(:associated_audits)
219
+ end
220
+
221
+ def association_exists?
222
+ !reflection.nil? &&
223
+ reflection.macro == :has_many &&
224
+ reflection.options[:class_name] == Audited.audit_class.name
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audited
4
+ class Sweeper
5
+ STORED_DATA = {
6
+ current_remote_address: :remote_ip,
7
+ current_request_uuid: :request_uuid,
8
+ current_user: :current_user,
9
+ origin: :origin,
10
+ user_agent: :user_agent,
11
+ ip: :ip,
12
+ uid: :uid,
13
+ client: :client
14
+ }
15
+
16
+ delegate :store, to: ::Audited
17
+
18
+ def around(controller)
19
+ self.controller = controller
20
+ STORED_DATA.each { |k, m| store[k] = send(m) }
21
+ yield
22
+ ensure
23
+ self.controller = nil
24
+ STORED_DATA.keys.each { |k| store.delete(k) }
25
+ end
26
+
27
+ def current_user
28
+ lambda { controller.send(Audited.current_user_method) if controller.respond_to?(Audited.current_user_method, true) }
29
+ end
30
+
31
+ def remote_ip
32
+ controller.try(:request).try(:remote_ip)
33
+ end
34
+
35
+ def request_uuid
36
+ controller.try(:request).try(:uuid)
37
+ end
38
+
39
+ def origin
40
+ controller.try(:request).try(:headers)['Origin']
41
+ end
42
+
43
+ def user_agent
44
+ controller.try(:request).try(:headers)['User-Agent']
45
+ end
46
+
47
+ def ip
48
+ controller.try(:request).try(:headers)['HTTP_X_FORWARDED_FOR']
49
+ end
50
+
51
+ def uid
52
+ controller.try(:request).try(:headers)['uid']
53
+ end
54
+
55
+ def client
56
+ controller.try(:request).try(:headers)['client']
57
+ end
58
+
59
+ def controller
60
+ store[:current_controller]
61
+ end
62
+
63
+ def controller=(value)
64
+ store[:current_controller] = value
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audited
4
+ VERSION = "5.1.3"
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "audited/rspec_matchers"
4
+ module RSpec::Matchers
5
+ include Audited::RspecMatchers
6
+ end
data/lib/audited.rb ADDED
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+
5
+ module Audited
6
+ class << self
7
+ attr_accessor \
8
+ :auditing_enabled,
9
+ :current_user_method,
10
+ :ignored_attributes,
11
+ :max_audits,
12
+ :store_synthesized_enums
13
+ attr_writer :audit_class
14
+
15
+ def audit_class
16
+ @audit_class ||= Audit
17
+ end
18
+
19
+ def store
20
+ current_store_value = Thread.current.thread_variable_get(:audited_store)
21
+
22
+ if current_store_value.nil?
23
+ Thread.current.thread_variable_set(:audited_store, {})
24
+ else
25
+ current_store_value
26
+ end
27
+ end
28
+
29
+ def config
30
+ yield(self)
31
+ end
32
+ end
33
+
34
+ @ignored_attributes = %w[lock_version created_at updated_at created_on updated_on]
35
+
36
+ @current_user_method = :current_user
37
+ @auditing_enabled = true
38
+ @store_synthesized_enums = false
39
+ end
40
+
41
+ require "audited/auditor"
42
+
43
+ ActiveSupport.on_load :active_record do
44
+ require "audited/audit"
45
+ include Audited::Auditor
46
+ end
47
+
48
+ require "audited/sweeper"
49
+ require "audited/railtie"
@@ -0,0 +1,27 @@
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"
9
+
10
+ module Audited
11
+ module Generators
12
+ class InstallGenerator < Rails::Generators::Base
13
+ include Rails::Generators::Migration
14
+ include Audited::Generators::MigrationHelper
15
+ extend Audited::Generators::Migration
16
+
17
+ class_option :audited_changes_column_type, type: :string, default: "text", required: false
18
+ class_option :audited_user_id_column_type, type: :string, default: "integer", required: false
19
+
20
+ source_root File.expand_path("../templates", __FILE__)
21
+
22
+ def copy_migration
23
+ migration_template "install.rb", "db/migrate/install_audited.rb"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audited
4
+ module Generators
5
+ module Migration
6
+ # Implement the required interface for Rails::Generators::Migration.
7
+ def next_migration_number(dirname) #:nodoc:
8
+ next_migration_number = current_migration_number(dirname) + 1
9
+ if ::ActiveRecord::Base.timestamped_migrations
10
+ [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
11
+ else
12
+ "%.3d" % next_migration_number
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audited
4
+ module Generators
5
+ module MigrationHelper
6
+ def migration_parent
7
+ "ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ add_column :audits, :association_id, :integer
6
+ add_column :audits, :association_type, :string
7
+ end
8
+
9
+ def self.down
10
+ remove_column :audits, :association_type
11
+ remove_column :audits, :association_id
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ add_column :audits, :comment, :string
6
+ end
7
+
8
+ def self.down
9
+ remove_column :audits, :comment
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ add_column :audits, :remote_address, :string
6
+ end
7
+
8
+ def self.down
9
+ remove_column :audits, :remote_address
10
+ end
11
+ end
12
+
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ add_column :audits, :request_uuid, :string
6
+ add_index :audits, :request_uuid
7
+ end
8
+
9
+ def self.down
10
+ remove_column :audits, :request_uuid
11
+ end
12
+ end
@@ -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
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ create_table :audits, :force => true do |t|
6
+ t.column :auditable_id, :integer
7
+ t.column :auditable_type, :string
8
+ t.column :associated_id, :integer
9
+ t.column :associated_type, :string
10
+ t.column :user_id, :<%= options[:audited_user_id_column_type] %>
11
+ t.column :user_type, :string
12
+ t.column :username, :string
13
+ t.column :action, :string
14
+ t.column :audited_changes, :<%= options[:audited_changes_column_type] %>
15
+ t.column :version, :integer, :default => 0
16
+ t.column :comment, :string
17
+ t.column :remote_address, :string
18
+ t.column :request_uuid, :string
19
+ t.column :created_at, :datetime
20
+ end
21
+
22
+ add_index :audits, [:auditable_type, :auditable_id, :version], :name => 'auditable_index'
23
+ add_index :audits, [:associated_type, :associated_id], :name => 'associated_index'
24
+ add_index :audits, [:user_id, :user_type], :name => 'user_index'
25
+ add_index :audits, :request_uuid
26
+ add_index :audits, :created_at
27
+ end
28
+
29
+ def self.down
30
+ drop_table :audits
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ if index_exists? :audits, [:association_id, :association_type], :name => 'association_index'
6
+ remove_index :audits, :name => 'association_index'
7
+ end
8
+
9
+ rename_column :audits, :association_id, :associated_id
10
+ rename_column :audits, :association_type, :associated_type
11
+
12
+ add_index :audits, [:associated_id, :associated_type], :name => 'associated_index'
13
+ end
14
+
15
+ def self.down
16
+ if index_exists? :audits, [:associated_id, :associated_type], :name => 'associated_index'
17
+ remove_index :audits, :name => 'associated_index'
18
+ end
19
+
20
+ rename_column :audits, :associated_type, :association_type
21
+ rename_column :audits, :associated_id, :association_id
22
+
23
+ add_index :audits, [:association_id, :association_type], :name => 'association_index'
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ rename_column :audits, :changes, :audited_changes
6
+ end
7
+
8
+ def self.down
9
+ rename_column :audits, :audited_changes, :changes
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ rename_column :audits, :auditable_parent_id, :association_id
6
+ rename_column :audits, :auditable_parent_type, :association_type
7
+ end
8
+
9
+ def self.down
10
+ rename_column :audits, :association_type, :auditable_parent_type
11
+ rename_column :audits, :association_id, :auditable_parent_id
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= migration_class_name %> < <%= migration_parent %>
4
+ def self.up
5
+ fix_index_order_for [:associated_id, :associated_type], 'associated_index'
6
+ fix_index_order_for [:auditable_id, :auditable_type], 'auditable_index'
7
+ end
8
+
9
+ def self.down
10
+ fix_index_order_for [:associated_type, :associated_id], 'associated_index'
11
+ fix_index_order_for [:auditable_type, :auditable_id], 'auditable_index'
12
+ end
13
+
14
+ private
15
+
16
+ def fix_index_order_for(columns, index_name)
17
+ if index_exists? :audits, columns, name: index_name
18
+ remove_index :audits, name: index_name
19
+ add_index :audits, columns.reverse, name: index_name
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,70 @@
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"
9
+
10
+ module Audited
11
+ module Generators
12
+ class UpgradeGenerator < Rails::Generators::Base
13
+ include Rails::Generators::Migration
14
+ include Audited::Generators::MigrationHelper
15
+ extend Audited::Generators::Migration
16
+
17
+ source_root File.expand_path("../templates", __FILE__)
18
+
19
+ def copy_templates
20
+ migrations_to_be_applied do |m|
21
+ migration_template "#{m}.rb", "db/migrate/#{m}.rb"
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def migrations_to_be_applied
28
+ Audited::Audit.reset_column_information
29
+ columns = Audited::Audit.columns.map(&:name)
30
+ indexes = Audited::Audit.connection.indexes(Audited::Audit.table_name)
31
+
32
+ yield :add_comment_to_audits unless columns.include?("comment")
33
+
34
+ if columns.include?("changes")
35
+ yield :rename_changes_to_audited_changes
36
+ end
37
+
38
+ unless columns.include?("remote_address")
39
+ yield :add_remote_address_to_audits
40
+ end
41
+
42
+ unless columns.include?("request_uuid")
43
+ yield :add_request_uuid_to_audits
44
+ end
45
+
46
+ unless columns.include?("association_id")
47
+ if columns.include?("auditable_parent_id")
48
+ yield :rename_parent_to_association
49
+ else
50
+ unless columns.include?("associated_id")
51
+ yield :add_association_to_audits
52
+ end
53
+ end
54
+ end
55
+
56
+ if columns.include?("association_id")
57
+ yield :rename_association_to_associated
58
+ end
59
+
60
+ if indexes.any? { |i| i.columns == %w[associated_id associated_type] }
61
+ yield :revert_polymorphic_indexes_order
62
+ end
63
+
64
+ if indexes.any? { |i| i.columns == %w[auditable_type auditable_id] }
65
+ yield :add_version_to_auditable_index
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,5 @@
1
+
2
+ module VelocityAudited
3
+ include Audited
4
+
5
+ end