モデルのカラム名を変更しようとしたところ、"SQLite3::ConstraintException: FOREIGN KEY constraint failed:"というエラーが吐かれたので、その対処法を書いておきます。
確証を持ってやったというより、できそうだなと思ったらできてしまった感じなので、間違っている部分などあればぜひ教えてください!
##rails db:migrate
のかわりにrails db:migrate reset
を実行する
結論からいうと、rails db:migrate
ではなくrails db:migrate reset
をうつことで無事にエラーを回避してカラム名の変更を行うことができました。
ふつうはrails db:migrate
なので、ちょっとイレギュラーな対応になるのかもしれません。
##前提と実現したかったこと
Railsチュートリアルの拡張機能(リプライ機能)を実装していて、userモデルのカラム名を変更しようとした。
カラム名の変更方法については、以下の記事を参考にさせていただきました。
【備忘録】Rails-カラム名を変更する方法
ざっくりと説明すると、
①rails g migraiton rename_カラム名_column_to_テーブル名
でマイグレーションファイルを生成
②マイグレーションファイルにrename_column テーブル名, 変更前のカラム名, 変更後のカラム名
を追記
③rails db:migrate
を実行
という流れです。
ここで、先述の"ConstraintException"なるエラーが発生しました。
##外部キーによる他モデルとの関連づけが原因
エラーに"FOREIGN KEY"とあるとおり、外部キーをつかってrelationshipsテーブルと関連づけをしていたことが原因でした。
class User < ApplicationRecord
has_many :microposts, dependent: :destroy
has_many :active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy
has_many :passive_relationships, class_name: "Relationship", foreign_key: "followed_id", dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
...
以下の記事を参考にしたところ、
①外部キーをつかって他のテーブルと関連づけをしていた
②すでにDB内にデータが存在しており、キーによる紐付けがおこなわれていた
という状態だったので変更ができなかったらしい(変更してしまうとデータ整合性がとれなくなる)、ということが分かりました。
ちなみに上記記事では、has_manyにつづけてdependent: :destroy
を指定することでこのエラーを解決しています。
##変更したいカラムはキーとは無関係なので、DBをリセットすることで対処
ただし、今回変更したかったカラムは外部キーに設定したカラムではないので、単純にdependent: :destroy
をつける対処はできません。
また、変更するカラムが外部キーとは直接関係ないことから、問題になるのは②の「すでにDBに存在していて、他のテーブルに紐づいているデータ」になりそうです。
もしそうであれば、この「すでにあるデータ」をいったん空にしてしまえばrails db:migrate
が実行できるはず。...DBをリセットしてマイグレーションを実行って、rails db:migrate:reset
そのものじゃん。
ということでやってみたら無事にマイグレーションが実行できました。schema.rbも意図したかたちになっています。