はじめに
現在、共同開発にてドキュメント作成アプリを開発中です。
その中でAncestryを用いた階層構造を実装しており、機能としてはドキュメント作成時にタイトル部分に/
を入力して、文章を区切ることによりディレクトリが作成できるようになっています。
今回はディレクトリの階層を5階層までにしたかったので、バリデーションをかけようと思います。しかし、デフォルトのバリデーションオプションでは難しそうでした。
そこで色々調べていくとActiveModel::EachValidator
を使うことで、独自のバリデーションを追加することが分かり便利だなと思ったため、備忘録として使い方を残しておきます。
カスタムバリデーターの作成
カスタムバリデーターとは
ActiveModel::Validator
やActiveModel::EachValidator
を使って自作のバリデーションを作成することです。
独自のバリデーションルールを追加しようとする時に、modelに書くと可読性が悪くなり、更には管理も大変になってしまいます。それを防ぐためにバリデートクラスと呼ばれる、バリデーションを自作するためのクラスを継承したクラスを作ります。
今回は使いやすいということで、ActiveModel::EachValidator
を継承したクラスを作成して、そこに独自のバリデーションルールを書いていきます。
ファイルの作成
-
app/
配下にvalidators
ディレクトリを作成します。 -
app/validators/<検証名>validator.rb
の形式でファイルを作成 -
ActiveModel::EachValidator
を継承したクラスを作成
class AncestryValidator < ActiveModel::EachValidator
end
ここで指定したクラス名が、modelでカスタムバリデーターを呼び出す際に使われます。
これでカスタムバリデーションを実装する準備ができたため、後はこのファイルにロジックを書いてあげれば完了です。
バリデーションルール作成
まずはカスタムバリデーション用にRailsが用意してくれている、validate_each
メソッドを追加しましょう。
class AncestryValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
end
end
validate_each
メソッドの3つの引数
validate_each
メソッドの3つの引数の中身にはそれぞれ、以下の値が入ります。
record
ここにはオブジェクトが入ります。
attribute
これには属性が入ります。
今回で言えば:ancesty
が返ってきます。
value
ユーザーが入力した値が入ります。
文字数検証などに使います。
以上のことを踏まえた上で、カスタムバリデーションを設定していきましょう!
カスタムバリデーション設定
今回は5階層以降のディレクトリを作成したくないため、以下のように設定しました。
class AncestryValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value.count("/") > 3
record.errors.add(attribute, "ディレクトリは6つ以上作成できません!")
end
end
end
/
の数により何階層目かを判断して、3つ以上になると6階層目になるためバリデーションに引っかかるようにしています。
record.errors.add(属性, メッセージ)
上記のようにすることでバリデーションを発生させて、メッセージを追加することができます。
属性を指定することで、今回なら「ancestryディレクトリは6つ以上作成できません!」と表示されるようになります。
呼び出し
最後に設定したバリデーションを使えるように、対象のモデルでカスタムバリデーションを呼び出す記述を追加しましょう!
validates :ancestry, ancestry: true
この記述により、ancestryカラムに対してAncestryValidatorクラスのカスタムバリデーションを適応させることができます。
まとめ
今回はActiveModel::EachValidator
を使った、独自のバリデーションを作成する方法について紹介しました。
初めて自作のバリデーションを作成しましたが、これを使いこなせるようになれば何でも検証できて便利だなと思ったので、ぜひ使いこなせるようになりたいと思います!