lib/phony_rails.rb in phony_rails-0.13.1 vs lib/phony_rails.rb in phony_rails-0.14.0
- old
+ new
@@ -3,10 +3,27 @@
require 'validators/phony_validator'
require 'phony_rails/version'
require 'yaml'
module PhonyRails
+ def self.default_country_code
+ @default_country_code ||= nil
+ end
+
+ def self.default_country_code=(new_code)
+ @default_country_code = new_code
+ @default_country_number = nil # Reset default country number, will lookup next time its asked for
+ end
+
+ def self.default_country_number
+ @default_country_number ||= default_country_code.present? ? country_number_for(default_country_code) : nil
+ end
+
+ def self.default_country_number=(new_number)
+ @default_country_number = new_number
+ end
+
def self.country_number_for(country_code)
return if country_code.nil?
country_codes_hash.fetch(country_code.to_s.upcase, {})['country_code']
end
@@ -26,69 +43,101 @@
# http://www.redguava.com.au/2011/06/rails-convert-phone-numbers-to-international-format-for-sms/
def self.normalize_number(number, options = {})
return if number.nil?
original_number = number
number = number.dup # Just to be sure, we don't want to change the original.
+ number, ext = extract_extension(number)
number.gsub!(/[^\(\)\d\+]/, '') # Strips weird stuff from the number
return if number.blank?
if _country_number = options[:country_number] || country_number_for(options[:country_code])
options[:add_plus] = true if options[:add_plus].nil?
# (Force) add country_number if missing
# NOTE: do we need to force adding country code? Otherwise we can share logic with next block
if !Phony.plausible?(number) || _country_number != country_code_from_number(number)
number = "#{_country_number}#{number}"
end
- elsif _default_country_number = options[:default_country_number] || country_number_for(options[:default_country_code])
+ elsif _default_country_number = extract_default_country_number(options)
options[:add_plus] = true if options[:add_plus].nil?
- # We try to add the default country number and see if it is a
- # correct phone number. See https://github.com/joost/phony_rails/issues/87#issuecomment-89324426
- unless number =~ /\A\+/ # if we don't have a +
- if Phony.plausible?("#{_default_country_number}#{number}") || !Phony.plausible?(number) || country_code_from_number(number).nil?
- number = "#{_default_country_number}#{number}"
- elsif (number =~ /^0[^0]/) && Phony.plausible?("#{_default_country_number}#{number.gsub(/^0/, '')}")
- # If the number starts with ONE zero (two might indicate a country code)
- # and this is a plausible number for the default_country
- # we prefer that one.
- number = "#{_default_country_number}#{number.gsub(/^0/, '')}"
- end
- end
- # number = "#{_default_country_number}#{number}" unless Phony.plausible?(number)
+ number = normalize_number_default_country(number, _default_country_number)
end
normalized_number = Phony.normalize(number)
options[:add_plus] = true if options[:add_plus].nil? && Phony.plausible?(normalized_number)
- options[:add_plus] ? "+#{normalized_number}" : normalized_number
+ normalized_number = options[:add_plus] ? "+#{normalized_number}" : normalized_number
+ format_extension(normalized_number, ext)
rescue
original_number # If all goes wrong .. we still return the original input.
end
+ def self.normalize_number_default_country(number, default_country_number)
+ # We try to add the default country number and see if it is a
+ # correct phone number. See https://github.com/joost/phony_rails/issues/87#issuecomment-89324426
+ unless number =~ /\A\+/ # if we don't have a +
+ if Phony.plausible?("#{default_country_number}#{number}") || !Phony.plausible?(number) || country_code_from_number(number).nil?
+ return "#{default_country_number}#{number}"
+ elsif (number =~ /^0[^0]/) && Phony.plausible?("#{default_country_number}#{number.gsub(/^0/, '')}")
+ # If the number starts with ONE zero (two might indicate a country code)
+ # and this is a plausible number for the default_country
+ # we prefer that one.
+ return "#{default_country_number}#{number.gsub(/^0/, '')}"
+ end
+ end
+ # number = "#{default_country_number}#{number}" unless Phony.plausible?(number)
+ # Just return the number unchanged
+ number
+ end
+
+ def self.extract_default_country_number(options = {})
+ options[:default_country_number] || country_number_for(options[:default_country_code]) || default_country_number
+ end
+
def self.country_code_from_number(number)
return nil unless Phony.plausible?(number)
Phony.split(Phony.normalize(number)).first
end
# Wrapper for Phony.plausible?. Takes the same options as #normalize_number.
# NB: This method calls #normalize_number and passes _options_ directly to that method.
def self.plausible_number?(number, options = {})
return false if number.nil? || number.blank?
+ number = extract_extension(number).first
number = normalize_number(number, options)
country_number = options[:country_number] || country_number_for(options[:country_code]) ||
- options[:default_country_number] || country_number_for(options[:default_country_code])
+ options[:default_country_number] || country_number_for(options[:default_country_code]) ||
+ default_country_number
Phony.plausible? number, cc: country_number
rescue
false
end
+ COMMON_EXTENSIONS = /[ ]*(ext|ex|x|xt|#|:)+[^0-9]*\(*([-0-9]{1,})\)*#?$/i
+
+ def self.extract_extension(number_and_ext)
+ return [nil, nil] if number_and_ext.nil?
+ # :nocov:
+ if subbed = number_and_ext.sub(COMMON_EXTENSIONS, '')
+ [subbed, Regexp.last_match(2)]
+ else
+ [number_and_ext, nil]
+ end
+ # :nocov:
+ end
+
+ def self.format_extension(number, ext)
+ ext.present? ? "#{number} x#{ext}" : number
+ end
+
module Extension
extend ActiveSupport::Concern
included do
private
# This methods sets the attribute to the normalized version.
# It also adds the country_code (number), eg. 31 for NL numbers.
def set_phony_normalized_numbers(attributes, options = {})
options = options.dup
+ assign_values_for_phony_symbol_options(options)
if respond_to?(:country_code)
set_country_as = options[:enforce_record_country] ? :country_code : :default_country_code
options[set_country_as] ||= country_code
end
attributes.each do |attribute|
@@ -96,10 +145,17 @@
raise("No attribute #{attribute_name} found on #{self.class.name} (PhonyRails)") unless self.class.attribute_method?(attribute_name)
new_value = PhonyRails.normalize_number(send(attribute), options)
send("#{attribute_name}=", new_value) if new_value
end
end
+
+ def assign_values_for_phony_symbol_options(options)
+ symbol_options = [:country_number, :default_country_number, :country_code, :default_country_code]
+ symbol_options.each do |option|
+ options[option] = send(options[option]) if options[option].is_a?(Symbol)
+ end
+ end
end
module ClassMethods
# Use this method on the class level like:
# phony_normalize :phone_number, :fax_number, :default_country_code => 'NL'
@@ -128,13 +184,14 @@
main_options = attributes.last.is_a?(Hash) ? attributes.pop : {}
main_options.assert_valid_keys :country_code, :default_country_code
attributes.each do |attribute|
raise(StandardError, "Instance method normalized_#{attribute} already exists on #{name} (PhonyRails)") if method_defined?(:"normalized_#{attribute}")
define_method :"normalized_#{attribute}" do |*args|
- options = args.first || {}
+ options = main_options.merge(args.first || {})
+ assign_values_for_phony_symbol_options(options)
raise(ArgumentError, "No attribute/method #{attribute} found on #{self.class.name} (PhonyRails)") unless respond_to?(attribute)
options[:country_code] ||= country_code if respond_to?(:country_code)
- PhonyRails.normalize_number(send(attribute), main_options.merge(options))
+ PhonyRails.normalize_number(send(attribute), options)
end
end
end
end
end