Giter VIP home page Giter VIP logo

phonie's Introduction

Phonie

Parsing, validating and creating phone numbers

Install

You can install the phonie library as a gem

gem install phonie

Initializing

You can initialize a new phone object with the number, area code, country code and extension number

Phonie::Phone.new('5125486', '91', '385')

or

Phonie::Phone.new(number: '5125486', area_code: '91', country_code: '385', extension: '143')

Parsing

You can create a new phone object by parsing from a string. Phonie::Phone does it’s best to detect the country and area codes:

Phonie::Phone.parse '+385915125486'
Phonie::Phone.parse '00385915125486'

If the country or area code isn’t given in the string, you must set it, otherwise it doesn’t work:

Phonie::Phone.parse '091/512-5486', country_code: '385'
Phonie::Phone.parse '(091) 512 5486', country_code: '385'

If you feel that it’s tedious, set the default country code once (in your config/environment.rb):

Phonie.configuration.default_country_code = '385'
Phonie::Phone.parse '091/512-5486'
Phonie::Phone.parse '(091) 512 5486'

Same goes for the area code:

Phonie::Phone.parse '451-588', country_code: '385', area_code: '47'

Alternatively Phonie can be configured via a block

Phonie.configure do |config|
  config.default_country_code = '385'
  config.default_area_code = '47'
  config.add_custom_named_format :short, '%A/%n1-%n2'
end

Phonie::Phone.parse '451-588'

Automatic country and area code detection

Like it’s stated above, Phone does it’s best to automatically detect the country and area code while parsing. To do this, phone uses data stored in data/countries.yml.

Each country code can have a regular expression named area_code that describes how the area code for that particular country looks like.

Validating

Validating is very relaxed, basically it strips out everything that’s not a number or ‘+’ character:

Phonie::Phone.valid? 'blabla 091/512-5486 blabla'

Formatting

Formating is done via the format method. The method accepts a Symbol or a String.

When given a string, it interpolates the string with the following fields:

  • %c - country_code (385)

  • %a - area_code (91)

  • %A - area_code with leading zero (091)

  • %n - number (5125486)

  • %f - first @@n1_length characters of number (configured through Phonie.n1_length), default is 3 (512)

  • %l - last characters of number (5486)

  • %x - the extension number

  • %X - the extension number with prefix

    pn = Phonie::Phone.parse('+385915125486')
    pn.to_s # => "+385915125486"
    pn.format("%A/%f-%l") # => "091/512-5486"
    pn.format("+ %c (%a) %n") # => "+ 385 (91) 5125486"
    

When given a symbol it is used as a lookup for the format in Phonie::Formatter.

pn.format(:europe) # => "+385 (0) 91 512 5486"
pn.format(:us) # => "(234) 123 4567"
pn.format(:default_with_extension) # => "+3851234567x143"

You can add your own custom named formats like so:

Phonie.configuration.add_custom_named_format :short, '%A/%n1-%n2'
pn.format(:short) # => 091/512-5486

ActiveModel validator

Phonie includes an ActiveModel validator. If you are using ActiveModel you can validate phone numbers like so:

class SomeModel
  include ActiveModel::Validations

  validates :phone_number, phone: true
end

model = SomeModel.new(phone_number: '')
model.valid? # false

model = SomeModel.new(phone_number: '+1 251 123 4567')
model.valid?  # true

Similarly you can validate if a number is a mobile number via:

validates :mobile_number, mobile_phone: true

Similarly you can validate if a number is in your default country via:

validates :mobile_number, default_country_phone: true

TODO

Add definitions for more countries

Currently tested on:

AE

UAE

AF

Afghanistan

AL

Albania

AM

Armenia

AR

Argentina

AT

Austria

AU

Australia

AZ

Azerbaijan

BA

Bosnia and Herzegovina

BD

Bangladesh

BE

Belgium

BF

Burkina Faso

BG

Bulgaria

BH

Bahrain

BO

Bolivia

BR

Brazil

BS

Bahamas

BT

Bhutan

BY

Belarus

BZ

