Home > other >  Pure ruby UK phone number validator
Pure ruby UK phone number validator

Time:10-06

I'm trying to implement a pure Ruby phone number validator for the UK's number. There are a lot of topics related to phone validation but most of them use regex which I want to avoid (mainly because it's unreadable). I'm aware of phone_validator_gem but frankly I don't want to use any additional gems.

Let's make these assumptions:

  • any perfix format allowed ( 447..., 447..., 07...)
  • UK phone numbers are 11 digits long when in the 07... format and always have 7 after the prefix (whether it's 44, 44 or 0)

The implemented module should do:

  • removes any spaces from number
  • check it is valid (raises an error if not)
  • outputs it in the 447... format

E.g. I call format with 071234 56789 as the input, it should return 447123456789. If I call it with 063434, it should raise an error.

I've no idea is there any way to avoid regex? What I did so far is just simple removing whitespaces and check if it's 11 digits.long, my module below:

module Uk
  VALID_PREFIX = ' 447'

  def self.format(number)
    clear_format = number.delete(' ')

    return clear_format if clear_format.delete('^0-9').length == 11 && clear_format[0, 4].includes?(VALID_PREFIX)

  end
end

CodePudding user response:

If you want to avoid gems and regexes, you're doing Rails in hard mode. I would strongly suggest you devote some time to getting comfortable with both.

Parsing phone numbers is always more complicated than you think. For example, your assumption that "UK phone numbers are 11 digits long when in the 07... format and always have 7 after the prefix (whether it's 44, 44 or 0)" is not correct. 07 is just a really common prefix.

It's best to leave it as someone else's problem, so if there's a gem use it. For example, uk-phone-number-formatter seems to do exactly what you want and it is tiny.


Let's say we do this without regexes and without gems and assume 07 is the only prefix. First, separate the problem into two steps.

  1. Normalization
  2. Validation

Normalization is reformatting the phone number so that equivalent phone numbers look the same. Validation is validating its a phone number. Validation is much easier if the data has already been normalized.

That means stripping everything that isn't a digit, fixing the prefx, and adding the at the front.

Stripping everything that isn't a digit is easy with gsub: phone.gsub!(/\D /). Or the non-regex delete: phone.delete('^0-9').

Now with non-numbers out of the way, we just want to change "07" into "447".

Finally, add the .

def normalize(phone)
  # Strip non-digits.
  normalized = phone.delete('^0-9')

  # Replace 07x with 447x  
  if normalized[0..1] == "07"
    normalized[0] = "44"
  end

  # Add the plus.
  return " #{normalized}"
end

Now that it's normalized, validation is easy.

# We assume the phone number is validated.
def phone_is_uk_format(phone)
  errors.add(:phone, :missing_prefx, message: "Missing  447 prefix")
    if normalized[0..3] != " 447"

  # 12 because of the leading  
  errors.add(:phone, :wrong_length, message: "A phone number is 11 digits")
    if normalized.length != 12
end

And integrating it with a model...

class Person < ApplicationRecord
  validate :phone_is_uk_format

  # Normalize the phone number when it is set.
  def phone=(number)
    super(normalize_uk_phone(number))
  end

  private def phone_is_uk_format
    # Validating presence is different.
    return if phone.blank?

    errors.add(:phone, :missing_prefx, message: "Missing  447 prefix")
      if phone[0..3] != " 447"

    # 12 because of the leading  
    errors.add(:phone, :wrong_length, message: "A phone number is 11 digits")
      if phone.length != 12
  end

  private def normalize_uk_phone(phone)
    # Strip non-digits.
    normalized = phone.delete('^0-9')

    # Replace 07x with 447x  
    if normalized[0..1] == "07"
      normalized[0] = "44"
    end

    # Add the plus.
    return " #{normalized}"
  end
end
  •  Tags:  
  • ruby
  • Related