早速Rails5を触ってると、nested attributes周りで詰まったので紹介します。
症状
- 全ての項目を入れてもバリデーションに引っかかって保存できない。
モデル
ここではモデル名をParent, Childとします。
class Parent < ApplicationRecord has_many :children accepts_nested_attributes_for :children end
class Child < ApplicationRecord belongs_to :parent end
対応
以下の用に書くと動くようになりました。
class Child < ApplicationRecord belongs_to :parent, optional: true end
原因
@parent.errors
でバリデーションの内容を見てみると
子テーブルにおいて親テーブルのIDが無いという内容でした。
で、調べ進めていくとRails5による新しい挙動が原因のようです。
つまりChildモデル内でparent_idが自動的にrequired: true
で
バリデーションがかかるようになっていたみたいです。
そしてRailsでバリデーションと保存の順番は大まかに
- Parentのバリデーション
- Childのバリデーション
- Parentの保存処理
- Childの保存処理
の順で行われ、Parentの保存がされて生まれたIDが
Childのparent_idに入ります。
しかし、Childモデル内でparent_id
が必須になっているために
はじめのParentのバリデーションの時点で
「Childにparent_idねーよ!」と怒って終了するようです。
なのでbelongs_to
にoptional: true
を付けて
parent_id
必須を無くしたという感じです。
「いや、そもそもrequired: true
つけんなよ」 という方は
こちらに取り方が書いてました。
設定でRails4と同じ挙動にできるみたいですね。
どっちがいいのやら。
他にもRails5でハマった時は紹介したいと思います。