外部キー制約の設定ができない
テーブルを作成するためにmigrationファイルを作成しdb:migrateしたら思いもよらないエラーが発生したので対処法を調査しました。
エラー内容
既存のテーブル(document_bases)があり、そのテーブルのidを外部キーに持つテーブル(document_views)を作成します。
migrationファイルを準備します
1 | class CreateDocumentView < ActiveRecord::Migration |
db:migrateします。すると以下のようなエラーが表示されました。
1 | ActiveRecord::StatementInvalid: Mysql2::Error: Key column 'document_basis_id' doesn't exist in table: ALTER TABLE `document_views` ADD CONSTRAINT `document_base_id_on_document_views` FOREIGN KEY (`document_basis_id`) REFERENCES `document_bases` (`id`) |
原因調査
最初なぜエラーになるのか全くわからなかったのですが、よく見るとKey column 'document_basis_id'となっていて、存在するカラムdocument_base_idと異なっています。
調べてみるとbasesはbaseの複数形でもあり、basisの複数形でもあるようです。basesから単数形に戻すときにbaseではなくbasisを選択されてしまっているようです。
対応方法
t.referencesのオプションであるforeign_keyでなんとか指定できないかと思い、add_foreign_keyのオプションを調べてみました。
https://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_foreign_key
するとoptionsの説明の最初に答えが書いてありました。
1 | :column |
Defaults to to_table.singularize + "_id"と書かれているので、singularizeメソッドを試してみました。
1 | [1] pry(main)> 'bases'.singularize |
ということでforeign_keyのオプションにcolumn: :document_base_idを指定することで無事migrateできました。
修正済migrationファイル
1 | class CreateDocumentView < ActiveRecord::Migration |
まとめ
Railsの単数形/複数形変換で存在しないカラム名/テーブル名に変換されてしまった場合は明示的に名前を指定するようにする。
APIドキュメントをちゃんと読むようにする。