同じタイプのエンティティに親子関係をもたせるときにparent_idのようなカラムを作って親のIDを持たせることがあると思います。
例えば下記のようなテーブルです。
親を持たない場合はNULLを入れる想定のためNULLを許可しています。
Hoges
+----------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------+------+-----+---------+----------------+
| id | bigint | NO | PRI | NULL | auto_increment |
| parent_id | bigint | YES | | NULL | |
| created_at | datetime(6) | NO | | NULL | |
| updated_at | datetime(6) | NO | | NULL | |
+----------------+------------------+------+-----+---------+----------------+
Hogeテーブルのモデルを作ると下記のようになります。
nilを許可するためにoptional: true
をつけています。
class Hoge < ApplicationRecord
belongs_to :parent, class_name: 'Hoge', optional: true
end
ただ、optionalの場合はHogesテーブルに存在しないidをparent_idに入れた場合もバリデーションはOKになってしまいます。
※Hogeテーブルに適切に外部キー制約を付けていれば存在しないIDはを指定した場合はエラー(ActiveRecord::InvalidForeignKey
)になります。
そこでタイトルに書いてある通り、nilは許可しつつ存在チェックはしたい場合の書き方を考えてみました。
カスタムバリデーションを使えばなんとでもなるのですが、できる限りシンプルにRailsに組み込まれているバリデーションを使って書いてみました。
もっと良い方法があればぜひ教えて下さい!!
(これを考えながら、そもそもbelongs_toのoptional: true
はnilは許可するけど関連が存在しないIDは許可しないになってくれるとありがたいなーと思ったりしました。)
class Hoge < ApplicationRecord
belongs_to :parent, class_name: 'Hoge', optional: true
validates :parent, presence: true, if: :parent_id?
end