From 38753de61dc7610423b231595991ebf6a8f723b3 Mon Sep 17 00:00:00 2001 From: fatkodima Date: Fri, 3 Jan 2025 13:59:08 +0200 Subject: [PATCH] missing_foreign_keys: consider column type for foreign key candidates (#204) --- .../detectors/missing_foreign_keys.rb | 9 ++++++--- .../detectors/missing_foreign_keys_test.rb | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/active_record_doctor/detectors/missing_foreign_keys.rb b/lib/active_record_doctor/detectors/missing_foreign_keys.rb index 0f506428..ed2ffd32 100644 --- a/lib/active_record_doctor/detectors/missing_foreign_keys.rb +++ b/lib/active_record_doctor/detectors/missing_foreign_keys.rb @@ -28,7 +28,7 @@ def detect # We need to skip polymorphic associations as they can reference # multiple tables but a foreign key constraint can reference # a single predefined table. - next unless named_like_foreign_key?(column) + next unless looks_like_foreign_key?(column) next if foreign_key?(table, column) next if polymorphic_foreign_key?(table, column) @@ -37,8 +37,11 @@ def detect end end - def named_like_foreign_key?(column) - column.name.end_with?("_id") + def looks_like_foreign_key?(column) + type = column.type.to_s + + column.name.end_with?("_id") && + (type == "integer" || type.include?("uuid")) end def foreign_key?(table, column) diff --git a/test/active_record_doctor/detectors/missing_foreign_keys_test.rb b/test/active_record_doctor/detectors/missing_foreign_keys_test.rb index 44e5b442..1af3bd75 100644 --- a/test/active_record_doctor/detectors/missing_foreign_keys_test.rb +++ b/test/active_record_doctor/detectors/missing_foreign_keys_test.rb @@ -21,6 +21,26 @@ def test_present_foreign_key_is_not_reported refute_problems end + def test_non_integer_missing_foreign_key_is_reported + Context.create_table(:users) do |t| + t.string :external_id + end + + refute_problems + end + + def test_uuid_missing_foreign_key_is_reported + require_uuid_column_type! + + Context.create_table(:users) do |t| + t.uuid :company_id + end + + assert_problems(<<~OUTPUT) + create a foreign key on users.company_id - looks like an association without a foreign key constraint + OUTPUT + end + def test_config_ignore_models Context.create_table(:companies) Context.create_table(:users) do |t|