1
0

【Rails】どちらか一方のデータ(カラム)のみを入力必須にするバリデーション

Last updated at Posted at 2023-12-01

Railsを使ったWebアプリの開発中、「2つの入力欄のうち、片っ方だけが入力されていればOK、っていうバリデーション付けられたらかっけぇ...」と思い、実際にその機能をつけました。

用意された2つの入力欄のうち、どちらか一方のデータ(カラム)のみを入力必須にするバリデーションを付与することは、とてつもなく重要です。実際、「携帯電話番号か自宅などの固定電話番号のうち、どちらか一方だけは入力が必須」という場面はよく見かけます。

そこで、「2つのデータのうち、どちらか一方のデータのみが入力されれば保存される」=「2つのデータ両方が入力された場合は保存されない」という、二者択一入力必須条件をRailsで実装する手順をまとめました。

二者択一入力必須条件をつける手順説明は、次の内容でまとめました。

  • 開発環境
  • 具体的な実装内容 《本編》
  • 実装のポイント:『排他的論理和:"^"』

開発環境

Category Value,Version
OS MacOS Sonoma 14.1.2
Ruby 3.2.0
Ruby on Rails 7.0.8

具体的な実装内容 《本編》

バリデーションを実装したいテーブルと関連するモデルに、次の内容を記述します。

models/x.rb

  # 「携帯電話番号か固定電話番号のうち、どちらか一方だけの入力が必須」という場面

class X < ApplicationRecord

  validate :required_either_mobile_number_or_landline_number

  private

  def required_either_mobile_number_or_landline_number
    return if mobile_number.present? ^ landline_number.present?
    # "^"は『排他的論理和』という論理演算子の一種です。本実装のポイントになります。
  end

end

補足

「どちらか一方のデータのみが入力されれば保存される」という条件ですが、マイグレーションファイルのNOT NULL制約(テーブルの属性値に空の値(NULL)が入らない(NOT)ように制限するための制約)はどちらのカラムにも設定します。

db/migrate/2023〜〜〜.rb
class CreatePersonalinformation < ActiveRecord::Migration[7.0]
  def change
    create_table :personalinformation do |t|
      t.string     :mobile_number,  null: false # NOT NULL制約
      t.string     :landline_number,  null: false # NOT NULL制約
      t.timestamps
    end
  end
end

実装のポイント:『排他的論理和:"^"』

今回の条件を満たすバリデーションを実装する際におさえるべきポイントは、次の点です。

「どちらか一方のデータ(カラム)のみ入力必須」は『排他的論理和:"^"』という論理演算子で与える。

「排他的論理和」とは?|Ruby公式ドキュメント

具体的にどういう論理演算子なのか、「⭕️データを保存できるパターン」と「❌データを保存できないパターン」に分けて、それぞれ解説します。

まず、「⭕️データを保存できるパターン」として、次の場合が挙げられます。

⭕️パターン①:「2つのデータ(カラム)のうち、どちらか一方のデータのみが入力された」場合

「true ^ false(false ^ true)」の場合

↓ つまり...

「mobile_number.present?とlandline_number.present?のうち、どちらか一方がtrueかつどちらか一方がfalse」という場合

一方、「❌データを保存できないパターン」として、「2つのデータ両方が入力された」場合と、「2つのデータ両方とも入力されない」場合、というパターンが挙げられます。

❌パターン①:「2つのデータ両方が入力された」場合

排他的論理和が「true ^ true」の場合

↓ つまり...

「mobile_numberが入力された(true)かつ landline_numberが入力された(true)」という場合

❌パターン②:「2つのデータ両方とも入力されない」場合

排他的論理和が「false ^ false」の場合

↓ つまり...

「mobile_numberが入力されない(false)かつ landline_numberが入力されない(false)」という場合

ここまで挙げたパターンは、モデルの単体テストをする際にも重要です。


プログラミング学習のアウトプット、以上になります。
ご指摘あれば、お気軽にコメントください。

参考記事:Railsで、どちらか一方のカラムを入力必須(二者択一)にするバリデーション

1
0
0

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
1
0