tl;dr
Rails5を利用している環境で、1対多の自己結合を実現させるために以下のようなコードを書いた。
class Hoge < ApplicationRecord
has_many :children, class_name: 'Hoge', foreign_key: 'parent_id', dependent: :destroy
belongs_to :parent, class_name: 'Hoge'
end
何度DBにレコードを登録しようとしても、毎回以下のようなエラーが発生して登録できない。
ActiveRecord::RecordInvalid: バリデーションに失敗しました: Parentを入力してください
いや、親に当たるレコードは、parent_id
持たないんだよなぁ。。。ってことで盛大にハマったのでメモ。
原因
参考にしたサイトの情報が古い(Rails4以前のもの)ばかりだったので、Rails5からの仕様変更でハマっていた。
Rails5からはbelongs_to
アソシエーションは、デフォルトでrequire: true
になったので、null
での登録ができなくなっていた。
※確かに、belongs_to
なのに、id
設定しないとかレアパターンなので、デフォルトをそっちにするのは自然なんだけど。
逆に、これまで通り(Rails4みたいに)belongs_to
のアソシエーションでnull
を許容したい場合は、optional: true
使えばエラーは発生しなくなる。
class Hoge < ApplicationRecord
has_many :children, class_name: 'Hoge', foreign_key: 'parent_id', dependent: :destroy
belongs_to :parent, class_name: 'Hoge', optional: true
end