velocity_audited 5.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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