Belize

CA

Canada

CH

Switzerland

CN

China

CR

Costa Rica

CU

Cuba

CY

Cyprus

CZ

Czech Republic

DE

Germany

DK

Denmark

DZ

Algeria

EC

Ecuador

EE

Estonia

EG

Egypt

ES

Spain

ET

Ethiopia

FI

Finland

FJ

Fiji

FR

France

GB

United Kingdom

GE

Georgia

GF

French Guiana

GH

Ghana

GP

Guadeloupe

GR

Greece

GT

Guatemala

GU

Guam

GY

Guyana

HK

Hong Kong

HR

Croatia

HU

Hungary

ID

Indonesia

IE

Ireland

IL

Israel

IN

India

IQ

Iraq

IR

Iran

IT

Italy

JM

Jamaica

JO

Jordan

JP

Japan

KE

Kenya

KR

South Korea

KW

Kuwait

LK

Sri Lanka

LT

Lithuania

LU

Luxembourg

LV

Latvia

MA

Morocco

ME

Montenegro

ML

Mali

MT

Malta

MX

Mexico

MY

Malaysia

NG

Nigeria

NI

Nicaragua

NL

Netherlands

NO

Norway

NP

Nepal

NZ

New Zealand

PA

Panama

PH

Philippines

PK

Pakistan

PT

Portugal

QA

Qatar

RS

Serbia

RU

Russian Federation

SA

Saudi Arabia

SC

Seychelles

SE

Sweden

SG

Singapore

SI

Slovenia

SK

Slovakia

SN

Senegal

SV

El Salvador

TO

Tonga

TT

Trinidad and Tobago

TW

Taiwan

TZ

Tanzania

UA

Ukraine

UG

Uganda

US

United States

UY

Uruguay

VE

Venezuela

VN

Vietnam

ZA

South Africa

ZW

Zimbabwe

How you can contribute

More testing is needed to add support for missing countries, and improve support for tested countries. In many cases only minimal testing is done on area codes, local number formats and number length where more exact matching is possible.

The best places to start is to read through the country tests and data/phone_countries.rb

Other libraries

This is based off a fork of the Phone gem (github.com/carr/phone), and was extensively modified for better support of country detection, and supports far more countries.

Contributors

Tomislav Carr, Don Morrison, Michael Squires, Todd Eichel (Fooala, Inc.), chipiga, Etienne Samson, Luke Randall, Wesley Moxam

phonie's People

Contributors

cainlevy avatar carr avatar chipiga avatar dramalho avatar elskwid avatar espen avatar feldpost avatar fzf avatar g1smd avatar grempe-thrillcall avatar ijpiantanida avatar ivalkeen avatar kristianmandrup avatar kwilcox avatar leifg avatar lukerandall avatar lunks avatar mfbmina avatar nofxx avatar peteryates avatar pusewicz avatar rywall avatar sagmor avatar sergiyukr avatar tfe avatar tiegz avatar tiennou avatar vicmargar avatar wmoxam avatar zoer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

phonie's Issues

Add configuration.n2_length

And validate you can't set both?

Some countries, here Brazil example, have n1 variable and n2 fixed:

Toll Free -> (0800) 123-4567
Landline -> (11) 1234-5678
Mobile -> (11) 12345-6789

Problems with 9 digits brazilian mobile phones

Some Brazilian mobile phones now have 9 digits.

Example:

This works
(Phonie::Phone.parse '31992211568', country_code: '55').area_code
31

But when area code is passed in the options instead of number:
(Phonie::Phone.parse '992211568', area_code: '31', country_code: '55').area_code
returns 99 and should return 31

Parsing phone number incorrectly when area code matches country code

We were running into an issue with an Italian number that had an area code that was matching the country code.

This is an example of the problem phone no: +39 393 2612345

We would pass this into phonie and get back an incorrect phone number:
Phonie::Phone.parse("3932612345", country_code: "39").format("00%c%a%n") => "003932612345"

Phonie as it stands does a full number regex pattern match when it is attempting to parse, which checks for country code, area code and the number.

