whodunit 0.4.1 → 0.5.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +17 -3
- data/README.md +36 -0
- data/lib/whodunit/generator.rb +6 -3
- data/lib/whodunit/migration_helpers.rb +112 -28
- data/lib/whodunit/stampable.rb +1 -1
- data/lib/whodunit/table_definition_extension.rb +11 -3
- data/lib/whodunit/version.rb +1 -1
- data/lib/whodunit.rb +24 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c21f2da7abe6b4a2b1440a155e75f28e8e73fea5bcd5cc4169a8c07c49a02c4
|
|
4
|
+
data.tar.gz: f1e0a0978d93eeff03293f1fe92b1aabcc536bd043e2972b28d360dd4c9e4259
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8a42ff533dd671e32a8a409a8bdd90ddb74b3dd34ab015cdfccabaee192761e8b1f629ff145cc22bf9db08d131e63009c1698a730710177434c2b46337f2a893
|
|
7
|
+
data.tar.gz: 9d5663c7629baa96a6076c6e3b8e4b4f201ced618653e5a27e3a8273db0bfe3ae7a99b6451518361af04e2793a4f0d17564f0959c33dc3028cdd34fe82d0ce9d
|
data/.rubocop.yml
CHANGED
|
@@ -43,6 +43,11 @@ Metrics/MethodLength:
|
|
|
43
43
|
Metrics/ModuleLength:
|
|
44
44
|
Exclude:
|
|
45
45
|
- 'lib/whodunit.rb'
|
|
46
|
+
- 'lib/whodunit/migration_helpers.rb'
|
|
47
|
+
|
|
48
|
+
Metrics/ParameterLists:
|
|
49
|
+
Exclude:
|
|
50
|
+
- 'lib/whodunit/migration_helpers.rb'
|
|
46
51
|
|
|
47
52
|
# RSpec specific configurations
|
|
48
53
|
RSpec/ExampleLength:
|
|
@@ -113,6 +118,7 @@ Metrics/AbcSize:
|
|
|
113
118
|
Max: 20
|
|
114
119
|
Exclude:
|
|
115
120
|
- 'spec/**/*'
|
|
121
|
+
- 'lib/whodunit/migration_helpers.rb'
|
|
116
122
|
|
|
117
123
|
Metrics/CyclomaticComplexity:
|
|
118
124
|
Max: 10
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Unreleased
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
## [0.5.0] - 2026-08-20
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added `auto_create_user_fk_constraints` configuration for automatically creating foreign-key constraints from creator, updater, and deleter stamp columns to the configured user table.
|
|
10
|
+
- Added `user_class_table_name` for explicitly overriding the inferred user table name.
|
|
11
|
+
- Added per-migration overrides for automatic user foreign-key creation.
|
|
12
|
+
- Added automatic injection of the configured soft-delete timestamp alongside the deleter stamp column.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Made stamp auto-injection idempotent when migrations already declare stamp columns or matching foreign keys.
|
|
17
|
+
- Removed stamp foreign-key constraints before removing stamp columns in migration helpers.
|
|
18
|
+
- Avoided loading the configured user model while migrations infer its table name, preventing failures when the user table is being created in the same migration.
|
|
19
|
+
- Skipped automatic stamp and user-FK injection for Rails internal metadata tables during database setup.
|
|
20
|
+
- Made `require "whodunit"` safe before Active Record loads by deferring migration integration until Active Record is available.
|
|
7
21
|
|
|
8
22
|
## [0.4.1] - 2026-06-01
|
|
9
23
|
|
data/README.md
CHANGED
|
@@ -208,6 +208,8 @@ Whodunit.configure do |config|
|
|
|
208
208
|
config.deleter_column = :deleted_by_id # Default: :deleter_id
|
|
209
209
|
config.soft_delete_column = :discarded_at # Default: nil
|
|
210
210
|
config.auto_inject_whodunit_stamps = false # Default: true
|
|
211
|
+
config.auto_create_user_fk_constraints = false # Default: false
|
|
212
|
+
# config.user_class_table_name = :accounts # Optional explicit table name
|
|
211
213
|
|
|
212
214
|
# Reverse association configuration
|
|
213
215
|
config.auto_setup_reverse_associations = false # Default: true
|
|
@@ -222,6 +224,40 @@ Whodunit.configure do |config|
|
|
|
222
224
|
end
|
|
223
225
|
```
|
|
224
226
|
|
|
227
|
+
When `auto_create_user_fk_constraints` is enabled, migration helpers add
|
|
228
|
+
foreign-key constraints from the configured creator, updater, and deleter
|
|
229
|
+
columns to the configured user table. The user table is inferred from
|
|
230
|
+
`user_class` unless `user_class_table_name` is set explicitly.
|
|
231
|
+
For the standard `User` model, Whodunit infers `users`; setting
|
|
232
|
+
`user_class_table_name` is not required. Use it only when the model maps to a
|
|
233
|
+
nonstandard table name or when you want to make that mapping explicit.
|
|
234
|
+
|
|
235
|
+
**Caution:** the referenced user table must be created before migrations that
|
|
236
|
+
create these foreign keys. The user model is not loaded while resolving the
|
|
237
|
+
table name, so a user table can safely use automatic stamps in its own
|
|
238
|
+
migration. Use `auto_create_user_fk_constraints: false` for migrations that
|
|
239
|
+
must run before the user table exists.
|
|
240
|
+
|
|
241
|
+
Automatic injection intentionally skips Rails internal metadata tables such as
|
|
242
|
+
`ar_internal_metadata` and `schema_migrations`.
|
|
243
|
+
|
|
244
|
+
When `soft_delete_column` is configured, `include_deleter: :auto` also adds
|
|
245
|
+
the configured soft-delete timestamp and deleter columns to new tables. The
|
|
246
|
+
injection is idempotent when either column was declared explicitly. Pass
|
|
247
|
+
`include_deleter: false` to omit only the deleter audit column for a specific
|
|
248
|
+
table.
|
|
249
|
+
|
|
250
|
+
The setting can be overridden for an individual migration:
|
|
251
|
+
|
|
252
|
+
```ruby
|
|
253
|
+
create_table :posts do |t|
|
|
254
|
+
t.timestamps
|
|
255
|
+
t.whodunit_stamps auto_create_user_fk_constraints: false
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
add_whodunit_stamps :legacy_posts, auto_create_user_fk_constraints: true
|
|
259
|
+
```
|
|
260
|
+
|
|
225
261
|
### Data Type Configuration
|
|
226
262
|
|
|
227
263
|
By default, all stamp columns use `:bigint` data type. You can customize this in several ways:
|
data/lib/whodunit/generator.rb
CHANGED
|
@@ -26,7 +26,7 @@ module Whodunit
|
|
|
26
26
|
# config.updater_column = :updated_by_id # Default: :updater_id
|
|
27
27
|
# # Column that stores who last updated the record
|
|
28
28
|
# config.deleter_column = :deleted_by_id # Default: :deleter_id
|
|
29
|
-
# # Column that stores who
|
|
29
|
+
# # Column that stores who performed the delete operation
|
|
30
30
|
#
|
|
31
31
|
# # Soft-delete integration
|
|
32
32
|
# # Enable tracking of who deleted records when using soft-delete gems
|
|
@@ -39,8 +39,11 @@ module Whodunit
|
|
|
39
39
|
# # Migration auto-injection
|
|
40
40
|
# # Control whether whodunit stamps are automatically added to new migrations
|
|
41
41
|
# config.auto_inject_whodunit_stamps = false # Default: true
|
|
42
|
-
# # When true, automatically adds
|
|
42
|
+
# # When true, automatically adds stamps to create_table definitions using timestamps
|
|
43
43
|
# # When false, you must manually add t.whodunit_stamps to your migrations
|
|
44
|
+
# config.auto_create_user_fk_constraints = false # Default: false
|
|
45
|
+
# # When true, adds foreign keys from stamp columns to the user table
|
|
46
|
+
# # config.user_class_table_name = :accounts # Optional explicit user table name
|
|
44
47
|
#
|
|
45
48
|
# # Column data type configuration
|
|
46
49
|
# # Configure what data types to use for the tracking columns
|
|
@@ -55,7 +58,7 @@ module Whodunit
|
|
|
55
58
|
# config.updater_column_type = :uuid # Default: nil (uses column_data_type)
|
|
56
59
|
# # Set to match your user model's primary key type
|
|
57
60
|
# config.deleter_column_type = :integer # Default: nil (uses column_data_type)
|
|
58
|
-
# #
|
|
61
|
+
# # Used whenever the deleter column is injected
|
|
59
62
|
# end
|
|
60
63
|
RUBY
|
|
61
64
|
|
|
@@ -74,7 +74,12 @@ module Whodunit
|
|
|
74
74
|
# add_whodunit_stamps :posts, include_deleter: true
|
|
75
75
|
# @example Exclude deleter column
|
|
76
76
|
# add_whodunit_stamps :posts, include_deleter: false
|
|
77
|
-
def add_whodunit_stamps(table_name, include_deleter: :auto, creator_type: nil, updater_type: nil, deleter_type: nil
|
|
77
|
+
def add_whodunit_stamps(table_name, include_deleter: :auto, creator_type: nil, updater_type: nil, deleter_type: nil,
|
|
78
|
+
auto_create_user_fk_constraints: nil)
|
|
79
|
+
if Whodunit.soft_delete_enabled? && !column_exists?(table_name, Whodunit.soft_delete_column)
|
|
80
|
+
add_column table_name, Whodunit.soft_delete_column, :datetime, null: true
|
|
81
|
+
end
|
|
82
|
+
|
|
78
83
|
if Whodunit.creator_enabled?
|
|
79
84
|
add_column table_name, Whodunit.creator_column, creator_type || Whodunit.creator_data_type, null: true
|
|
80
85
|
end
|
|
@@ -88,6 +93,7 @@ module Whodunit
|
|
|
88
93
|
end
|
|
89
94
|
|
|
90
95
|
add_whodunit_indexes(table_name, include_deleter)
|
|
96
|
+
add_whodunit_foreign_keys(table_name, include_deleter, auto_create_user_fk_constraints)
|
|
91
97
|
end
|
|
92
98
|
|
|
93
99
|
# Remove stamp columns from an existing table.
|
|
@@ -107,7 +113,9 @@ module Whodunit
|
|
|
107
113
|
# remove_whodunit_stamps :posts, include_deleter: true
|
|
108
114
|
# @example Exclude deleter removal
|
|
109
115
|
# remove_whodunit_stamps :posts, include_deleter: false
|
|
110
|
-
def remove_whodunit_stamps(table_name, include_deleter: :auto, **_options)
|
|
116
|
+
def remove_whodunit_stamps(table_name, include_deleter: :auto, auto_create_user_fk_constraints: nil, **_options)
|
|
117
|
+
remove_whodunit_foreign_keys(table_name, include_deleter, auto_create_user_fk_constraints)
|
|
118
|
+
|
|
111
119
|
if Whodunit.creator_enabled? && column_exists?(table_name, Whodunit.creator_column)
|
|
112
120
|
remove_column table_name, Whodunit.creator_column
|
|
113
121
|
end
|
|
@@ -120,6 +128,10 @@ module Whodunit
|
|
|
120
128
|
column_exists?(table_name, Whodunit.deleter_column)
|
|
121
129
|
remove_column table_name, Whodunit.deleter_column
|
|
122
130
|
end
|
|
131
|
+
|
|
132
|
+
return unless Whodunit.soft_delete_enabled? && column_exists?(table_name, Whodunit.soft_delete_column)
|
|
133
|
+
|
|
134
|
+
remove_column table_name, Whodunit.soft_delete_column
|
|
123
135
|
end
|
|
124
136
|
|
|
125
137
|
# Add stamp columns to a table definition or existing table.
|
|
@@ -129,8 +141,7 @@ module Whodunit
|
|
|
129
141
|
# 2. As a standalone method in migrations (attempts to infer table name)
|
|
130
142
|
#
|
|
131
143
|
# Only adds columns that are enabled in configuration. For new tables,
|
|
132
|
-
#
|
|
133
|
-
# to be conservative.
|
|
144
|
+
# include_deleter: :auto follows the configured soft-delete column.
|
|
134
145
|
#
|
|
135
146
|
# @param table_def [ActiveRecord::ConnectionAdapters::TableDefinition, nil]
|
|
136
147
|
# the table definition (when used in create_table block) or nil
|
|
@@ -154,40 +165,52 @@ module Whodunit
|
|
|
154
165
|
# t.whodunit_stamps include_deleter: true
|
|
155
166
|
# end
|
|
156
167
|
def whodunit_stamps(table_def = nil, include_deleter: :auto, creator_type: nil, updater_type: nil,
|
|
157
|
-
deleter_type: nil)
|
|
168
|
+
deleter_type: nil, auto_create_user_fk_constraints: nil)
|
|
158
169
|
if table_def.nil?
|
|
159
|
-
handle_migration_stamps(include_deleter, creator_type, updater_type, deleter_type
|
|
170
|
+
handle_migration_stamps(include_deleter, creator_type, updater_type, deleter_type,
|
|
171
|
+
auto_create_user_fk_constraints)
|
|
160
172
|
else
|
|
161
|
-
handle_table_definition_stamps(table_def, include_deleter, creator_type, updater_type, deleter_type
|
|
173
|
+
handle_table_definition_stamps(table_def, include_deleter, creator_type, updater_type, deleter_type,
|
|
174
|
+
auto_create_user_fk_constraints)
|
|
162
175
|
end
|
|
163
176
|
end
|
|
164
177
|
|
|
165
178
|
private
|
|
166
179
|
|
|
167
180
|
# Handle stamps when called as migration method
|
|
168
|
-
def handle_migration_stamps(include_deleter, creator_type, updater_type, deleter_type
|
|
181
|
+
def handle_migration_stamps(include_deleter, creator_type, updater_type, deleter_type,
|
|
182
|
+
auto_create_user_fk_constraints)
|
|
169
183
|
table_name = infer_table_name_from_migration
|
|
170
184
|
return unless table_name
|
|
171
185
|
|
|
172
186
|
add_whodunit_stamps(table_name, include_deleter: include_deleter, creator_type: creator_type,
|
|
173
|
-
updater_type: updater_type, deleter_type: deleter_type
|
|
187
|
+
updater_type: updater_type, deleter_type: deleter_type,
|
|
188
|
+
auto_create_user_fk_constraints: auto_create_user_fk_constraints)
|
|
174
189
|
end
|
|
175
190
|
|
|
176
191
|
# Handle stamps when called within create_table block
|
|
177
|
-
def handle_table_definition_stamps(table_def, include_deleter, creator_type, updater_type, deleter_type
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
192
|
+
def handle_table_definition_stamps(table_def, include_deleter, creator_type, updater_type, deleter_type,
|
|
193
|
+
auto_create_user_fk_constraints)
|
|
194
|
+
add_whodunit_columns_to_table_definition(table_def, include_deleter, creator_type, updater_type, deleter_type)
|
|
195
|
+
add_whodunit_indexes_for_create_table(table_def, include_deleter)
|
|
196
|
+
add_whodunit_foreign_keys_for_create_table(table_def, include_deleter, auto_create_user_fk_constraints)
|
|
197
|
+
end
|
|
181
198
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
199
|
+
def add_whodunit_columns_to_table_definition(table_def, include_deleter, creator_type, updater_type, deleter_type)
|
|
200
|
+
add_table_definition_column(table_def, Whodunit.creator_column, creator_type || Whodunit.creator_data_type,
|
|
201
|
+
Whodunit.creator_enabled?)
|
|
202
|
+
add_table_definition_column(table_def, Whodunit.updater_column, updater_type || Whodunit.updater_data_type,
|
|
203
|
+
Whodunit.updater_enabled?)
|
|
204
|
+
add_table_definition_column(table_def, Whodunit.soft_delete_column, :datetime,
|
|
205
|
+
Whodunit.soft_delete_enabled?)
|
|
206
|
+
add_table_definition_column(table_def, Whodunit.deleter_column, deleter_type || Whodunit.deleter_data_type,
|
|
207
|
+
should_include_deleter_for_new_table?(include_deleter))
|
|
208
|
+
end
|
|
185
209
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
end
|
|
210
|
+
def add_table_definition_column(table_def, column, type, enabled)
|
|
211
|
+
return unless enabled && !stamp_column_defined?(table_def, column)
|
|
189
212
|
|
|
190
|
-
|
|
213
|
+
table_def.column column, type, null: true
|
|
191
214
|
end
|
|
192
215
|
|
|
193
216
|
# Determine if deleter column should be included based on configuration.
|
|
@@ -198,12 +221,11 @@ module Whodunit
|
|
|
198
221
|
include_deleter == :auto ? soft_delete_enabled? : include_deleter.eql?(true)
|
|
199
222
|
end
|
|
200
223
|
|
|
201
|
-
#
|
|
202
|
-
# This prevents adding deleter columns to tables that may not need them.
|
|
224
|
+
# Determine whether a new table should include the deleter column.
|
|
203
225
|
# @param include_deleter [Symbol, Boolean] the inclusion preference
|
|
204
|
-
# @return [Boolean] true
|
|
226
|
+
# @return [Boolean] true when explicitly requested or soft-delete is configured
|
|
205
227
|
def should_include_deleter_for_new_table?(include_deleter)
|
|
206
|
-
|
|
228
|
+
should_include_deleter?(include_deleter)
|
|
207
229
|
end
|
|
208
230
|
|
|
209
231
|
# Check if soft-delete is enabled based on configuration.
|
|
@@ -241,6 +263,60 @@ module Whodunit
|
|
|
241
263
|
table_def.index Whodunit.deleter_column, name: "index_#{table_name}_on_deleter"
|
|
242
264
|
end
|
|
243
265
|
|
|
266
|
+
def add_whodunit_foreign_keys(table_name, include_deleter, override)
|
|
267
|
+
return unless create_user_fk_constraints?(override)
|
|
268
|
+
|
|
269
|
+
add_foreign_key table_name, Whodunit.user_table_name, column: Whodunit.creator_column if Whodunit.creator_enabled?
|
|
270
|
+
add_foreign_key table_name, Whodunit.user_table_name, column: Whodunit.updater_column if Whodunit.updater_enabled?
|
|
271
|
+
return unless should_include_deleter?(include_deleter)
|
|
272
|
+
|
|
273
|
+
add_foreign_key table_name, Whodunit.user_table_name, column: Whodunit.deleter_column
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def add_whodunit_foreign_keys_for_create_table(table_def, include_deleter, override)
|
|
277
|
+
return unless create_user_fk_constraints?(override)
|
|
278
|
+
|
|
279
|
+
add_table_definition_foreign_key(table_def, Whodunit.creator_column) if Whodunit.creator_enabled?
|
|
280
|
+
add_table_definition_foreign_key(table_def, Whodunit.updater_column) if Whodunit.updater_enabled?
|
|
281
|
+
return unless should_include_deleter_for_new_table?(include_deleter)
|
|
282
|
+
|
|
283
|
+
add_table_definition_foreign_key(table_def,
|
|
284
|
+
Whodunit.deleter_column)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def stamp_column_defined?(table_def, column_name)
|
|
288
|
+
table_def.columns.any? { |column| column.name.to_s == column_name.to_s }
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def add_table_definition_foreign_key(table_def, column_name)
|
|
292
|
+
return if table_def.foreign_keys.any? do |foreign_key|
|
|
293
|
+
foreign_key.to_table.to_s == Whodunit.user_table_name.to_s &&
|
|
294
|
+
foreign_key.options[:column].to_s == column_name.to_s
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
table_def.foreign_key Whodunit.user_table_name, column: column_name
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def create_user_fk_constraints?(override)
|
|
301
|
+
override.nil? ? Whodunit.auto_create_user_fk_constraints : override
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def remove_whodunit_foreign_keys(table_name, include_deleter, override)
|
|
305
|
+
return unless create_user_fk_constraints?(override)
|
|
306
|
+
|
|
307
|
+
if Whodunit.creator_enabled?
|
|
308
|
+
remove_foreign_key table_name, Whodunit.user_table_name,
|
|
309
|
+
column: Whodunit.creator_column
|
|
310
|
+
end
|
|
311
|
+
if Whodunit.updater_enabled?
|
|
312
|
+
remove_foreign_key table_name, Whodunit.user_table_name,
|
|
313
|
+
column: Whodunit.updater_column
|
|
314
|
+
end
|
|
315
|
+
return unless should_include_deleter?(include_deleter)
|
|
316
|
+
|
|
317
|
+
remove_foreign_key table_name, Whodunit.user_table_name, column: Whodunit.deleter_column
|
|
318
|
+
end
|
|
319
|
+
|
|
244
320
|
# Attempt to infer table name from migration class name
|
|
245
321
|
def infer_table_name_from_migration
|
|
246
322
|
return nil unless respond_to?(:migration_name)
|
|
@@ -249,10 +325,10 @@ module Whodunit
|
|
|
249
325
|
case migration_name
|
|
250
326
|
when /^Create(\w+)$/
|
|
251
327
|
table_name = ::Regexp.last_match(1)
|
|
252
|
-
table_name.
|
|
328
|
+
table_name.underscore.pluralize
|
|
253
329
|
when /^Add\w*To(\w+)$/
|
|
254
330
|
table_name = ::Regexp.last_match(1)
|
|
255
|
-
table_name.
|
|
331
|
+
table_name.underscore
|
|
256
332
|
end
|
|
257
333
|
end
|
|
258
334
|
|
|
@@ -263,5 +339,13 @@ module Whodunit
|
|
|
263
339
|
end
|
|
264
340
|
end
|
|
265
341
|
|
|
266
|
-
#
|
|
267
|
-
|
|
342
|
+
# Integrate immediately when Active Record is already loaded, or defer until it is.
|
|
343
|
+
# :nocov:
|
|
344
|
+
if defined?(ActiveRecord::Migration)
|
|
345
|
+
ActiveRecord::Migration.include(Whodunit::MigrationHelpers)
|
|
346
|
+
elsif defined?(ActiveSupport)
|
|
347
|
+
ActiveSupport.on_load(:active_record) do
|
|
348
|
+
ActiveRecord::Migration.include(Whodunit::MigrationHelpers)
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
# :nocov:
|
data/lib/whodunit/stampable.rb
CHANGED
|
@@ -186,7 +186,7 @@ module Whodunit
|
|
|
186
186
|
# @return [void]
|
|
187
187
|
# @api private
|
|
188
188
|
def setup_whodunit_associations
|
|
189
|
-
return if abstract_class?
|
|
189
|
+
return if abstract_class? || !table_exists?
|
|
190
190
|
|
|
191
191
|
setup_creator_association if creator_column_exists? && model_creator_enabled?
|
|
192
192
|
setup_updater_association if updater_column_exists? && model_updater_enabled?
|
|
@@ -42,7 +42,7 @@ module Whodunit
|
|
|
42
42
|
skip = options.delete(:skip_whodunit_stamps)
|
|
43
43
|
result = super
|
|
44
44
|
|
|
45
|
-
if Whodunit.auto_inject_whodunit_stamps && !_whodunit_stamps_added && !skip
|
|
45
|
+
if Whodunit.auto_inject_whodunit_stamps && !_whodunit_stamps_added && !skip && !whodunit_internal_table?
|
|
46
46
|
whodunit_stamps(include_deleter: :auto)
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -52,9 +52,17 @@ module Whodunit
|
|
|
52
52
|
# assign true tp the tracker `@_whodunit_stamps_added` before the
|
|
53
53
|
# reuse/call of the `whodunit_stamps` flow from the Whodunit::MigrationHelpers module (see railtie.rb)
|
|
54
54
|
#
|
|
55
|
-
def whodunit_stamps(include_deleter: :auto, creator_type: nil, updater_type: nil, deleter_type: nil
|
|
55
|
+
def whodunit_stamps(include_deleter: :auto, creator_type: nil, updater_type: nil, deleter_type: nil,
|
|
56
|
+
auto_create_user_fk_constraints: nil)
|
|
56
57
|
self._whodunit_stamps_added = true
|
|
57
|
-
self.class.whodunit_stamps(self, include_deleter:, creator_type:, updater_type:, deleter_type
|
|
58
|
+
self.class.whodunit_stamps(self, include_deleter:, creator_type:, updater_type:, deleter_type:,
|
|
59
|
+
auto_create_user_fk_constraints:)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def whodunit_internal_table?
|
|
65
|
+
%w[ar_internal_metadata schema_migrations].include?(name.to_s)
|
|
58
66
|
end
|
|
59
67
|
end
|
|
60
68
|
end
|
data/lib/whodunit/version.rb
CHANGED
data/lib/whodunit.rb
CHANGED
|
@@ -43,6 +43,11 @@ module Whodunit
|
|
|
43
43
|
# @return [String] the user class name
|
|
44
44
|
mattr_accessor :user_class, default: "User"
|
|
45
45
|
|
|
46
|
+
# Explicit user table name override. When nil, the table name is inferred
|
|
47
|
+
# from the configured user class.
|
|
48
|
+
# @return [String, Symbol, nil] the user table name override
|
|
49
|
+
mattr_accessor :user_class_table_name, default: nil
|
|
50
|
+
|
|
46
51
|
# The column name for tracking who created the record (default: :creator_id)
|
|
47
52
|
# @return [Symbol] the creator column name
|
|
48
53
|
mattr_accessor :creator_column, default: :creator_id
|
|
@@ -65,6 +70,10 @@ module Whodunit
|
|
|
65
70
|
# @return [Boolean] auto-injection setting
|
|
66
71
|
mattr_accessor :auto_inject_whodunit_stamps, default: true
|
|
67
72
|
|
|
73
|
+
# Whether migration helpers should create foreign keys to the user table.
|
|
74
|
+
# @return [Boolean] automatic user foreign-key constraint setting
|
|
75
|
+
mattr_accessor :auto_create_user_fk_constraints, default: false
|
|
76
|
+
|
|
68
77
|
# @!group Data Type Configuration
|
|
69
78
|
|
|
70
79
|
# The default data type for stamp columns (default: :bigint)
|
|
@@ -132,6 +141,21 @@ module Whodunit
|
|
|
132
141
|
user_class.to_s
|
|
133
142
|
end
|
|
134
143
|
|
|
144
|
+
# Resolve the configured user table name without loading the model. Migration
|
|
145
|
+
# execution can happen before the user table exists, so constantizing the
|
|
146
|
+
# user class here may cause Active Record to query a missing relation.
|
|
147
|
+
# Explicit configuration takes precedence; class objects may still provide
|
|
148
|
+
# their custom Active Record table name directly.
|
|
149
|
+
#
|
|
150
|
+
# @return [String] the user table name
|
|
151
|
+
def self.user_table_name
|
|
152
|
+
return user_class_table_name.to_s if user_class_table_name
|
|
153
|
+
|
|
154
|
+
return user_class.table_name.to_s if user_class.respond_to?(:table_name)
|
|
155
|
+
|
|
156
|
+
user_class_name.underscore.pluralize
|
|
157
|
+
end
|
|
158
|
+
|
|
135
159
|
# @!group Data Type Helpers
|
|
136
160
|
|
|
137
161
|
# Get the data type for the creator column
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: whodunit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ken C. Demanawa
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|