Railsのvalidationで値が空であることを検証する absence: true

こんにちは!kossyです!




さて、今回はRailsのvalidationで値が空であることを検証する absence: trueの使い方について、
ブログに残してみたいと思います。



環境

Ruby 2.6.6
Rails 6.0.3.4
MacOS catalina



まずはドキュメントを読んで使い方を把握しよう


2.10 absence
このヘルパーは、指定された属性が「空」であることを検証します。値がnilや空文字である (つまり空欄またはホワイトスペースである) かどうかを確認するために、内部ではpresent?メソッドを使っています。

class Person < ApplicationRecord
  validates :name, :login, :email, absence: true
end

関連付けが存在しないことを確認したい場合は、関連付けられたオブジェクト自体が存在しないかどうかを確認し、そのオブジェクトが関連付けにマッピングされた外部キーでないことを確認する必要があります。

class LineItem < ApplicationRecord
  belongs_to :order
  validates :order, absence: true
end

関連付けられたレコードが存在してはならない場合、これを検証するには:inverse_ofオプションでその関連付けを指定する必要があります。

class Order < ApplicationRecord
  has_many :line_items, inverse_of: :order
end

このヘルパーを使って、has_oneまたはhas_manyリレーションシップを経由して関連付けられたオブジェクトが存在しないことを検証すると、presence?でもなくmarked_for_destruction?(削除するためにマークされている)でもないかどうかがチェックされます。

false.present?は常にfalseなので、真偽値に対してこのメソッドを使うと正しい結果が得られません。真偽値が存在しないことをチェックしたい場合は、validates :field_name, exclusion: { in: [true, false] }を使う必要があります。

デフォルトのエラーメッセージは「must be blank」です。

指定された値がnullかどうかを確認するバリデーションオプションです。

上記で挙げられた例以外にどういう風に使えるか少し考えてみました。

with_optionsメソッドと組み合わせて、特定の条件下でバリデーションが発火するようにする

一つの使用例として、with_optionsと組み合わせるやり方があると思います。

例えば、「公開 / 非公開」を管理する is_published という属性と、「公開日」を表すpublished_atという属性があったとします。
普通に考えれば、「非公開」なのに、published_atに値が入っている状態は異常な状態かと思います(アプリケーションの要件にもよると思いますが、、、

このような場合、

class Post < ActiveRecord::Base

  with_options if: :private? do
    validates :published_at, absence: true
  end
end

のように、非公開状態の時だけ値がnullであることを検証するバリデーションを記載することができます。




勉強になりました。



大いに参考にさせていただいたサイト

この場を借りて御礼を申し上げます。


tbpgr.hatenablog.com