LoginSignup
2

More than 5 years have passed since last update.

Railsで個別のカラムをバリデーションするvalidate_specific_value gem

Posted at

RailsのActiveRecordで個別のカラムをバリデーションするvalidate_specific_value gemを作った。

このgemを使う利点

通常のバリデーション実行にはmodel#valid?を使うが、このメソッドはそのモデルのすべてのバリデーションを実行してしまう。

バリデーションの内容によってはデータベースでSQLを実行するもの、複雑なRubyのコードを実行するもの、などがあり、毎回すべてのバリデーションを実行してしまうと必要以上にコストがかかってしまうことになる。

app/models/user.rb
class User < ApplicationRecord
  # valid?を呼ぶたびに、emailとnameがユニークかどうかをチェックするSQLを実行する
  validates :email, uniqueness: true
  validates :name, uniqueness: true

  # valid?を呼ぶたびに、高コストなバリデーションが実行される
  validates_with Validations::ComplexValidator 
end

このvalidate_specific_value gemを使えば、特定のカラムだけに対してバリデーションを実行することができる。

validate_specific_value gemの使い方

Gemfileに追加する。

Gemfile
gem 'validate_specific_value'

validates_specificで個別にバリデーションしたいカラムを指定する。

app/models/user.rb
class User < ApplicationRecord
  validates_specific :name
end

validates_specific :attributeとしておくことで、valid_attribute?というメソッドが定義される。

user = User.new(name: 'duplicate_name')
user.valid_name?
# => false

user.errors[:name]
# => ["has already been taken"]

実装の詳細

メタプログラミングで下記の処理を実現している。RailsのAPIで特定のカラムのバリデーションルールをすべて取得し、それをループの中で実行している。

class User < ApplicationRecord
  def valid_name?
    errors.clear
    self.class.validators_on(:name).each do |validator|
      validator.validate_each(self, :name, self[:name])
    end
    errors.empty?
  end
end

参考リンク

validate_specific_value gem

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2