phonelib 0.7.4 → 0.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3d4b5fdc2ce47146fc219685f85a1a275894a236741d615dd22d62a4a5e690d
4
- data.tar.gz: 127a169f1a25adc3885e90318d1893bd6939eb9fb43c6e2131d709e7b08c8869
3
+ metadata.gz: ead15db333d3f8490017aef9004751e4944ba84689238cb2c2579cde56c3b751
4
+ data.tar.gz: ac6ff256e13409683825f984fb400e1eb85d6dfbfaec90dc10f163414d69eb8a
5
5
  SHA512:
6
- metadata.gz: 4501c256fa95121131857d8a091ddd09deea7a5ab71fe1aaf01816ebb7911d088a95ac1229235365588b735dadc6d19a317fef2fa400c45090d52796b349e78a
7
- data.tar.gz: 9d703e8b8448ce2c9a5755057132a7c9aec769a400fb5ffab055b5b9a94ad8eab296f795defd6cac1352ecb85df5279b5eddf45f341948df140f2863d8c945f9
6
+ metadata.gz: 3e49e7edbe4835d24c76f393aa2a21f9bfd0cf2876536f4106e39def0bd3806b2099fc45a9a2fa8b71a8ecf6a47404c2938a26881fcd153548be396bac9977c5
7
+ data.tar.gz: 237714d47010cbb5258944d0cdadfb55f7df6d8facbf6fe0c13651b0f759ea8fd6cb3737d9e52a5c1244b0270616150214e580675148a73fa7c44494c42c1eed
Binary file
data/data/phone_data.dat CHANGED
Binary file
data/lib/phonelib/core.rb CHANGED
@@ -4,12 +4,35 @@ module Phonelib
4
4
  # @private variable will include hash with data for validation
5
5
  @@phone_data = nil
6
6
 
7
+ # eagerly initialize the gem, loads data into memory. not required, initialization is done lazily otherwise, but
8
+ # may be desirable in production enviroments to avoid initialization time on first use.
9
+ def eager_load!
10
+ return if @@skip_eager_loading
11
+ phone_data
12
+ phone_ext_data
13
+ end
14
+
15
+ @@skip_eager_loading = false
16
+ def skip_eager_loading!
17
+ @@skip_eager_loading = true
18
+ end
19
+
7
20
  # getter for phone data for other modules of gem, can be used outside
8
21
  # @return [Hash] all data for phone parsing
9
22
  def phone_data
10
23
  @@phone_data ||= load_data.freeze
11
24
  end
12
25
 
26
+ # @private getter for phone data indexed by country code (internal use only)
27
+ def data_by_country_codes
28
+ @@data_by_country_codes ||= phone_data.each_value.group_by { |d| d[COUNTRY_CODE] }.freeze
29
+ end
30
+
31
+ # @private getter for all international prefixes in phone_data
32
+ def phone_data_int_prefixes
33
+ @@all_int_prefixes ||= phone_data.map {|k,v| v[:international_prefix] }.select { |v| v != '' }.compact.uniq.join('|').freeze
34
+ end
35
+
13
36
  # @private used to cache frequently-used regular expressions
14
37
  @@phone_regexp_cache = {}
15
38
 
@@ -30,14 +53,14 @@ module Phonelib
30
53
  @@default_country = nil
31
54
 
32
55
  # getter method for default_country variable
33
- # @return [String|nil] Default country set for parsing or nil
56
+ # @return [String,Symbol,Array<String,Symbol>,nil] Default country ISO2 code or codes used for parsing
34
57
  def default_country
35
58
  @@default_country
36
59
  end
37
60
 
38
61
  # setter method for default_country variable
39
- # @param country [String|Symbol] default country ISO2 code used for parsing
40
- # @return [String|nil] Default country set for parsing or nil
62
+ # @param country [String,Symbol,Array<String,Symbol>] Default country ISO2 code or codes used for parsing
63
+ # @return [String,Symbol,Array<String,Symbol>] Default country ISO2 code or codes used for parsing
41
64
  def default_country=(country)
42
65
  @@default_country = country
43
66
  end
@@ -179,7 +202,7 @@ module Phonelib
179
202
  def add_additional_regex(country, type, national_regex)
180
203
  return unless Phonelib::Core::TYPES_DESC.keys.include?(type.to_sym)
181
204
  return unless national_regex.is_a?(String)
182
- @@phone_data = nil
205
+ @@phone_data = @@data_by_country_codes = nil
183
206
  @@additional_regexes[country.to_s.upcase] ||= {}
184
207
  @@additional_regexes[country.to_s.upcase][type] ||= []
185
208
  @@additional_regexes[country.to_s.upcase][type] << national_regex
@@ -45,6 +45,7 @@ module Phonelib
45
45
  'TA' => 'SH',
46
46
  'TC' => 'US',
47
47
  'TT' => 'US',
48
+ 'UM' => 'US',
48
49
  'VA' => 'IT',
49
50
  'VC' => 'US',
50
51
  'VG' => 'US',
@@ -160,6 +161,7 @@ module Phonelib
160
161
  # some countries missing formats, and are linking them to another countries
161
162
  def process_format_links
162
163
  FORMAT_SHARING.each do |destination, source|
164
+ next unless @data[destination]
163
165
  @data[destination][:formats] ||= []
164
166
  @data[destination][:formats] = @data[destination][:formats] + @data[source][:formats]
165
167
  end
@@ -195,7 +197,7 @@ module Phonelib
195
197
 
196
198
  require 'open-uri'
197
199
  require 'csv'