Full Number Match
Regexp.new("^[+]?(#{country_code})(#{area_code})(#{local_number_format})$")

The issue is 393 is the area code which contains the same numbers as the country code of 39.
326 is also a valid area code, phonie thinks this number is alright since it's still valid regex.

What I had proposed on doing was rewriting the parse function of parser class to read the area code first if the country code was present.

An issue with this became present in the cn_test.rb spec however as the country code was both present in the phone number and within the country_code variable.

https://github.com/wmoxam/phonie/blob/master/lib/phonie/parser.rb#L39
What I wanted to do:

def parse(number, default_area_code = nil)
  parsed_number = parse_area_code_match(number) if country_code.present?
  parsed_number ||= parse_full_match(number)
  parsed_number ||= parse_with_default(number, default_area_code)
  parsed_number ||= {}
end

Any help on this would be appreciated!

Rubocop -a the project

Should be done first, there's no logic change but lots of stupid git conflicts might happen.

import LibPhoneNumber Metadata database?

Just came across Google's libphonenumber project and I'm wondering if there are benefits in converting and importing their database to fill in the gaps Phonie has.

There's a whole library for Ruby here but I suppose that's a full blown alternative to Phonie, the database however would be awesome to have.

Have you considered this before?

Can you add support for a redundant 0 between the country code and area code

It is very popular to have an area code of the format 0XX, but when you want to use the country code yy it should turn yyxx and not yy0xx. In my app a lot of time I get numbers formatted as yy0xx, thats a user's mistake of course but it can be easily parsed without the 0. Is there a chance you can add support for this type of numbers?

Add a negation method to is_mobile?

It's a good practice to have a negation method like #any? to #empty?

Also, remove is_ , as it's said a bad practice by ruby spec/rubocop.

It could be landline? fixed?

Allow an initializer to take in extra area codes

Hello! Great little library here. I'm wondering if you'd be open to a change that allowed additional area codes to be injected into the gem? That way we wouldn't be dependent on you updating them.

Wdyt?

Data Split & Organize & Memoize

Up to discussion, but if each country code had it N.yml file?
It may get loaded in a JIT fashion, so country would load to memory only codes used.
And on each yml you could add comments that would really help figuring out the regexes.

How it would look for 55, Brazil:

# This file should be named 55.yml
# Local numbers start with 2 up to 9.
# Tool free start with 800
55:
  iso_code: BR
  national_dialing_prefix: '0'
  international_dialing_prefix: '00'
  area_code: ((1[1-9]|2[147]|3[1-578]|4[1-9]|5[1-5]|6[1235-9]|7[134579]|8[1-8]|9[12568])|0[3589]00)
  local_number_format: ([1-5]\d{7}|9?[6-9]\d{7}|\d{7})
  mobile_format: ([129][1-9]9|[3-9][1-9])[6-9]\d{7}
  number_format: \d{10,11}

Some popular countries can not be parsed

Hello, Wesley.

The gem becomes useless without popular countries.
The following countries are critical, imho:
Andorra, Monaco, Isle of Man, Kazakhstan, Moldova, Macedonia, Venezuela, Tajikistan, Uzbekistan.

Do you plan to cover them in some future?

Thank you in advance.

Phone numbers with Houston area code 346 fail to parse

Here is an example:

[1] »  Phonie::Phone.parse '346-404-0001'
=> nil
[2] »  Phonie::Phone.parse '713-404-0001'
=> #<Phonie::Phone:0x00007ff4946778a8 @number="4040001", @area_code="713", @country_code="1", @extension=nil, @country=#<Phonie::Country:0x00007ff47cf12868 @name="United States", @country_code="1", @char_2_code="1", @iso_3166_code="US", @parser=#<Phonie::Parser:0x00007ff47cf12610 @area_code="201|202|203|...|341|347|351|352|360|361|364|369|380|385|386|401|402|404|
...
954|956|959|970|971|972|973|974|975|978|979|980|984|985|989)$/>, @national_dialing_prefix="1">, @errors={}>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.