Skip to content
This repository has been archived by the owner on Jun 10, 2018. It is now read-only.

Find a territory by country code #41

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/global_phone/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ def parse(string, territory_name = default_territory_name)
db.parse(string, territory_name)
end

def territory_for_country_code(string)
region = db.region_for_country_code(string)
return unless region
region.territory_for_contry_code
end

def normalize(string, territory_name = default_territory_name)
number = parse(string, territory_name)
number.international_string if number
Expand Down
70 changes: 60 additions & 10 deletions lib/global_phone/database.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
require 'global_phone/parsing'
require 'json'
require 'global_phone/region'

module GlobalPhone
class Database
include Parsing
attr_reader :regions

def self.load_file(filename)
load(File.read(filename))
end

def self.load(json)
require 'json'
new(JSON.parse(json))
end

attr_reader :regions

def initialize(record_data)
@regions = record_data.map { |data| Region.new(data) }
@territories_by_name = {}
end

def parse(string, territory_name)
string = Number.normalize(string)
territory = self.territory(territory_name)
raise ArgumentError, "unknown territory `#{territory_name}'" unless territory

if starts_with_plus?(string)
parse_international_string(string)
elsif string =~ territory.international_prefix
string = strip_international_prefix(territory, string)
parse_international_string(string)
else
territory.parse_national_string(string)
end
end

def region(country_code)
regions_by_country_code[country_code.to_s]
end
Expand All @@ -36,13 +48,51 @@ def inspect
"#<#{self.class.name}>"
end

protected
def regions_by_country_code
@regions_by_country_code ||= Hash[*regions.map { |r| [r.country_code, r] }.flatten]
def region_for_country_code(string)
country_code_candidates_for(strip_leading_plus(string)).each do |country_code|
if found_region = region(country_code)
return found_region
end
end
nil
end

private

def parse_international_string(string)
string = strip_leading_plus(Number.normalize(string))

if region = region_for_country_code(string)
region.parse_national_string(string)
end
end

def starts_with_plus?(string)
string[0, 1] == "+"
end

def region_for_territory(name)
regions.find { |r| r.has_territory?(name) }
def strip_leading_plus(string)
if starts_with_plus?(string)
string[1..-1]
else
string
end
end

def strip_international_prefix(territory, string)
string.sub(territory.international_prefix, "")
end

def country_code_candidates_for(string)
(1..3).map { |length| string[0, length] }
end

def regions_by_country_code
@regions_by_country_code ||= Hash[*regions.map { |r| [r.country_code, r] }.flatten]
end

def region_for_territory(name)
regions.find { |r| r.has_territory?(name) }
end
end
end
2 changes: 1 addition & 1 deletion lib/global_phone/database_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def inspect
"#<#{self.class.name} (#{doc.search("*").size} elements)>"
end

protected
private
def territory_nodes
doc.search("territory")
end
Expand Down
2 changes: 1 addition & 1 deletion lib/global_phone/number.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def to_s
international_string
end

protected
private
def format
@format ||= find_format_for(national_string)
end
Expand Down
52 changes: 0 additions & 52 deletions lib/global_phone/parsing.rb

This file was deleted.

9 changes: 6 additions & 3 deletions lib/global_phone/region.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
require 'global_phone/format'
require 'global_phone/record'
require 'global_phone/territory'
require 'global_phone/utils'

module GlobalPhone
class Region < Record
Expand All @@ -23,7 +22,7 @@ def territories

def territory(name)
name = name.to_s.upcase
territories.detect { |region| region.name == name }
territories.detect { |territory| territory.name == name }
end

def has_territory?(name)
Expand All @@ -38,11 +37,15 @@ def parse_national_string(string)
end
end

def territory_for_contry_code
territories.first
end

def inspect
"#<#{self.class.name} country_code=#{country_code} territories=[#{territory_names.join(",")}]>"
end

protected
private
def territory_names
territory_record_data.map(&:first)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/global_phone/territory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def inspect
"#<#{self.class.name} country_code=#{country_code} name=#{name}>"
end

protected
private
def strip_prefixes(string)
if national_prefix_for_parsing
transform_rule = national_prefix_transform_rule || ""
Expand Down
14 changes: 0 additions & 14 deletions lib/global_phone/utils.rb

This file was deleted.

24 changes: 23 additions & 1 deletion test/context_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,33 @@ class ContextTest < TestCase
assert_nil context.validate("+0651816068")
end

test 'finding region by string' do
assert_found_territory_for_country_code('1', {country_code: '1', country_name: 'US'})
assert_found_territory_for_country_code('+1', {country_code: '1', country_name: 'US'})
assert_found_territory_for_country_code('131', {country_code: '1', country_name: 'US'})
assert_found_territory_for_country_code('+375', {country_code: '375', country_name: 'BY'})

assert_not_found_territory_for_country_code('+9')
end

def assert_parses(string, assertions)
territory_name = assertions.delete(:with_territory) || context.default_territory_name
number = context.parse(string, territory_name)
assert_kind_of Number, number
assert_equal({ :country_code => number.country_code, :national_string => number.national_string }, assertions)
assert_equal(assertions,
{ :country_code => number.country_code, :national_string => number.national_string })
end

def assert_found_territory_for_country_code(string, assertions)
territory = context.territory_for_country_code(string)

assert_equal(assertions, {country_code: territory.country_code, country_name: territory.name})
end

def assert_not_found_territory_for_country_code(string)
territory = context.territory_for_country_code(string)

assert_nil territory
end

def assert_does_not_parse(string, options = {})
Expand Down