目次
概要
Railsのバリデーションでよく使うヘルパーをざっくりまとめました。 まだ働いて1年も経っていないので、仕事を通して重要だなと感じたやつは随時追加していきます。
バリデーションでよく使うヘルパー
バリデーションって言葉はvalid(有効な)が由来なので、「有効か?、有効ではないか?」を検証しているんだと思っていただけると理解しやすいです。
presence
このヘルパーは、指定した属性が空でないことを検証します。属性が空であることが許されない場合に、使用します。
class Event < ApplicationRecord include Hashid::Rails belongs_to :user validates :reserve_date, presence: true end
numericality
このヘルパーは、属性が数値のみを持つかどうかを検証します。整数値のみを許可するように指定するには、:only_integer を true に設定します。
class Event < ApplicationRecord include Hashid::Rails belongs_to :user # validates :price, numericality: trueと書くと、少数も通してしまう validates :price, numericality: { only_integer: true } end
only_integer以外にも、許容値に制約を加えるため様々なオプションが存在します。主に重さや値段など0より小さいことが許されない場合や、属性の値をある数値と比較して検証したい場合に、numericalityヘルパーを使用します。
class Event < ApplicationRecord include Hashid::Rails belongs_to :user validates :price, numericality: { greater_than_or_equal_to: 0 } # 0より大きい値のみ許容する場合は、greater_thanを使用する validates :price, numericality: { greater_than: 0 } # numericalityには複数のオプションを指定できる validates :contents_quantity, numericality: { only_integer: true, greater_than_or_equal_to: 1 }, allow_nil: true end
length
このヘルパーは、属性の値の長さを検証します。何文字以上何文字以下を検証したい場合、inオプションを指定します。
class User < ApplicationRecord validates :name, length: { minimum: 2 } # inオプションは、属性の長さは、与えられた間隔に含まれなければならないことを検証します # 以下の場合、6文字以上20文字以下ならOK validates :password, length: { in: 6..20 } # isオプションは、属性の長さは、与えられた値と等しくなければならないことを検証します # 以下の場合、6文字であればOK validates :registration_number, length: { is: 6 } end
(注) あくまでlengthオプションは、文字列の長さを検証するだけなので、数値の大小などは検証できません。数値の大小を検証したい場合、numericalityヘルパーを使用します。
comparison(Rails7)
Rails7からcomparisonヘルパーが追加されました。このヘルパーのおかげで、日付の検証で独自の検証メソッドを定義しなくても、検証できるようになりました。
このヘルパーは、比較可能な任意の2つの値の比較を検証します。主に日付の比較をしたい時に使用します。過去の日付で予約日を入力できないようにしたり、未来の日付で記録した日を入力できないようにしたい場合に使用します。
class Event < ApplicationRecord include Hashid::Rails belongs_to :user validates :date, comparison: { less_than_or_equal_to: proc { Date.today } } validates :reserve_date, comparison: { greater_than_or_equal_to: proc { Date.today } }, allow_nil: true end
(注) procを書かないと挙動がおかしい時があるので、必ず書きましょう。
uniqueness
このヘルパーは、オブジェクトが保存される直前に属性の値が一意であることを検証します。DBの一意制約とは違うので、DB側にも一意制約を設定しておきましょう。メールなど、一意であってほしい値を検証するときにuniquenessヘルパーを使用します。
class User < ApplicationRecord validates :email, uniqueness: true end
独自の検証メソッドを使ったバリデーション
validatesメソッドに用意されているヘルパーでは有効性を検証できない場合に使用します。事前に検証用のプライベートメソッドを定義しておいて、validateメソッドにそのプライベートメソッドを指定します。valid? メソッドは、errors コレクションが空であることを確認します。したがって、プライベートメソッド内で検証が失敗した場合、errors.addを実行する必要があります。モデルに定義すべきでないメソッドをモデル内に定義することは、ファットモデルの原因になるので、ヘルパーで対処できる場合は、そちらを優先的に利用しましょう。
class Event < ApplicationRecord include Hashid::Rails belongs_to :user validate :discount_cannot_be_greater_than_total_price # 省略 private def discount_cannot_be_greater_than_total_price if discount > total_price errors.add(:discount, "can't be greater than total value") end end end
参考記事
Active Record Validations — Ruby on Rails Guides