Permalink
Browse files

+ experimental 1.6.6 release of plausibility checking

  • Loading branch information...
1 parent c957a70 commit 3bbddb84e9a63c2105caf7b9212d1cd4ac1afa5c @floere committed Mar 18, 2012
View
@@ -1,5 +1,9 @@
h2. Upcoming Version.
+h2. Version 1.6.6
+
+* hanke: Experimental @plausible?@ feature. Checks if the given number is a plausible number. Returns @false@ if 100% not plausible, @true@ if probably true.
+
h2. Version 1.6.5
* hanke: Ghana (thanks jschwertfeger!).
View
@@ -12,6 +12,8 @@
require File.expand_path '../phony/national_code', __FILE__
require File.expand_path '../phony/country', __FILE__
require File.expand_path '../phony/country_codes', __FILE__
+require File.expand_path '../phony/validator', __FILE__
+require File.expand_path '../phony/validators', __FILE__
require File.expand_path '../phony/dsl', __FILE__
# Countries.
@@ -37,7 +39,8 @@ module Phony
# Phony uses a single country codes instance.
#
- @codes = CountryCodes.instance
+ @codes = CountryCodes.instance
+ @validator = Validators.instance
class << self
@@ -74,6 +77,16 @@ def format! phone_number, options = {}
end
alias formatted format
alias formatted! format!
+
+ # Makes a plausibility check.
+ #
+ # If it returns false, it is not plausible.
+ # If it returns true, it is unclear whether it is plausible,
+ # leaning towards being plausible.
+ #
+ def plausible? number, hints = {}
+ @validator.plausible? number, hints
+ end
# def service? number
# @codes.service? number.dup
@@ -27,7 +27,9 @@
# USA, Canada, etc.
#
- country '1', fixed(3) >> split(3,4)
+ country '1',
+ fixed(3) >> split(3,4),
+ invalid_ndcs(/911/)
# Kazakhstan (Republic of) & Russian Federation.
#
@@ -6,7 +6,7 @@ module Phony
#
class CountryCodes
- attr_reader :mapping
+ attr_reader :splitter_mapping
attr_accessor :international_absolute_format, :international_relative_format, :national_format
def initialize
@@ -22,11 +22,14 @@ def self.instance
@instance ||= new
end
- @@normalizing_pattern = /^0+|\D/
- def normalize number
+ @@basic_normalizing_pattern = /^0+|\D/
+ def clean number
# Remove non-digit chars.
#
- number.gsub! @@normalizing_pattern, EMPTY_STRING
+ number.gsub! @@basic_normalizing_pattern, EMPTY_STRING
+ end
+ def normalize number
+ clean number
national_handler, cc, rest = split_cc number
@normalize_format % [cc, national_handler.normalize(rest)]
end
@@ -102,7 +105,7 @@ def split_cc rest
presumed_cc = ''
1.upto(3) do |i|
presumed_cc << rest.slice!(0..0)
- national_code_handler = mapping[i][presumed_cc]
+ national_code_handler = splitter_mapping[i][presumed_cc]
return [national_code_handler, presumed_cc, rest] if national_code_handler
end
# This line is never reached as CCs are in prefix code.
@@ -121,9 +124,9 @@ def add country_code, country
country_code = country_code.to_s
optimized_country_code_access = country_code.size
- @mapping ||= {}
- @mapping[optimized_country_code_access] ||= {}
- @mapping[optimized_country_code_access][country_code] = country
+ @splitter_mapping ||= {}
+ @splitter_mapping[optimized_country_code_access] ||= {}
+ @splitter_mapping[optimized_country_code_access][country_code] = country
end
end
View
@@ -46,8 +46,9 @@ class DSL
#
#
- def country country_code, country
+ def country country_code, country, validator = nil
Phony::CountryCodes.instance.add country_code, country
+ Phony::Validators.instance.add country_code, validator if validator
end
# National matcher & splitters.
@@ -89,6 +90,12 @@ def split *local
def matched_split options = {}
Phony::LocalSplitters::Regex.instance_for options
end
+
+ # Validators
+ #
+ def invalid_ndcs ndc
+ Validator.new.ndc_check ndc
+ end
end
@@ -1,62 +1,24 @@
-# # Number: A possible phone number, E164 or not.
-# # Hints: Information that helps or constricts the plausibility check.
-# #
-# plausible? number, hints = {}
-#
-
-# plausible? number # Uses the definitions from the country definition to plausibility check.
-# plausible? number, cc: 1 # => Checks cc.
-# plausible? number, pattern: /[^5]/ # Uses def, checks against split.
-# plausible? number, country: 1, pattern: [3, 4, 3] # Uses given country – adds cc.
-#
-
-# Basic plausibility is:
-# * Max digits are 15.
-# * Min digits are 2 (?)
-#
-
module Phony
class Validator
-
- # TODO Beautify.
- #
- def plausible? number, hints = {}
- normalized = normalize number
-
- # False if it fails the basic check.
- #
- return false unless normalized.size === (2..15)
-
- # Hint based checking.
- #
- cc, ndc, *rest = split normalized
-
- # CC.
- #
- cc_needed = hints[:cc]
- return false if cc_needed && cc_needed != cc
-
- # NDC.
- #
- ndc_needed = hints[:ndc]
- return false if ndc_needed && ndc_needed != ndc
-
- # Country specific checks?
- #
-
- # Get the country.
- #
-
- # Check.
- #
+
+ attr_reader :ndc_checks
+
+ def initialize
+ @ndc_checks = []
+ end
+
+ def plausible? ndc, rest
+ ndc_checks && ndc_checks.each do |ndc_check|
+ return false if ndc_check === ndc
+ end
- rescue StandardError
- return false
+ true
end
-
- def normalize number
- number
+
+ def ndc_check ndc
+ @ndc_checks << ndc
+ self
end
end
@@ -0,0 +1,77 @@
+# # Number: A possible phone number, E164 or not.
+# # Hints: Information that helps or constricts the plausibility check.
+# #
+# plausible? number, hints = {}
+#
+
+# plausible? number # Uses the definitions from the country definition to plausibility check.
+# plausible? number, cc: 1 # => Checks cc.
+# plausible? number, pattern: /[^5]/ # Uses def, checks against split.
+# plausible? number, country: 1, pattern: [3, 4, 3] # Uses given country – adds cc.
+#
+
+# Basic plausibility is:
+# * Max digits are 15.
+# * Min digits are 2 (?)
+#
+
+module Phony
+
+ class Validators
+
+ def initialize
+ @validators = {}
+ end
+
+ def self.instance
+ @instance ||= new
+ end
+
+ # Add a specific country validator.
+ #
+ def add cc, validator
+ @validators[cc] = validator
+ end
+
+ # Is the given number plausible?
+ #
+ def plausible? number, hints = {}
+ normalized = CountryCodes.instance.clean number
+
+ # False if it fails the basic check.
+ #
+ return false unless (2..15) === normalized.size
+
+ # Hint based checking.
+ #
+ cc, ndc, *rest = Phony.split normalized
+
+ # CC.
+ #
+ cc_needed = hints[:cc]
+ return false if cc_needed && cc_needed != cc
+
+ # NDC.
+ #
+ ndc_needed = hints[:ndc]
+ return false if ndc_needed && ndc_needed != ndc
+
+ # Country specific checks.
+ #
+ validator = validator_for cc
+ validator.plausible? ndc, rest
+ rescue StandardError
+ return false
+ end
+
+ def validator_for cc
+ @validators[cc] || default_validator
+ end
+
+ def default_validator
+ @default_validator ||= Validator.new
+ end
+
+ end
+
+end
View
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'phony'
- s.version = '1.6.5'
+ s.version = '1.6.6'
s.authors = ['Florian Hanke']
s.email = 'florian.hanke+phony@gmail.com'
s.homepage = 'http://github.com/floere/phony'
@@ -0,0 +1,43 @@
+# encoding: utf-8
+#
+require 'spec_helper'
+
+describe 'validations' do
+
+ describe 'plausible?' do
+
+ it "is correct" do
+ Phony.plausible?('0000000').should be_false
+ end
+ it "is correct" do
+ Phony.plausible?('hello').should be_false
+ end
+
+ it "is correct" do
+ Phony.plausible?('+41 44 111 22 33').should be_true
+ end
+ it "is correct for explicit checks" do
+ Phony.plausible?('+41 44 111 22 33', cc: '41').should be_true
+ end
+ it "is correct for explicit checks" do
+ Phony.plausible?('+41 44 111 22 33', ndc: '44').should be_true
+ end
+ it "is correct for explicit checks" do
+ Phony.plausible?('+41 44 111 22 33', cc: '1').should be_false
+ end
+ it "is correct for explicit checks" do
+ Phony.plausible?('+41 44 111 22 33', ndc: '43').should be_false
+ end
+
+ context 'countries' do
+
+ it "is correct for US numbers" do
+ Phony.plausible?('1-800-692-7753').should be_true
+ Phony.plausible?('1-911').should be_false
+ end
+
+ end
+
+ end
+
+end
@@ -57,9 +57,6 @@
it "should not normalize a number with a correct zero inside" do
Phony.normalize('+390909709511').should == '390909709511'
end
- it "works with completely broken numbers" do
- Phony.normalize('0000000').should == ''
- end
end
end

0 comments on commit 3bbddb8

Please sign in to comment.