Edited at

カスタムバリデートでバリデーション前編 初心者→中級者へのSTEP3/25


カスタムバリデートでバリデーション前編

はじめに

前回の記事ではControllerでのバリデーションの具体例としてフォームオブジェクトを紹介しました。今回はモデルでのバリデーションとして、ロジックな検証をカスタムバリデートを用いてしていきます。


カスタムバリデートとは

Railsに組み込まれているバリデーションだけでは足りない時、プロジェクト仕様のバリデーションルールを追加することになりますが、それを全てmodelに書くと可読性が悪くなります。管理も大変です。てな訳でバリデートクラスなるものを作って独自のルールをそこにまとめようということです。


個別のEachValidator

カスタムバリデータを追加するには二つのアプローチがあります。

まずは個別の属性にバリデートをかけるEachValidatorについて説明します。

今回はemailのバリデーションを例にします。emailがちゃんとemailの形式を取っているかのバリデーションです。

app/validtors/階層に、カスタムバリデータクラスとしてemail_validator.rbを作成します。


email_validator.rb

class EmailValidator < ActiveModel::EachValidator

def validate_each(record, attribute, value)
unless value =~ /\A[a-zA-Z0-9_\#!$%&`'*+\-{|}~^\/=?\.]+@[a-zA-Z0-9][a-zA-Z0-9\.-]+\z/
record.errors[attribute] << (options[:message] || "はメールアドレスではありません")
end
end
end

個別の属性にバリデートをかけるカスタムバリデートを作成する場合、validate_eachを定義する必要があります。

validate_eachの引数、recordに呼び出し元のモデルインスタンスが入り、attributeに属性、valueに値が入ります。このメソッド内で呼び出し元のモデルインスタンスの属性値がemailとして正しい形式か検証しています。

ちなみに正規表現にて検証してますが、これにマッチしないとerrors[]にメッセージが格納されます。実はここの記述がないとエラー時にfalseを返してくれません。erros[]にエラーメッセージがあることで、そのデータは正しくないデータと判定します。

クラス名も重要です。~~Validatorとクラスを名付ければ,モデルにて:~~で呼び出せます。

つまり、下記のようになります。


User.rb

class User < ApplicationRecord

validates :email, presence: true, email: true
end

これでemail属性にだけ先ほどカスタムバリデートクラスに記述した正規表現で検証できます。


まとめ

カスタムバリデートによる個別の属性の検証はこんな感じです。今回はルールがemailとして正しいかだけの検証だったのであまり差を感じませんが、もっと複雑なルールの場合、モデルにそれを書くよりこのカスタムバリデートクラスにまとめた方が、スッキリしていいですよね。

次回はもう一つのアプローチ、レコード一つ対象にバリデートをかけるものを説明してみます。


参考にしたの

Active Record バリデーション

https://railsguides.jp/active_record_validations.html#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%BF

【パーフェクトRails】バリデーションをクラスに分離する

https://waterlow2013.hatenablog.com/entry/2016/10/11/011312

メールアドレスの妥当性を正規表現でチェックする

http://rubytips86.hatenablog.com/entry/2014/03/28/135838