Skip to content

Commit

Permalink
Release 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Harrelson committed Dec 25, 2009
1 parent df7a643 commit 270fbda
Show file tree
Hide file tree
Showing 9 changed files with 336 additions and 0 deletions.
30 changes: 30 additions & 0 deletions lib/phone_number/active_record_extensions.rb
@@ -0,0 +1,30 @@
module PhoneNumber::ActiveRecordExtensions
def self.included( base )
base.extend ActsMethods
end

module ActsMethods
def phone_number( *args )
unless included_modules.include? InstanceMethods
self.class_eval { extend ClassMethods }
include InstanceMethods
end
initialize_compositions( args )
end

alias_method :phone_numbers, :phone_number
end

module ClassMethods
def initialize_compositions( attrs )
attrs.each do |attr|
composed_of attr, :class_name => 'PhoneNumber::Number', :mapping => ["raw_#{attr}", 'raw'], :converter => :convert,
:allow_nil => true
end
end
end

module InstanceMethods

end
end
72 changes: 72 additions & 0 deletions lib/phone_number/number.rb
@@ -0,0 +1,72 @@
module PhoneNumber
class Number
attr_reader :country_code, :area_code, :subscriber_number_prefix, :subscriber_number_postfix, :extension

def initialize( number )
if number.is_a?( String ) && m = number.match( /^(\d{1,2})(\d{3})(\d{3})(\d{4})x?(\d*)$/ )
@country_code, @area_code, @subscriber_number_prefix, @subscriber_number_postfix, @extension = m[1], m[2], m[3], m[4], m[5]
elsif number.is_a?( Hash )
@country_code, @area_code, @subscriber_number_prefix, @subscriber_number_postfix, @extension = number[:country_code], number[:area_code], number[:subscriber_number_prefix], number[:subscriber_number_postfix], number[:extension]
end

@@pattern_map = {
/%c/ => (@country_code || '').gsub( /0/, '' ) || "",
/%C/ => @country_code || "",
/%a/ => @area_code || "",
/%m/ => @subscriber_number_prefix || "",
/%p/ => @subscriber_number_postfix || "",
/%x/ => @extension || ""
}

@@patterns = {
:us => "%c (%a) %m-%p x %x",
:us_short => "(%a) %m-%p",
:nanp_short => "(%a) %m-%p"
}

self.freeze
end

def self.parse( number )
number.gsub!( / x /, 'x' )
if m = number.match( /^\+?(\d{0,2})[ \.\-]?\(?(\d{3})\)?[ \.\-]?(\d{3})[ \.\-]?(\d{4})[ x]?(\d*)$/ )
cntry_cd = m[1].size == 2 ? m[1] : "0#{m[1]}"
cntry_cd = '01' if cntry_cd.nil? || cntry_cd.empty? || cntry_cd == '0'
Number.new( :country_code => cntry_cd, :area_code => m[2], :subscriber_number_prefix => m[3], :subscriber_number_postfix => m[4],
:extension => m[5] )
end
end

def empty?
return (@country_code.nil? || @country_code.empty?) && (@area_code.nil? || @area_code.empty?) && (@subscriber_number_prefix.nil? || @subscriber_number_prefix.empty?) &&
(@subscriber_number_postfix.nil? || @subscriber_number_postfix.empty?) && (@extension.nil? || @extension.empty?)
end

# Creates a phone number based on pattern provided. Defaults to US (NANP) formatting (111) 111-1111.
#
# Symbols:
# %c - country code
# %a - area code
# %m - subscriber prefix
# %p - subscriber postfix
#
def to_s( pattern="" )
return '' if self.empty?
to_return = pattern.is_a?( Symbol ) ? @@patterns[pattern] : pattern
to_return = @@patterns[:us_short] if to_return.empty?
@@pattern_map.each { |pat, replacement| to_return = to_return.gsub( pat, replacement ) }
to_return.strip
end

def self.convert( number )
parse( number )
end