198
- io = open('http://api.geonames.org/countryInfoCSV?username=demo&style=full')
200
+ io = URI.open('http://download.geonames.org/export/dump/countryInfo.txt')
199
201
  csv = CSV.new(io, {col_sep: "\t"})
200
202
  csv.each do |row|
201
203
  next if row[0].nil? || row[0].start_with?('#') || row[0].empty? || row[0].size != 2
@@ -178,6 +178,8 @@ module Phonelib
178
178
 
179
179
  # @private extracts extension from passed phone number if provided
180
180
  def separate_extension(original)
181
+ return [original, ''] unless Phonelib.extension_separate_symbols
182
+
181
183
  regex = if Phonelib.extension_separate_symbols.is_a?(Array)
182
184
  cr("#{Phonelib.extension_separate_symbols.join('|')}")
183
185
  else
@@ -124,15 +124,22 @@ module Phonelib
124
124
  #
125
125
  # * +phone+ - phone number for parsing
126
126
  def detect_and_parse(phone, country)
127
- result = {}
128
- Phonelib.phone_data.each do |key, data|
127
+ countries_data = country_code_candidates_for(phone).flat_map { |code|
128
+ Phonelib.data_by_country_codes[code] || []
129
+ }
130
+ countries_data.each_with_object({}) do |data, result|
131
+ key = data[:id]
129
132
  parsed = parse_single_country(phone, data)
130
133
  if (!Phonelib.strict_double_prefix_check || key == country) && double_prefix_allowed?(data, phone, parsed && parsed[key])
131
134
  parsed = parse_single_country(changed_dp_phone(key, phone), data)
132
135
  end
133
136
  result.merge!(parsed) unless parsed.nil?
134
- end
135
- result
137
+ end.compact
138
+ end
139
+
140
+ def country_code_candidates_for(phone)
141
+ stripped_phone = phone.gsub(/^(#{Phonelib.phone_data_int_prefixes})/, '')
142
+ ((1..3).map { |length| phone[0, length] } + (1..3).map { |length| stripped_phone[0, length] }).uniq
136
143
  end
137
144
 
138
145
  # Create phone representation in e164 format
@@ -7,6 +7,8 @@ module Phonelib
7
7
  if result.size == 1
8
8
  result
9
9
  else
10
+ matched_countries = country_or_default_country(nil) & result.keys
11
+ result = result.keep_if {|k, _v| matched_countries.include?(k) } if matched_countries
10
12
  Hash[result.take(1)]
11
13
  end
12
14
  end
@@ -56,7 +58,7 @@ module Phonelib
56
58
  def country_can_dp?(country)
57
59
  Phonelib.phone_data[country] &&
58
60
  Phonelib.phone_data[country][Core::DOUBLE_COUNTRY_PREFIX_FLAG] &&
59
- !original_starts_with_plus?
61
+ !original_starts_with_plus? && original_s.start_with?(Phonelib.phone_data[country][Core::COUNTRY_CODE])
60
62
  end
61
63
 
62
64
  # changes phone to with/without double country prefix
@@ -66,6 +68,7 @@ module Phonelib
66
68
 
67
69
  country_code = Phonelib.phone_data[country][Core::COUNTRY_CODE]
68
70
  if phone.start_with? country_code * 2
71
+ # remove double prefix in case it is there
69
72
  phone.gsub(cr("^#{country_code}"), '')
70
73
  else
71
74
  "#{country_code}#{phone}"
@@ -5,7 +5,7 @@ module Phonelib
5
5
  # @param formatted [Boolean] whether to return numbers only or formatted
6
6
  # @return [String] formatted national number
7
7
  def national(formatted = true)
8
- return @national_number unless valid?
8
+ return @national_number unless possible?
9
9
  format_match, format_string = formatting_data
10
10
 
11
11
  if format_match
@@ -52,7 +52,7 @@ module Phonelib
52
52
  def international(formatted = true, prefix = '+')
53
53
  prefix = formatted if formatted.is_a?(String)
54
54
  return nil if sanitized.empty?
55
- return "#{prefix}#{country_prefix_or_not}#{sanitized}" unless valid?
55
+ return "#{prefix}#{country_prefix_or_not}#{sanitized}" unless possible?
56
56
  return "#{prefix}#{data_country_code}#{@national_number}" unless formatted
57
57
 
58
58
  fmt = @data[country][:format]
@@ -1,4 +1,4 @@
1
1
  module Phonelib
2
2
  # @private
3
- VERSION = '0.7.4'
3
+ VERSION = '0.8.7'
4
4
  end
data/lib/phonelib.rb CHANGED
@@ -17,4 +17,12 @@ if defined?(ActiveModel) || defined?(Rails)
17
17
  else
18
18
  autoload :PhoneValidator, 'validators/phone_validator'
19
19
  end
20
+
21
+ if defined?(Rails)
22
+ class Phonelib::Railtie < Rails::Railtie
23
+ initializer 'phonelib' do |app|
24
+ app.config.eager_load_namespaces << Phonelib
25
+ end
26
+ end
27
+ end
20
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phonelib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
4
+ version: 0.8.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vadim Senderovich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-19 00:00:00.000000000 Z
11
+ date: 2024-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.13.0
33
+ version: '1.15'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.13.0
40
+ version: '1.15'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.0.0
75
+ version: 1.0.9
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 1.0.0
82
+ version: 1.0.9
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: benchmark-ips
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: benchmark-memory
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: rack-cache
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -169,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
197
  - !ruby/object:Gem::Version
170
198
  version: '0'
171
199
  requirements: []
172
- rubygems_version: 3.0.8
200
+ rubygems_version: 3.1.4
173
201
  signing_key:
174
202
  specification_version: 4
175
203
  summary: Gem validates phone numbers with Google libphonenumber database