くるみ
ねえ、Railsで下のようなエラーと遭遇しちゃったんだけど
ActiveRecord::RecordInvalid (Validation failed: Lost must exist):
ということで今回は
- 同じようなエラーに遭遇したので解決法を知りたい
- というかそもそもこの「…must exist」って何?
という方に向けてこの「Validation failed: (モデル名) must exist」というエラーの対処法をまとめました。
自分の備忘録代わりでもありますが、参考になれば幸いです⸝⸝- ̫ -⸝⸝
Railsの「Validation failed:~must exist」の解決法
まずは結論から。そのエラーに対してブログ主の場合、
このLostというモデルと1対多の関係にあるMatterモデルクラスに以下のように記述することで解決しました。
class Matter < ApplicationRecord
belongs_to :user
belongs_to :lost, optional: true #ここを追加
end
ということで簡潔にまとめると…
解決法まとめ
- モデルクラスの関連付けのメソッドの引数に「optional: true」を記述する
というかそもそも「optional: true」って何?
くるみ
オプション「optional:true」とは?
先ほど追加したオプション「optional:true」とは何か、例と共に見ていきましょう。
class Lost < ApplicationRecord
has_many :matters, dependent: :destroy
end
class Matter < ApplicationRecord
belongs_to :lost, optional: true
end
このようにLostモデルとMatterが1対多の関係にあるとします。その場合、
- Matterテーブルの外部キーであるlost_idというカラムは、自動でnillが禁止になる
- よってバリデーションではじかれてしまいエラーになる
というわけです。
ブログ主
なるほどね
optional: trueはオプション
簡潔に説明すると、この「optional: true」は「外部キーがnillであることを許可してくれるオプション」です
belongs_to :lost, optional: true
この「optional: true」を関連付けのメソッドbelongs_toのオプションで記述することによって、
「空でもいいよ」ということになるのでバリデーションにひっからず上手く保存されるということですね。
余談
class MattersController < ApplicationController
def q1_after
@matter=Matter.new(user_id:current_user.id, is_solved:false)
@lesson=Lesson.find_by(name:params[:lesson])
category=params[:category]
if @matter.save #lesson_idが空の状態
redirect_to("/q2/#{@matter.id}/#{@lesson.id}/#{category}")
else
flash[:notice]="やり直してください"
redirect_to("/q1")
end
end
end
ブログ主の場合、この6行目のレコードを保存する際に外部キーが空であった(にしていた)ため、今回のエラーにひっかりました。
まとめ
まあ本来外部キーをnilのまま保存することの方が珍しい(?)ので、そこまで気をつける必要は無いかもしれませんが、頭の片隅ぐらいには入れておきたいですね。
参考になれば幸いです!では⸝⸝- ̫ -⸝⸝
参考させていただき、無事エラー解決・保存させる事ができました!
ありがとうございました!