##起こったこと
ユーザーを削除しようとしたら下記のようなエラーが出てきてしまった。
sqlite3::constraintexception: foreign key constraint failed
##環境
Ruby : 2.7.3
Ruby on Rails : 6.1.3.2
SQLite3 : 3.32.3
##アプリの機能
私が作っているアプリはユーザーが投稿、いいね、コメント、フォロー機能などを備えていました。
ですので、
主なテーブルとして、User,Post テーブル
中間テーブルとして、Postlike,Comment,Relationshipテーブル
を作っていました
##原因・解決策
原因はdependent: :destroyのつけ忘れです。
dependent: :destroyとは、これをモデルにつける(以下のように)ことによってUserが削除された時にUser外部キーに設定していた投稿自体も削除してくれる便利なものです
class User < ApplicationRecord
has_many :posts, dependent: :destroy <---ここが大事
end
class Timepost < ApplicationRecord
belongs_to :user
end
といっても自分自身dependent: :destroyはしっかりコードに記述しながらアプリを作りましたし、再度確認してもしっかりと書かれていたので最初はどこが原因かわかりませんでした。(relationships.rbを除いては)
ユーザーを新規作成し、投稿、いいね機能などを使わずにユーザー削除をすると正常にユーザーは削除されたため、原因はモデル周りにあることははっきりしました。
そして、投稿をした後にユーザー削除をすると正常に削除される(よしよし)、投稿にいいねをした後にユーザー削除をすると正常に削除される(よしよし)、このように1つずつ機能を試し、ユーザー削除が正常に機能しているのかをチェックしていると、フォロー機能を使った後にユーザー削除すると下記のエラーが出ることがわかりました。
sqlite3::constraintexception: foreign key constraint failed
フォロー機能は自分では作り方がわからなかったのでRailsでフォロー機能を作る方法こちらの記事を参考にして作りました。
###見た記事のモデル
class User < ApplicationRecord
has_many :relationships <--ここ
has_many :followings, through: :relationships, source: :follow
has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id' <--ここ
has_many :followers, through: :reverse_of_relationships, source: :user
end
class Relationship < ApplicationRecord
belongs_to :user
belongs_to :follow, class_name: 'User'
validates :user_id, presence: true
validates :follow_id, presence: true
end
問題はuser.rbの2行目と4行目にありました
この2つにdependent: :destroyが記述されておらずエラーが出ていたのです。
ですので以下のコードに変更しました
class User < ApplicationRecord
has_many :relationships, dependent: :destroy <--ここを変更
has_many :followings, through: :relationships, source: :follow
has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id', dependent: :destroy <--ここを変更
has_many :followers, through: :reverse_of_relationships, source: :user
end
###反省
今回はdependent: :destroy のつけ忘れでエラーが出てしまいましたが、根本的な原因はフォロー機能を実装するときにしっかりとコードを理解せず使っていたことです。
初学者のためフォロー機能の作り方なんて思いつきませんし他人のをパクるのはありがと思うのですが自分のアプリで使うコードは最低限理解する必要があるかなと思いました。
これから気をつけたいと思います