ActiveRecord::RecordNotSaved - Failed to save the new associated モデル名.:
が発生し解決に少し時間かかったのと、
エラーでググっても同じ問題で発生している人が見当たらなかったので、メモしておきます
結論
とりあえず結論
関連テーブルをnewで作成しつつ代入し用途した際に、newで作成失敗しエラーが発生したみたいです
これだけだと分かりづらいので説明していきます
ソースを使って詳しく解説
まずは前提
Blogというモデルがあり、それに対して1対1で紐づくOwnerがあったとします Blog作成後にのupdateでBlogに紐づくOwnerを作成して一緒に紐付けを行うという処理になります
class Blog < ApplicationRecord has_one: owner end class Owner < ApplicationRecord belongs_to: blog end class BlogsController < ApplicationController def update @blog = Blog.find(params[:id]) if !@blog.owner @blog.owner = Owner.new( name: params[:name], email: params[:email] ) end end end
仕様追加で処理を追加
仕様が追加され、新しくCompanyテーブルを作成しOwnerを紐付けました
class Blog < ApplicationRecord has_one: owner, dependent: :destroy end class Owner < ApplicationRecord belongs_to: blog belongs_to: company # 新しく追加 end # 新しくCompanyモデルを追加 class Company < ApplicationRecord has_many: owner end class BlogsController < ApplicationController def update @blog = Blog.find(params[:id]) if !@blog.owner @blog.owner = Owner.new( name: params[:name], email: params[:email] ) end end end
エラー発生
この状態で動かしたら以下のようなエラーが出ました
ActiveRecord::RecordNotSaved - Failed to save the new associated owner.:
@blog.owner = Owner.new(
でエラーが出ているということは、エラーの詳細内容で分かったのですがパッと原因が分からず
なので一旦newして変数に入れてから紐付けを試してみたり、newする時の渡す値を変えたり変更したりと試している中でやっと原因らしき情報を手に入れました
Owner.new(
だったのをOwner.create!(
に変更したときに、comanyを入力してくださいという、エラーが発生
原因判明
原因はOwner.newする際に一緒にcompanyを渡していないことが原因でした
先日書いた以下の記事で説明しているのですが、
belongs_to: company, optional: true
であれば、companyをしていなくてもエラーにはならないのですが、
今回は必ず設定して欲しかったのでoptional: true
は設定していませんでした
Owner.newでエラーが発生し、それが原因で@blog.owner = Owner.new(
にてエラーになっていたようです
以下のようにcompanyを設定してあげるようにしたら無事動くようになりました!
class BlogsController < ApplicationController def update @blog = Blog.find(params[:id]) company = Company.find_by(params[:comapny_id]) if !@blog.owner @blog.owner = Owner.new( name: params[:name], email: params[:email], company: company # OwnerにCompanyへの紐付けを追加 ) end end end
最後に
ちょっとしたことでハマることってたまにあるんですよね
同じようなケースがググっても見つからなかったのでハマる人は少ないのかもしれませんが、同じようにハマった人の参考になれば幸いです