[Ruby] I tried to write a validation and test by expressing a phone number (fixed phone / mobile phone) with a regular expression in Rails

1 minute read

Introduction

I tried to express the phone number with a regular expression to validate the phone number.

Please refer to the following for regular expressions.
Beginners welcome! Introduction to Regular Expressions with Hands and Eyes, Part 1 “Let’s Search for Phone Numbers in Various Formats” Ruby | Created while verifying ruby regular expression with Rubular #ruby #regular expression Rubular(Youcancheckwhilevalidatingtheregularexpression)

Phone number prerequisites

There are various combinations (number of digits, hyphens, parentheses) in the telephone number, but this time we will assume the following

·Fixed-line phone ・10 digits in total ・Head is 0 ・4 digits at the end ・There may be hyphens and parentheses (it is not necessary)

·mobile phone 11 digits in total ・1st and 3rd digits are 0 ・The second digit is 5-9 ・There may be hyphens and parentheses (it is not necessary)

The telephone number patterns that satisfy these are roughly classified as follows. (0 is fixed and x is an arbitrary number) ・Fixed telephone (10 digits)

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

・Mobile phone (11 digits) 050-xxxx-xxxx 060-xxxx-xxxx 070-xxxx-xxxx 080-xxxx-xxxx 090-xxxx-xxxx

Express with regular expressions (copy and paste OK!!)

** Fixed line: \A0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d {3}[-(]?\d{2}|\d{4}[-(]?\d{1})[-)]?\d{4}\z** ** Mobile phone: \A0[5789]0[-]?\d{4}[-]?\d{4}\z** Regular expression_Rubular.png

Regular expression explanation

\A: represents an initial \d{n}: n digits [-(]?: “-“ or “(“ is entered (there may be neither) |: or \z: the last character

For readability, I’ve separated them as follows: (\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\ d{4}[-(]?\d{1}) is long and confusing, so I started a line with “|”.

【Fixed-line phone】 Regular expression_fixed.png

【mobile phone】 Regular Expression_Mobile.png

Validation and testing with Rspec

With that in mind, I wrote a phone number validation and test.

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'format' do
    let(:user) {FactoryBot.create(:user)} # Create a FactoryBot for the User in another file.

    it'phone_number format is correct' do
      expect(user.phone_number).to match(VALID_PHONE_NUMBER_REGEX)
    end
  end
end

The following was added with reference to the comment received from @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, 3rd digit is 0, total 10-11 digit phone number is generated
  end
end