Skip to content

Commit a1e60f9

Browse files
authored
table_without_timestamps: detect tables without timestamp columns (#197)
1 parent 8736fc7 commit a1e60f9

File tree

5 files changed

+121
-0
lines changed

5 files changed

+121
-0
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ can detect:
1616
* primary keys having short integer types - [`active_record_doctor:short_primary_key_type`](#detecting-primary-keys-having-short-integer-types)
1717
* mismatched foreign key types - [`active_record_doctor:mismatched_foreign_key_type`](#detecting-mismatched-foreign-key-types)
1818
* tables without primary keys - [`active_record_doctor:table_without_primary_key`](#detecting-tables-without-primary-keys)
19+
* tables without timestamps - [`active_record_doctor:table_without_timestamps`](#detecting-tables-without-timestamps)
1920

2021
It can also:
2122

@@ -642,6 +643,29 @@ Supported configuration options:
642643
- `enabled` - set to `false` to disable the detector altogether
643644
- `ignore_tables` - tables whose primary key existence should not be checked
644645

646+
### Detecting Tables Without Timestamps
647+
648+
Tables should have timestamp columns (`created_at`/`updated_at`). Otherwise, it becomes problematic
649+
to easily find when the record was created/updated, if the table is active or can be removed,
650+
automatic Rails cache expiration after record updates is not possible.
651+
652+
Running the command below will list all tables without default timestamp columns:
653+
654+
```
655+
bundle exec rake active_record_doctor:table_without_timestamps
656+
```
657+
658+
The output of the command looks like this:
659+
660+
```
661+
add a created_at column to companies
662+
```
663+
664+
Supported configuration options:
665+
666+
- `enabled` - set to `false` to disable the detector altogether
667+
- `ignore_tables` - tables whose timestamp columns existence should not be checked
668+
645669
## Ruby and Rails Compatibility Policy
646670

647671
The goal of the policy is to ensure proper functioning in reasonable

lib/active_record_doctor.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
require "active_record_doctor/detectors/short_primary_key_type"
2222
require "active_record_doctor/detectors/mismatched_foreign_key_type"
2323
require "active_record_doctor/detectors/table_without_primary_key"
24+
require "active_record_doctor/detectors/table_without_timestamps"
2425
require "active_record_doctor/errors"
2526
require "active_record_doctor/help"
2627
require "active_record_doctor/runner"

lib/active_record_doctor/config/default.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@
6464
enabled: true,
6565
ignore_tables: []
6666

67+
detector :table_without_timestamps,
68+
enabled: true,
69+
ignore_tables: []
70+
6771
detector :undefined_table_references,
6872
enabled: true,
6973
ignore_models: []
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# frozen_string_literal: true
2+
3+
require "active_record_doctor/detectors/base"
4+
5+
module ActiveRecordDoctor
6+
module Detectors
7+
class TableWithoutTimestamps < Base # :nodoc:
8+
@description = "detect tables without created_at/updated_at columns"
9+
@config = {
10+
ignore_tables: {
11+
description: "tables whose timestamp columns existence should not be checked",
12+
global: true
13+
}
14+
}
15+
16+
private
17+
18+
TIMESTAMPS = {
19+
"created_at" => "created_on",
20+
"updated_at" => "updated_on"
21+
}.freeze
22+
23+
def message(table:, column:)
24+
"add a #{column} column to #{table}"
25+
end
26+
27+
def detect
28+
each_table(except: config(:ignore_tables)) do |table|
29+
TIMESTAMPS.each do |column, alternative_column|
30+
unless column(table, column) || column(table, alternative_column)
31+
problem!(table: table, column: column)
32+
end
33+
end
34+
end
35+
end
36+
end
37+
end
38+
end
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# frozen_string_literal: true
2+
3+
class ActiveRecordDoctor::Detectors::TableWithoutTimestampsTest < Minitest::Test
4+
def test_table_without_timestamps_reported
5+
Context.create_table(:companies) do |t|
6+
t.string :name
7+
end
8+
9+
assert_problems(<<~OUTPUT)
10+
add a created_at column to companies
11+
add a updated_at column to companies
12+
OUTPUT
13+
end
14+
15+
def test_table_with_timestamps_is_not_reported
16+
Context.create_table(:companies) do |t|
17+
t.timestamps
18+
end
19+
refute_problems
20+
end
21+
22+
def test_table_with_alternative_timestamps_is_not_reported
23+
Context.create_table(:companies) do |t|
24+
t.timestamp :created_on
25+
t.timestamp :updated_on
26+
end
27+
refute_problems
28+
end
29+
30+
def test_config_ignore_tables
31+
Context.create_table(:companies)
32+
33+
config_file(<<-CONFIG)
34+
ActiveRecordDoctor.configure do |config|
35+
config.detector :table_without_timestamps,
36+
ignore_tables: ["companies"]
37+
end
38+
CONFIG
39+
40+
refute_problems
41+
end
42+
43+
def test_global_ignore_tables
44+
Context.create_table(:companies)
45+
46+
config_file(<<-CONFIG)
47+
ActiveRecordDoctor.configure do |config|
48+
config.global :ignore_tables, ["companies"]
49+
end
50+
CONFIG
51+
52+
refute_problems
53+
end
54+
end

0 commit comments

Comments
 (0)