daddyz / phonelib

Ruby gem for phone validation and formatting using google libphonenumber library data
MIT License
1.08k stars 131 forks source link

For some numbers after adding custom regex: undefined method 'match' for nil:NilClass (NoMethodError) #324

Open philippgille opened 1 week ago

philippgille commented 1 week ago

Hello πŸ‘‹ , thanks for maintaining phonelib and regularly updating it!

I recently had to add some custom regular expressions to consider some phone numbers as valid which the library didn't consider as valid yet, but then ran into the error undefined method 'match' for nil:NilClass (NoMethodError).

To reproduce, create the following files:

$ tree
.
β”œβ”€β”€ Gemfile
β”œβ”€β”€ app.rb
└── config
    └── initializers
        └── phone_lib.rb

Gemfile:

source 'https://rubygems.org'

gem 'phonelib', '~> 0.9.3'

(Or 0.10.1)

config/initializers/phone_lib.rb:

require 'phonelib'

# Phonelib.additional_regexes = [
#   [:fr, :mobile, '^07\d{8}$'],
#   [:dz, :mobile, '^0(5|6)\d{8}$'],
# ]

app.rb:

require_relative 'config/initializers/phone_lib'

puts "Hello, World!"

phone_number = Phonelib.parse("+33 761234567")
puts "+33 761234567 is valid: #{phone_number.valid?}"

phone_number = Phonelib.parse("+213 551234567")
puts "+213 551234567 is valid: #{phone_number.valid?}"

Then run (in Docker for reproducability independent of locally installed Ruby version):

docker run --rm -v $(pwd):/app -w /app ruby:3.2 bash -c 'bundle install && ruby app.rb'

Which works fine 🟒:

Fetching gem metadata from https://rubygems.org/.
Fetching phonelib 0.9.3
Installing phonelib 0.9.3
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Hello, World!
+33 761234567 is valid: true
+213 551234567 is valid: true

Now comment the added regexes back in and run again. Here it might not be necessary because the numbers are already considered valid, but I just took some anonymous examples. Let's assume they aren't valid and the regexes are required. It leads to an error πŸ”΄ :

Fetching gem metadata from https://rubygems.org/.
Fetching phonelib 0.9.3
Installing phonelib 0.9.3
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Hello, World!
+33 761234567 is valid: true
/usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:216:in `block in number_format': undefined method `match' for nil:NilClass (NoMethodError)

            national.match(cr("^(#{format[Core::LEADING_DIGITS]})"))) && \
                    ^^^^^^
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:214:in `each'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:214:in `find'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:214:in `number_format'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:177:in `national_and_data'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:115:in `parse_single_country'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:133:in `block in detect_and_parse'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:131:in `each'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:131:in `each_with_object'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:131:in `detect_and_parse'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:50:in `analyze_single_country'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone_analyzer.rb:21:in `analyze'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/phone.rb:32:in `initialize'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/core.rb:414:in `new'
    from /usr/local/bundle/gems/phonelib-0.9.3/lib/phonelib/core.rb:414:in `parse'
    from app.rb:8:in `<main>'

The interesting part is that the error only happens for the second number, not the first one.

=> Is there some issue with the combination of the second regex with the second phone number? Or something else?