概要
「ActiveRecord::RecordInvalid: Validation failed: Users must exist」というエラーが出たので検索をしていると、正しくなさそうな「optional: true」を使用した回避策が散見されたのでデバッグの流れを中心に書いてみました。
学習し始めは、自分でデバッグしようにも**何をすればいいのか分からない!**ということが多かったので何かの参考になれば嬉しいです。
エラーの発生状況と原因
エラーの発生状況
ミニブログにコメントをつけるアプリを作っている最中にコメントの投稿をsaveすると、一見正しく見えるのにsaveがfalseになっていた。
原因
アソシエーションが正しくなかった。
class User < ApplicationRecord
has_many :blogs, dependent: :destroy
end
class Blog < ApplicationRecord
# 間違い
belongs_to :users
# 正しい
belongs_to :user
end
デバッグの流れ
1. save!を試す
saveがfalseになっていたのでsave!で強制セーブしてエラーを確認。
「Users must exist」をみた時点で複数形になっていることを気づくべきだった。
pry(main)> blog = current_user.blogs.build(blog_params)
pry(main)> blog.save
=> false
pry(main)>blog.save!
ActiveRecord::RecordInvalid: Validation failed: Users must exist
2. エラーの中身を確認
@blog.save
=> false
[4] pry(#<BlogsController>)> @blog.errors
=> #<ActiveModel::Errors:0x00007f96e90695c8
@base=#<Blog:0x00007f96ef23e528 id: nil, title: "a", body: "a", user_id: 1, created_at: nil, updated_at: nil>,
@details={:users=>[{:error=>:blank}]},
@messages={:users=>["must exist"]}>
3. optional: trueを付けてみた
検索結果にやたら出てきたので試してみると、保存に成功。
必要な値は揃っているので、データベースを確認しても全てのカラムが埋まっている。
しかし、裏技的で根本の問題は解決していないよね...
class Blog < ApplicationRecord
belongs_to :users, optional: true
end
4. belongs_toが複数形になっていることに気づく
アソシエーションは、一側を単数形、多側を複数形にしなければいけないので気をつけましょう。
【Railsガイド】Active Record の関連付け
後書き
前にもこんなミスをやらかしていた気がしますが、久しぶりに一からコードを書いていたのでこういう部分でミスを多発していました(^^;
それにしても、エラーの出かたもoptional: trueで回避できることもなかなか面白い発見でした。