validate 関連先のバリデーションも実行する

使用可能な関連付け

  • belongs_to
  • has_and_belongs_to_many
  • has_many
  • has_one

公式のAPIドキュメントを見る限りでは上記の通り。Rails Guideのvalidateの解説を見るとhas_and_belongs_to_manyでは使えないような説明がされている。

対となる関連に指定するオプション

なし

概要

validate: trueを指定することで関連先のバリデーションを実行する。

少なくとも、belongs_tohas_oneでは、関連元と関連先の双方のレコードが作成済みの状態で、関連先に変更が入っていた場合はバリデーションが実行される。

# 以下のバリデーションがあるとして
# validates :name, presence: true
Profile.create(name: 'suzuki')
Author.create(profile: profile)

# Authorには
# belongs_to :profile, validate: true
# の設定をしてある
author = Author.last
author.profile.name = nil
# profileのバリデーションも実行されるのでfalseになる
author.valid? # => false
author.profile.name = 'yamada'
# trueが返るが、profileが保存されるわけではない
author.save # => true
Profile.last.name # => 'suzuki'

validate: trueの指定がない場合は、Profileのバリデーションは実行されず、author.valid?trueを返している。

新規レコードの場合は、通常は連鎖的に保存されるはずなのでvalidate: trueがあってもなくても同じはずである。

has_manyhas_and_belongs_to_manyについて挙動を確認してみたが、効果がないようだった。

注意が必要なのは、関連先のバリデーションを実行するが保存するわけではないという点だろう。カウンターキャッシュのような2テーブルが協調してレコードを更新し、バリデーションで有効性をチェックしているような場合にバリデーションだけ実行して保存し忘れないように注意しなければいけない。

正直、動作確認していてかなり混乱した。どういう時に使う機能なのかわからない。歴史的経緯というか古い機能が残り続けているだけな気がする。