private

def raw
ext = (@extension.nil? || @extension.empty?) ? "" : "x#{@extension}"
"#{@country_code}#{@area_code}#{@subscriber_number_prefix}#{@subscriber_number_postfix}#{ext}"
end
end
end
59 changes: 59 additions & 0 deletions phone_number.gemspec
@@ -0,0 +1,59 @@
# Generated by jeweler
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
# -*- encoding: utf-8 -*-

Gem::Specification.new do |s|
s.name = %q{phone_number}
s.version = "0.0.1"

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["C. Jason Harrelson (midas)"]
s.date = %q{2009-12-25}
s.description = %q{Encapsulates the composed of pattern for phone numbers into any easy to use library.}
s.email = %q{jason@lookforwardenterprises.com}
s.extra_rdoc_files = [
"LICENSE",
"README.rdoc"
]
s.files = [
".document",
".gitignore",
"LICENSE",
"README.rdoc",
"Rakefile",
"VERSION",
"lib/phone_number.rb",
"spec/phone_number_spec.rb",
"spec/spec.opts",
"spec/spec_helper.rb"
]
s.homepage = %q{http://github.com/midas/phone_number}
s.rdoc_options = ["--charset=UTF-8"]
s.require_paths = ["lib"]
s.rubygems_version = %q{1.3.5}
s.summary = %q{Encapsulates the composed of pattern for phone numbers into any easy to use library.}
s.test_files = [
"spec/phone_number/number_parsing_shared_spec.rb",
"spec/phone_number/number_spec.rb",
"spec/phone_number_spec.rb",
"spec/spec_helper.rb"
]

if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3

if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<activerecord>, [">= 2.3"])
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
else
s.add_dependency(%q<activerecord>, [">= 2.3"])
s.add_dependency(%q<rspec>, [">= 1.2.9"])
end
else
s.add_dependency(%q<activerecord>, [">= 2.3"])
s.add_dependency(%q<rspec>, [">= 1.2.9"])
end
end

@@ -0,0 +1,23 @@
class PhoneNumberMigrationGenerator < Rails::Generator::NamedBase
def initialize( runtime_args, runtime_options={} )
super
@stamp = DateTime.now.strftime( "%Y%m%d%H%M%S" )
parse_args( args )
end

def manifest
file_name = "#{@table.uppercase}HavePhoneNumbers"

record do |m|
m.directory "db/migrate"
m.template "migration.rb", "db/migrate/#{@stamp}_#{file_name.underscore}.rb"
end
end

private

def parse_args( args )
@table = args[0]
@field = args[1]
end
end
@@ -0,0 +1,9 @@
class <%= file_name.camelcase %>
def self.up
add_column :<%= @table %>, :raw_<%= @field %>, :string, :limit => 35
end

def self.down
remove_column :<%= @table %>, :raw_<%= @field %>
end
end
11 changes: 11 additions & 0 deletions script/console
@@ -0,0 +1,11 @@
#!/usr/bin/env ruby
# File: script/console
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'

libs = " -r irb/completion"
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
libs << " -r 'active_record' -r '#{File.dirname(__FILE__) + '/../lib/phone_number.rb'}'"

puts "Loading phone number gem"
exec "#{irb} #{libs} --simple-prompt"
3 changes: 3 additions & 0 deletions spec/database.yml
@@ -0,0 +1,3 @@
test:
:adapter: sqlite3
:database: ":memory:"
45 changes: 45 additions & 0 deletions spec/phone_number/number_parsing_shared_spec.rb
@@ -0,0 +1,45 @@
require File.expand_path( File.dirname(__FILE__) + '/../spec_helper' )

shared_examples_for "The phone number 1-234-567-8901 x 111" do
it "should agree that the country code is '01'" do
@instance.country_code.should eql( '01' )
end

it "should agree that the area code is '234'" do
@instance.area_code.should eql( '234' )
end

