Railsのモデルでの条件付きバリデーション
Railsアプリケーションのモデルにおけるバリデーションを行う際に、自分の書き方が良くなかったことから色々とバリデーションの書き方の勉強になったので、まとめてみます。
Railsのモデルファイルを考えた時、そのモデルがあるフラグがONである場合のみバリデーションを実行したいとします。その時に自分は次のように書いてしまっていました。今回は仮にMessageというモデルとします。
class Message
...
attr_accessor :send_flag
before_validation :check_send_date
...
private
def check_send_date
... if send_flag # (send_flagがONである場合のみ実行)
end
end
上のコードが自分が書いた良くなかったコードの例です。before_validationで必ずバリデーションメソッドを実行して、メソッドの中に条件文を書くことにより、send_flagがONになっている場合のみチェックが実行されるように書いていましたが、この書き方だと条件に関らずバリデーションメソッドが実行される事になります。つまり行う必要がない場合でも現状バリデーションメソッドを無駄に実行しています。そこでバリデーションメソッドに条件を書くのではなく、
class Message
...
attr_accessor :send_flag
before_validation :check_send_date, if: -> { send_flag == true } # ←条件文をbefore_validationに移行
...
private
def check_send_date
...
end
end
また今回の例だけでなく、Railsのコントローラーのcreateメソッドが実行されるタイミングでのみバリデーションメソッドを実行したいという時などもあると思います。そのような時はbefore_validationの行の末尾などにon::create を加えると、コントローラーのcreateメソッドが実行される時にのみバリデーションが実行されます。
まとめ
Railsのモデルでバリデーションを実装する場合、不要にバリデーションが実行されるのを防ぐため条件や、条件を付け加える場所をしっかりと考えて無駄のないバリデーションを行っていきたいと思います。