Skip to content

Commit

Permalink
Add table_without_primary_key checker (#173)
Browse files Browse the repository at this point in the history
  • Loading branch information
fatkodima committed Mar 1, 2024
1 parent de610a9 commit 945d3c8
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 0 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ can detect:
* incorrect values of `dependent` on associations - [`active_record_doctor:incorrect_dependent_option`](#detecting-incorrect-dependent-option-on-associations)
* primary keys having short integer types - [`active_record_doctor:short_primary_key_type`](#detecting-primary-keys-having-short-integer-types)
* mismatched foreign key types - [`active_record_doctor:mismatched_foreign_key_type`](#detecting-mismatched-foreign-key-types)
* tables without primary keys - [`active_record_doctor:table_without_primary_key`](#detecting-tables-without-primary-keys)

It can also:

Expand Down Expand Up @@ -604,6 +605,29 @@ Supported configuration options:
- `ignore_columns` - foreign keys, written as table.column, that should not be
checked.

### Detecting Tables Without Primary Keys

Tables should have primary keys. Otherwise, it becomes problematic to easily find a specific record,
logical replication in PostgreSQL will be troublesome, because all the rows need to be unique
in the table then etc.

Running the command below will list all tables without primary keys:

```
bundle exec rake active_record_doctor:table_without_primary_key
```

The output of the command looks like this:

```
add a primary key to companies
```

Supported configuration options:

- `enabled` - set to `false` to disable the detector altogether
- `ignore_tables` - tables whose primary key existense should not be checked

## Ruby and Rails Compatibility Policy

The goal of the policy is to ensure proper functioning in reasonable
Expand Down
1 change: 1 addition & 0 deletions lib/active_record_doctor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
require "active_record_doctor/detectors/incorrect_dependent_option"
require "active_record_doctor/detectors/short_primary_key_type"
require "active_record_doctor/detectors/mismatched_foreign_key_type"
require "active_record_doctor/detectors/table_without_primary_key"
require "active_record_doctor/errors"
require "active_record_doctor/help"
require "active_record_doctor/runner"
Expand Down
4 changes: 4 additions & 0 deletions lib/active_record_doctor/config/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
enabled: true,
ignore_tables: []

detector :table_without_primary_key,
enabled: true,
ignore_tables: []

detector :undefined_table_references,
enabled: true,
ignore_models: []
Expand Down
30 changes: 30 additions & 0 deletions lib/active_record_doctor/detectors/table_without_primary_key.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

require "active_record_doctor/detectors/base"

module ActiveRecordDoctor
module Detectors
class TableWithoutPrimaryKey < Base # :nodoc:
@description = "detect tables without primary keys"
@config = {
ignore_tables: {
description: "tables whose primary key existense should not be checked",
global: true
}
}

private

def message(table:)
"add a primary key to #{table}"
end

def detect
each_table(except: config(:ignore_tables)) do |table|
column = primary_key(table)
problem!(table: table) unless column
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

class ActiveRecordDoctor::Detectors::TableWithoutPrimaryKeyTest < Minitest::Test
def test_table_without_primary_key_reported
Context.create_table(:companies, id: false) do |t|
t.string :name
end

assert_problems(<<~OUTPUT)
add a primary key to companies
OUTPUT
end

def test_table_with_primary_key_is_not_reported
Context.create_table(:companies)
refute_problems
end

def test_config_ignore_tables
Context.create_table(:companies, id: false) do |t|
t.string :name
end

config_file(<<-CONFIG)
ActiveRecordDoctor.configure do |config|
config.detector :table_without_primary_key,
ignore_tables: ["companies"]
end
CONFIG

refute_problems
end

def test_global_ignore_tables
Context.create_table(:companies, id: false) do |t|
t.string :name
end

config_file(<<-CONFIG)
ActiveRecordDoctor.configure do |config|
config.global :ignore_tables, ["companies"]
end
CONFIG

refute_problems
end
end

0 comments on commit 945d3c8

Please sign in to comment.