it "should agree that the subscriber number prefix is '567'" do
@instance.subscriber_number_prefix.should eql( '567' )
end

it "should agree that the subscriber number postfix is '234'" do
@instance.subscriber_number_postfix.should eql( '8901' )
end

it "should agree that the extension is '111'" do
@instance.extension.should eql( '111' )
end
end

shared_examples_for "The phone number 1-234-567-8901" do
it "should agree that the country code is '01'" do
@instance.country_code.should eql( '01' )
end

it "should agree that the area code is '234'" do
@instance.area_code.should eql( '234' )
end

it "should agree that the subscriber number prefix is '567'" do
@instance.subscriber_number_prefix.should eql( '567' )
end

it "should agree that the subscriber number postfix is '234'" do
@instance.subscriber_number_postfix.should eql( '8901' )
end

it "should agree that the extension is ''" do
@instance.extension.should eql( '' )
end
end
84 changes: 84 additions & 0 deletions spec/phone_number/number_spec.rb
@@ -0,0 +1,84 @@
require File.expand_path( File.dirname(__FILE__) + '/../spec_helper' )
require File.expand_path( File.dirname(__FILE__) + '/number_parsing_shared_spec' )


describe "PhoneNumber::Number" do
describe "when initializing from a raw string with an extension" do
before :each do
@instance = PhoneNumber::Number.new( '012345678901x111' )
end

it_should_behave_like "The phone number 1-234-567-8901 x 111"
end

describe "when initializing from a raw string without an extension" do
before :each do
@instance = PhoneNumber::Number.new( '012345678901' )
end

it_should_behave_like "The phone number 1-234-567-8901"
end

describe "when being set equal to a string if correctly parsing" do
numbers = ['012345678901', '+012345678901', '12345678901', '2345678901', '01-234-567-8901', '01.234.567.8901', '01 234 567 8901', '+01-234-567-8901',
'+01.234.567.8901', '+01 234 567 8901', '1-234-567-8901', '1.234.567.8901', '1 234 567 8901', '+1-234-567-8901', '+1.234.567.8901', '+1 234 567 8901',
'1 (234) 567-8901', '(234) 567-8901', '1 (234) 567.8901', '(234) 567.8901', '(234) 567 8901', '(234) 5678901', '(234)5678901', '1(234)5678901',
'01(234)5678901', '+1(234)5678901', '+01(234)5678901' ]

numbers.each do |number|
describe "'#{number}'" do
before :each do
@instance = PhoneNumber::Number.parse( number )
end

it_should_behave_like "The phone number 1-234-567-8901"
end
end

numbers.map{ |n| n + 'x111' }.each do |number|
describe "'#{number}'" do
before :each do
@instance = PhoneNumber::Number.parse( number )
end

it_should_behave_like "The phone number 1-234-567-8901 x 111"
end
end

numbers.map{ |n| n + ' x 111' }.each do |number|
describe "'#{number}'" do
before :each do
@instance = PhoneNumber::Number.parse( number )
end

it_should_behave_like "The phone number 1-234-567-8901 x 111"
end
end
end

describe "when formatting output" do
before :each do
@instance = PhoneNumber::Number.new( '012345678901x111' )
end

it "should format the number correctly with the pattern '%a-%m-%p'" do
@instance.to_s( '%a-%m-%p' ).should eql( '234-567-8901' )
end

it "should format the number correctly with the pattern '%a.%m.%p x %x'" do
@instance.to_s( '%a.%m.%p x %x' ).should eql( '234.567.8901 x 111' )
end

it "should define a format of us_short" do
@instance.to_s( :us_short ).should eql( '(234) 567-8901' )
end

it "should use the us_short format for its default format" do
@instance.to_s( :us_short ).should eql( @instance.to_s )
end
end

it "should agree that a newly instantiated phone number is empty" do
PhoneNumber::Number.new( nil ).empty?.should be_true
end
end

0 comments on commit 270fbda

Please sign in to comment.