波打際のブログさん

主に、プログラミング備忘録など。

Rails4のバリデータをテストまでしっかり書いた備忘録

はじめに

 Rails4には様々なバリデータが用意されていますが、プロダクトを実装する過程で自作のバリデータを定義して使いたくなることが稀によくあります。稀によくある事なので、その都度使い方を調べていていますが、バリデータの実装からロケールファイルの定義、テストの書き方までまとまっているページがないので備忘録程度にまとめておきます。

バリデータ

今回作るバリデータについて

 バリデーション対象のカラムの内容が hoge であるかチェックするHogeValidatorを作成します。バリデーションのオプションで hoge が連続する回数を指定できるようにします。

# text が `hoge` であることのバリデーション
validates :text, :hoge => {:count => 1}

# text が `hogehoge` であることのバリデーション
validates :text, :hoge => {:count => 2}


こんな感じで使えるバリデータを作ります。

バリデータの定義

 `app/validators` フォルダに `hoge_validator.rb` を作ります。

class HogeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless ('hoge' * options[:count]) == value
      record.errors.add(attribute, :hoge, options)
    end
  end
end

ロケールの定義

 通常のバリデーションエラーメッセージと同様に記述していきます。

ja:
  activerecord:
    errors:
      messages:
        hoge: 'hoge成分が足りません。'

テスト

 `spec/validators/` フォルダに `hoge_validator_spec.rb` を作ります。

require 'spec_helper'

describe HogeValidator do
  let :validator do
    HogeValidator.new({:attributes => [attribute]}, :count => 1)
  end

  let :errors do
    ActiveModel::Errors.new(mock_class)
  end

  let :attribute do
    :text
  end

  let :mock_class do
    double('model').tap do |mock|
      allow(mock).to receive(:class) { ActiveRecord::Base }
      allow(mock).to receive(:errors) {errors}
      allow(mock).to receive(:read_attribute_for_validation) {attribute_value}
    end
  end

  subject do
    validator.validate_each(mock_class, attribute, attribute_value)
    errors.empty?
  end

  context 'ただしくHogeってる時' do
    let :attribute_value do
      'hoge'
    end

    it 'バリデーションが通ること' do
      expect(subject).to be_truthy
    end
  end

  context 'Hogeってないとき' do
    let :attribute_value do
      'fuga'
    end

    it 'バリデーションが通らない' do
      expect(subject).to be_falsey
    end
  end
end

 今回は省略しましたが、エラーメッセージに関するテストを行うとさらに良いと思います。