Module: PhonyRails

Defined in:
lib/phony_rails.rb,
lib/phony_rails/version.rb

Defined Under Namespace

Modules: Extension

Constant Summary collapse

COMMON_EXTENSIONS =
/[ ]*(ext|ex|x|xt|#|:)+[^0-9]*\(?([-0-9]{1,})\)?#?$/i.freeze
VERSION =
'0.14.13'

Class Method Summary collapse

Class Method Details

.country_code_from_number(number) ⇒ Object

Returns the country dail code (eg. ‘31’) for a number (eg. +31612341234). Should probably be named ‘country_number_from_number’.



102
103
104
105
106
# File 'lib/phony_rails.rb', line 102

def self.country_code_from_number(number)
  return nil unless Phony.plausible?(number)

  Phony.split(Phony.normalize(number)).first
end

.country_codes_hashObject



33
34
35
# File 'lib/phony_rails.rb', line 33

def self.country_codes_hash
  @country_codes_hash ||= YAML.load_file(File.join(File.dirname(File.expand_path(__FILE__)), 'data/country_codes.yaml'))
end

.country_from_number(number) ⇒ Object

Returns the country (eg. ‘NL’) for a number (eg. +31612341234).



109
110
111
112
113
# File 'lib/phony_rails.rb', line 109

def self.country_from_number(number)
  return nil unless Phony.plausible?(number)

  country_codes_hash.select { |_country, hash| hash['country_code'] == country_code_from_number(number) }.keys[0]
end

.country_number_for(country_code) ⇒ Object



27
28
29
30
31
# File 'lib/phony_rails.rb', line 27

def self.country_number_for(country_code)
  return if country_code.nil?

  country_codes_hash.fetch(country_code.to_s.upcase, {})['country_code']
end

.default_country_codeObject



10
11
12
# File 'lib/phony_rails.rb', line 10

def self.default_country_code
  @default_country_code ||= nil
end

.default_country_code=(new_code) ⇒ Object



14
15
16
17
# File 'lib/phony_rails.rb', line 14

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

.default_country_numberObject



19
20
21
# File 'lib/phony_rails.rb', line 19

def self.default_country_number
  @default_country_number ||= default_country_code.present? ? country_number_for(default_country_code) : nil
end

.default_country_number=(new_number) ⇒ Object



23
24
25
# File 'lib/phony_rails.rb', line 23

def self.default_country_number=(new_number)
  @default_country_number = new_number
end

.extract_default_country_number(options = {}, current_instance = nil) ⇒ Object



91
92
93
94
95
96
97
98
# File 'lib/phony_rails.rb', line 91

def self.extract_default_country_number(options = {}, current_instance = nil)
  country_code = if current_instance.present? && options[:default_country_code].respond_to?(:call)
                   options[:default_country_code].call(current_instance) rescue nil
                 else
                   options[:default_country_code]
                 end
  options[:default_country_number] || country_number_for(country_code) || default_country_number
end

.extract_extension(number_and_ext) ⇒ Object



134
135
136
137
138
139
# File 'lib/phony_rails.rb', line 134

def self.extract_extension(number_and_ext)
  return [nil, nil] if number_and_ext.nil?

  subbed = number_and_ext.sub(COMMON_EXTENSIONS, '')
  [subbed, Regexp.last_match(2)]
end

.format_extension(number, ext) ⇒ Object



141
142
143
# File 'lib/phony_rails.rb', line 141

def self.format_extension(number, ext)
  ext.present? ? "#{number} x#{ext}" : number
end

.normalize_number(number, options = {}, current_instance = nil) ⇒ Object

This method requires a country_code attribute (eg. NL) and phone_number to be set. Options:

:country_number => The country dial code (eg. 31 for NL).
:default_country_number => Fallback country code.
:country_code => The country code we should use.
:default_country_code => Some fallback code (eg. 'NL') that can be used as default (comes from phony_normalize_numbers method).
:add_plus => Add a '+' in front so we know the country code is added. (default: true)
:extension => Include the extension. (default: true)

This idea came from:

http://www.redguava.com.au/2011/06/rails-convert-phone-numbers-to-international-format-for-sms/


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/phony_rails.rb', line 47

def self.normalize_number(number, options = {}, current_instance = nil)
  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
    number = "#{_country_number}#{number}" if !Phony.plausible?(number) || _country_number != country_code_from_number(number)
  elsif _default_country_number = extract_default_country_number(options, current_instance)
    options[:add_plus] = true if options[:add_plus].nil?
    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)
  normalized_number = options[:add_plus] ? "+#{normalized_number}" : normalized_number

  options[:extension] = true if options[:extension].nil?
  normalized_number = options[:extension] ? format_extension(normalized_number, ext) : normalized_number
  normalized_number
rescue StandardError
  original_number # If all goes wrong .. we still return the original input.
end

.normalize_number_default_country(number, default_country_number) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/phony_rails.rb', line 76

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\(?(\+|00)/ # if we don't have a + or 00
    return "#{default_country_number}#{number}" if Phony.plausible?("#{default_country_number}#{number}") || !Phony.plausible?(number) || country_code_from_number(number).nil?
    # 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/, '')}" if (number =~ /^0[^0]/) && Phony.plausible?("#{default_country_number}#{number.gsub(/^0/, '')}")
  end
  # number = "#{default_country_number}#{number}" unless Phony.plausible?(number)
  # Just return the number unchanged
  number
end

.plausible_number?(number, options = {}) ⇒ Boolean

Wrapper for Phony.plausible?. Takes the same options as #normalize_number. NB: This method calls #normalize_number and passes options directly to that method. It uses the ‘cc’ option for Phony. This was a required param before?

Returns:

  • (Boolean)


118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/phony_rails.rb', line 118

def self.plausible_number?(number, options = {})
  return false if number.blank?

  number = extract_extension(number).first
  number = normalize_number(number, options)
  country_number = options[:country_number] || country_number_for(options[:country_code]) ||
                   country_code_from_number(number) ||
                   options[:default_country_number] || country_number_for(options[:default_country_code]) ||
                   default_country_number
  Phony.plausible? number, cc: country_number
rescue StandardError
  false
end