はじめに
私は普段Ruby on Railsで開発をしているのですが、その中でRailsのActive Recordの持つバリデーション機能をよく使います。
先日改めて公式ドキュメントを読んだので、以前の自分に対する自戒を込めて、オプションについて紹介したいと思います。
知らないともったいないオプション
以前の私は、安易にvalidateメソッドを使用している事がありました。とてもシンプルなバリデーション(存在チェックするだけ、文字数チェックするだけ、数値チェックするだけなど)以外は全部validateで書けばいいじゃん!と思っていました。しかし、validatesメソッドを用いることで、無駄に独自バリデーションメソッドを書かずに済むし、読む方も分かりやすいし、いいこと尽くしです。そして何より、Railsを使ってるのに用意されたオプションを使いこなしてないのは、とてもダサい...。ということで、以前の自分ならvalidateメソッドで書いてたかもしれないバリデーションをちゃんとvalidatesで書く場合に使えるオプションを紹介します。
-
:if
オプション
このオプションでは、ブーリアンを返却する条件を指定することで、特定の条件時にバリデーションを発動させることが出来ます。
バリデーションの実行直前に呼び出されるメソッド名を、:ifや:unlessオプションにシンボルで指定したり、Procやlambdaを用いてその場で条件を書いたり、引数が必要なメソッドを呼び出す事ができます。
例えば、支払いフォームにおいて、カード払いを選択されている場合のみカード番号のバリデーションを実行するという場合、オプションを知らなければこんな感じで書いてしまうかもしれません。validateの行を読んだだけでは具体的にどんなバリデーションなのかわかりませんし、メソッド内も条件分岐が複数出てきて、シンプルな仕様に対してコード数がかかっている気がします。。
class Order < ApplicationRecord
validate :validate_card_number
def validate_card_number
return unless payment_type == "card"
errors.add(:card_number, '入力してください') if card_number.blank?
end
end
しかし、オプションを知っていれば、以下のように書くことが出来ます。validatesの一行を見るだけで、何に対するどんなバリデーションがどんな条件のときに実行されるのか一瞬で理解できます。
class Order < ApplicationRecord
validates :card_number, presence: true, if: :paid_with_card?
def paid_with_card?
payment_type == "card"
end
end
[引用] Railsガイド
さらに、with_options
を用いることで以下のように、
一つの条件で複数のバリデーションをコントロールすることが出来ます。
class User < ApplicationRecord
with_options if: :is_admin? do |admin|
admin.validates :password, length: { minimum: 10 }
admin.validates :email, presence: true
end
end
[引用] Railsガイド
-
:on
オプション
このオプションではバリデーション実行のタイミングを指定します。以下のように、指定したコンテキストでのみバリデーションを実行します。
class User < ApplicationRecord
validates :name, presence: true, on: :foo
end
user.valid?(:foo)
また、unless: -> { validation_context == :foo }
のように
指定したコンテキスト以外の時にバリデーションを実行することも出来ます。
-
:allow_nil
オプション
読んで字の通り、中身がnilの時にバリデーションを通過させるオプションです。nilの時にはバリデーション書けなくていいんだよな、という時って結構あると思います。ちゃんと使っていきたいです。
使わないとこんなことになります。
class Coffee < ApplicationRecord
validate :validate_size
def validate_size
return if size.nil?
errors.add(:size, '有効な値ではありません') unless %w(small medium large).include?(size)
end
end
class Coffee < ApplicationRecord
validates :size, inclusion: { in: %w(small medium large),
message: "%{value}は有効な値ではありません" }, allow_nil: true
end
-
:allow_blank
先程の:allow_nil
と同様、読んで字の通り、中身がblankの時にバリデーションを通過させるオプションです。
最後に
今回紹介したオプション以外にも、:strict
オプションや:message
オプションもありますし、lengthのバリデーションを行う際のオプションやnumericalityのバリデーションを行う際のオプションもあります。公式ドキュメントを見たことない人がもしいれば、必ず目を通しておいたほうがいいと思います。公式ドキュメントは宝の山です。
私も、オプション使いこなして、読みやすくて無駄のない適切なコード目指してレベルアップしていきたいと思います!
【参考・引用】