LoginSignup
18
17

More than 3 years have passed since last update.

Railsで電話番号(固定電話・携帯電話)を正規表現で表し、バリデーションとテストを書いてみた

Last updated at Posted at 2020-06-21

はじめに

電話番号のバリデーションをするために電話番号を正規表現で表してみた。

正規表現については下記を参考にしてください。

初心者歓迎!手と目で覚える正規表現入門・その1「さまざまな形式の電話番号を検索しよう」
Ruby | Rubular で ruby の正規表現を検証しながら作成 #ruby #正規表現
Rubular(正規表現を検証しながら確認できます)

電話番号の前提条件

電話番号には様々な組み合わせ(桁数・ハイフン・括弧)があるが今回は下記を前提として表現する

・固定電話
 ・全部で10桁
 ・頭が0
 ・末尾は4桁
 ・ハイフンや括弧が入る可能性がある(なくても良い)

・携帯電話
 ・全部で11桁
 ・1,3桁目は0
 ・2桁目は5-9
 ・ハイフンや括弧が入る可能性がある(なくても良い)

これらを満たす電話番号のパターンは大きく分けて下記ようになる。(0は固定でxには任意の数字が入る)
・固定電話(10桁)

0x-xxxx-xxxx
0xx-xxx-xxxx
0xxx-xx-xxxx
0xxxx-x-xxxx

・携帯電話(11桁)
050-xxxx-xxxx
060-xxxx-xxxx
070-xxxx-xxxx
080-xxxx-xxxx
090-xxxx-xxxx

正規表現で表す(コピペでOK!!)

固定電話:\A0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1})[-)]?\d{4}\z
携帯電話:\A0[5789]0[-]?\d{4}[-]?\d{4}\z
正規表現_Rubular.png

正規表現の解説

\A: 頭文字を表す
\d{n}: n桁の数字
[-(]?: "-"もしくは"("が入る (どちらもない場合もある)
|: or
\z: 最後の文字

読みやすくするために、下記のように区切ってみた。
(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1}) が長くてわかりにくくしていので "|"で改行した。

【固定電話】
正規表現_固定.png

【携帯電話】
正規表現_携帯.png

Rspecでのバリデーションとテスト

ここまでを考慮して電話番号のバリデーションとテストを書いてみた。

User.rb
class User < ApplicationRecord
  VALID_PHONE_NUMBER_REGEX = /\A0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1})[-)]?\d{4}\z|\A0[5789]0[-]?\d{4}[-]?\d{4}\z/
  validates :phone_number, presence: true, format: { with: VALID_PHONE_NUMBER_REGEX }
end
user_spec.rb
RSpec.describe User, type: :model do
  before do
    stub_const('VALID_PHONE_NUMBER_REGEX', \A0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1})[-)]?\d{4}\z|\A0[5789]0[-]?\d{4}[-]?\d{4}\z)
  end

  context 'フォーマット' do
    let(:user) { FactoryBot.create(:user) }  # 別ファイルでUserのFactoryBotを作成しています。

    it 'phone_numberのフォーマットが適切であること' do
      expect(user.phone_number).to match(VALID_PHONE_NUMBER_REGEX)
    end
  end
end

@jnchitoさんに頂いたコメントを参考に下記を追加しました。(2020/6/22)

spec/factories/users.rb
FactoryBot.define do
  factory :user do
    phone_number { "0#{rand(0..9)}0#{rand(1_000_000..99_999_999)}" }
    # 1,3桁目が0, 全部で10-11桁の電話番号を生成
  end
end
18
17
3

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
18
17