LoginSignup
24
16

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-03-19

はじめに

Ruby on Rails で どちらか一方のカラムを入力必須にするバリデーションについて書きます。

具体的な例をあげると、ユーザーモデルのemailphone、どちらか片方だけに必ず値が入るようにバリデーションします。両方に値が入っている場合もNGです。

要件に合わなかったバリデーション

ググって下記のようなバリデーションを見つけましたが、両方入力した場合にバリデーションを通ってしまうので、要件には合いません。

app/models/user.rb
class User < ApplicationRecord
  # phoneが空ならば、emailを必須にする
  validates :email, presence: true, unless: :phone?

  # emailが空ならば、phoneを必須にする
  validates :phone, presence: true, unless: :email?
end
User.create!(name: "たなか", email: "test@example.com", phone: "08011112222")

=> #<User id: 1, name: "たなか", email: "tanaka@example.com", phone: "08011112222", created_at: "2020-03-19 12:29:20", updated_at: "2020-03-19 12:29:20">

要件にあったバリデーション

要件を満たすために、次のカスタムバリデーションを作成しました。

app/models/user.rb
class User < ApplicationRecord
  validate :required_either_email_or_phone

  private

  def required_either_email_or_phone
    # 演算子 ^ で排他的論理和(XOR)にしています
    # emailかphoneのどちらかの値があれば true
    # email、phoneどちらも入力されている場合や入力されていない場合は false
    return if email.present? ^ phone.present?

    errors.add(:base, 'メールアドレスまたは電話番号のどちらか一方を入力してください')
  end
end
User.create!(name: "たなか", email: "tanaka@example.com", phone: "08011112222")

# => ActiveRecord::RecordInvalid (バリデーションに失敗しました: emailまたはphoneのどちらか一方を入力してください)

User.create!(name: "たなか", email: nil, phone: nil)

# => ActiveRecord::RecordInvalid (バリデーションに失敗しました: emailまたはphoneのどちらか一方を入力してください)

User.create!(name: "たなか", email: "tanaka@example.com", phone: nil)

# => <User id: 2, name: "たなか", email: "tanaka@example.com", phone: nil, created_at: "2020-03-19 13:06:55", updated_at: "2020-03-19 13:06:55">

おわり

普段は論理和 || 演算子 か論理積 && 演算子 ばかりで、^ 演算子は使わないので、上記のコードを思いつくまでに時間をかけてしまいました…!

24
16
1

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
24
16