lib/phonie/country.rb in phonie-2.1.2 vs lib/phonie/country.rb in phonie-3.0.0

- old
+ new

@@ -1,115 +1,79 @@ +require 'forwardable' +require 'yaml' + module Phonie - class Country < Struct.new(:name, :country_code, :char_2_code, :iso_3166_code, :area_code, :local_number_format, :mobile_format, :full_number_length, :number_format, :national_dialing_prefix) - def self.load - data_file = File.join(File.dirname(__FILE__), 'data', 'phone_countries.yml') + class Country + extend Forwardable - all = [] - YAML.load(File.read(data_file)).each do |c| - next unless c[:area_code] && c[:local_number_format] - all << Country.new(c[:name], c[:country_code], c[:char_2_code], c[:iso_3166_code], c[:area_code], c[:local_number_format], c[:mobile_format], c[:full_number_length], c[:number_format], c[:national_dialing_prefix]) + attr_reader :name, :country_code, :char_2_code, :iso_3166_code, :parser + + def initialize(params) + @name = params[:name] + @country_code = params[:country_code] + @char_2_code = params[:char_2_code] + @iso_3166_code = params[:iso_3166_code] + @parser = Phonie::Parser.new(params) + @national_dialing_prefix = params[:national_dialing_prefix] + end + + def_delegators :parser, :is_mobile?, :possible_valid_number?, + :is_valid_number?, :parse + + def self.all + @@all ||= begin + YAML.load_file(Phonie.configuration.data_file_path).collect do |country_params| + Country.new(country_params) + end.select {|country| country.valid? } end - all end - COUNTRIES = self.load - COUNTRIES_BY_PHONE_CODE = COUNTRIES.inject(Hash.new){|h, c| (h[c.country_code] ||= []) << c; h } - COUNTRIES_BY_COUNTRY_CODE = Hash[*COUNTRIES.map{|c| [c.iso_3166_code.downcase, c] }.flatten] - COUNTRIES_BY_NAME = Hash[*COUNTRIES.map{|c| [c.name.downcase, c] }.flatten] + def self.all_by_phone_code + @@all_by_phone_code ||= all.inject(Hash.new){|h, c| (h[c.country_code] ||= []) << c; h } + end + def self.all_by_country_code + @@all_by_country_name ||= Hash[*all.map{|c| [c.iso_3166_code.downcase, c] }.flatten] + end + + def self.all_by_name + @@all_by_name ||= Hash[*all.map{|c| [c.name.downcase, c] }.flatten] + end + def self.find_all_by_phone_code(code) - COUNTRIES_BY_PHONE_CODE[code] || [] + all_by_phone_code[code] || [] end def self.find_by_country_code(code) - COUNTRIES_BY_COUNTRY_CODE[code.downcase] if code + all_by_country_code[code.downcase] if code end def self.find_by_name(name) - COUNTRIES_BY_NAME[name.downcase] if name + all_by_name[name.downcase] if name end - # detect country from the string entered - def self.detect(string, default_country_code, default_area_code) + # detect country from the passed phone number + def self.detect(phone_number, default_country_code, default_area_code) # use the default_country_code to try for a quick match - country = find_all_by_phone_code(default_country_code).find do |country| - country.matches_full_number?(string) || - country.matches_local_number_with_area_code?(string) || - country.matches_local_number?(string, default_area_code) + country = find_all_by_phone_code(default_country_code).find do |c| + c.possible_valid_number?(phone_number, default_area_code) end # then search all for a full match - country || COUNTRIES.find {|country| country.matches_full_number?(string) } + country || all.find {|country| country.is_valid_number?(phone_number) } end def to_s name end - def is_mobile?(number) - return true if mobile_format.nil? - number =~ mobile_number_regex ? true : false - end - - # true if string contains country_code + area_code + local_number - def matches_full_number?(string) - string =~ full_number_regex && string =~ number_format_regex - end - - # true if string contains area_code + local_number - def matches_local_number_with_area_code?(string) - string =~ area_code_number_regex && string =~ number_format_regex - end - - # true if string contains only the local_number, but the default_area_code is valid - def matches_local_number?(string, default_area_code) - string =~ number_regex && default_area_code =~ area_code_regex - end - - def parse(number, default_area_code) - if md = number.match(full_number_regex) - {:area_code => md[2], :number => md[-1]} - elsif md = number.match(area_code_number_regex) - {:area_code => md[1], :number => md[-1]} - elsif md = number.match(number_regex) - {:area_code => default_area_code, :number => md[1]} - else - {} - end - end - def national_dialing_prefix - prefix = super - if prefix == "None" - nil - else - prefix - end - end + return nil if @national_dialing_prefix == "None" - private - - def number_format_regex - @number_format_regex ||= Regexp.new("^[+0]?(#{country_code})?(#{number_format})$") + @national_dialing_prefix end - def full_number_regex - @full_number_regex ||= Regexp.new("^[+]?(#{country_code})(#{area_code})(#{local_number_format})$") - end - - def area_code_number_regex - @area_code_number_regex ||= Regexp.new("^0?(#{area_code})(#{local_number_format})$") - end - - def area_code_regex - @area_code_regex ||= Regexp.new("^0?(#{area_code})$") - end - - def mobile_number_regex - @mobile_number_regex ||= Regexp.new("^(#{mobile_format})$") - end - - def number_regex - @number_regex ||= Regexp.new("^(#{local_number_format})$") + def valid? + !!(name && parser.valid?) end end end