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 |
具体的な実装内容 《本編》
バリデーションを実装したいテーブルと関連するモデルに、次の内容を記述します。
# 「携帯電話番号か固定電話番号のうち、どちらか一方だけの入力が必須」という場面
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)ように制限するための制約)はどちらのカラムにも設定します。
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で、どちらか一方のカラムを入力必須(二者択一)にするバリデーション