「ちょっとした条件を満たした時だけ、バリデーションを実行したい」みたいなことが何度かあったので、その辺りの備忘録。

あるパラメータが入力されている時だけバリデーションしたい場合

例)fugaが入力されている時だけhogeも入力必須としたい。

NoMethodError (undefined method `validate' for true:TrueClass)

ダダダっと勢いで次のようなコードを書くと怒られる。

class User < ApplicationRecord
  validates :hoge, presence: true, if: :fuga.present?
end

条件付きバリデーション - Railsガイド

ついifやunlessの後には条件式を書きたくなるが、

引数にはシンボル、ProcまたはArrayを使えます。

とのこと。

Procを使う場合

class User < ApplicationRecord
  validates :hoge, presence: true, if: Proc.new { |user| user.fuga.present? }
end

1行で書けるのがメリット。

メソッドを定義してシンボルを使う場合

条件が複雑になる場合や、使い回す場合はProcよりもこっちで書くほうが良さそう。

class User < ApplicationRecord
  validates :hoge, presence: true, if: :present_fuga_and_piyo?

  private
    def present_fuga_and_piyo?
      fuga.present? && piyo.present?
    end
end

よく見る形。

どちらかのパラメータを必須としたい場合

例)hogeとfugaのどちらか片方は必須としたい。

validates :hoge_or_fuga, presence: true

private
  def hoge_or_fuga
    hoge.present? || fuga.present?
  end

boolを返すメソッドを定義して、validatesの第一引数に指定する。