<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -1,5 +1,6 @@
 == master
 
+* Add the ability to parse raw values [Matt Lightner]
 * Validate that the country code is known
 * Validate number lengths on a per-country code basis
 * Add the list of available country codes</diff>
      <filename>CHANGELOG.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -53,3 +53,7 @@ To run against a specific version of Rails:
 == Dependencies
 
 * Rails 2.3 or later
+
+== References
+
+* Casey West - {Parse-PhoneNumber}[http://search.cpan.org/~cwest/Parse-PhoneNumber-1.1]</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -51,6 +51,11 @@ class PhoneNumber &lt; ActiveRecord::Base
   # The list of country calling codes as defined by ITU-T recommendation E.164
   COUNTRY_CODES = VALID_LENGTHS.keys
   
+  # Whether to always use the default country code configured for this model
+  # when parsing the raw content of a phone number
+  cattr_accessor :use_default_country_code_on_parse
+  @@use_default_country_code_on_parse = false
+  
   belongs_to :phoneable, :polymorphic =&gt; true
   
   validates_presence_of :phoneable_id, :phoneable_type, :country_code, :number
@@ -58,7 +63,6 @@ class PhoneNumber &lt; ActiveRecord::Base
   validates_numericality_of :extension, :allow_nil =&gt; true
   validates_length_of :extension, :maximum =&gt; 10, :allow_nil =&gt; true
   validates_inclusion_of :country_code, :in =&gt; COUNTRY_CODES
-  
   validates_each :number do |phone_number, attr, value|
     country_code = phone_number.country_code
     
@@ -74,4 +78,54 @@ class PhoneNumber &lt; ActiveRecord::Base
       end
     end
   end
+  
+  # The raw, unparsed content containing the phone number.  This can be parsed
+  # in various formats, such as:
+  # * 600 600 11 22
+  # * + 386 1 5853 449
+  # * +48 (22) 64 0001
+  # * 36 1 267-4636
+  # * +39-02-48230001
+  # * 202 331 996 x4621
+  # * 358 2 141 540 65 ext. 1423
+  attr_accessor :content
+  before_validation_on_create :parse_content, :if =&gt; :content
+  
+  private
+    # Parses the raw content of a phone number, extracting the following
+    # attributes:
+    # * country_code
+    # * number
+    # * extension
+    def parse_content
+      content = self.content.strip
+      
+      # Check for extension
+      if match = content.match(/\s*(?:(?:ext|ex|xt|x)[\s.:]*(\d+))$/i)
+        self.extension = match[1]
+        content.gsub!(match.to_s, '')
+      end
+ 
+      # Remove non-digits and leading 0
+      content.gsub!(/\D/, '')
+      content.gsub!(/^0+/, '')
+      
+      if use_default_country_code_on_parse
+        # Scrub pre-determined country code
+        content.gsub!(/^#{country_code}/, '')
+      else
+        # Try to figure out the country code.  It is not possible for one
+        # country code's number to overlap another.
+        (1..3).each do |length|
+          code = content[0, length]
+          if VALID_LENGTHS[code] # Fast lookup
+            self.country_code = code
+            content.gsub!(/^#{code}/, '')
+            break
+          end
+        end
+      end
+      
+      self.number = content
+    end
 end</diff>
      <filename>app/models/phone_number.rb</filename>
    </modified>
    <modified>
      <diff>@@ -154,3 +154,166 @@ class PhoneNumberAfterBeingCreatedTest &lt; Test::Unit::TestCase
     assert_equal @person, @phone_number.phoneable
   end
 end
+
+class PhoneNumberParserTest &lt; Test::Unit::TestCase
+  def setup
+    @person = create_person
+    @phone_number = new_phone_number(:phoneable =&gt; @person, :country_code =&gt; nil, :number =&gt; nil, :extension =&gt; nil)
+  end
+  
+  def test_should_parse_country_code_with_1_digit
+    @phone_number.content = '11234567890'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_nil @phone_number.extension
+  end
+  
+  def test_should_parse_country_code_with_2_digits
+    @phone_number.content = '20123456789'
+    
+    assert @phone_number.valid?
+    assert_equal '20', @phone_number.country_code
+    assert_equal '123456789', @phone_number.number
+    assert_nil @phone_number.extension
+  end
+  
+  def test_should_parse_country_code_with_3_digits
+    @phone_number.content = '21212345678'
+    
+    assert @phone_number.valid?
+    assert_equal '212', @phone_number.country_code
+    assert_equal '12345678', @phone_number.number
+    assert_nil @phone_number.extension
+  end
+  
+  def test_should_parse_number_with_spaces
+    @phone_number.content = '1 123 456 7890'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_nil @phone_number.extension
+  end
+  
+  def test_should_parse_number_with_dashes
+    @phone_number.content = '1-123-456-7890'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_nil @phone_number.extension
+  end
+  
+  def test_should_parse_number_with_parentheses
+    @phone_number.content = '1- (123) 456-7890'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_nil @phone_number.extension
+  end
+  
+  def test_should_parse_number_with_leading_zero
+    @phone_number.content = '011234567890'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_nil @phone_number.extension
+  end
+  
+  def test_should_parse_number_with_multiple_leading_zeroes
+    @phone_number.content = '0011234567890'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_nil @phone_number.extension
+  end
+  
+  def test_should_parse_extension_with_leading_ext
+    @phone_number.content = '11234567890 ext. 123'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_equal '123', @phone_number.extension
+  end
+  
+  def test_should_parse_extension_with_leading_ex
+    @phone_number.content = '11234567890 ex:123'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_equal '123', @phone_number.extension
+  end
+  
+  def test_should_parse_extension_with_leading_xt
+    @phone_number.content = '11234567890 xt: 123'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_equal '123', @phone_number.extension
+  end
+  
+  def test_should_parse_extension_with_leading_x
+    @phone_number.content = '11234567890 x.  123'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_equal '123', @phone_number.extension
+  end
+  
+  def test_should_parse_extension_with_mixed_case
+    @phone_number.content = '11234567890 xT 123'
+    
+    assert @phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '1234567890', @phone_number.number
+    assert_equal '123', @phone_number.extension
+  end
+  
+  def test_should_not_be_valid_if_parse_fails
+    @phone_number.content = '1123456789'
+    
+    assert !@phone_number.valid?
+    assert_equal '1', @phone_number.country_code
+    assert_equal '123456789', @phone_number.number
+    assert_nil @phone_number.extension
+  end
+end
+
+class PhoneNumberParserWithDefaultCountryCodeTest &lt; Test::Unit::TestCase
+  def setup
+    PhoneNumber.use_default_country_code_on_parse = true
+    
+    @person = create_person
+    @phone_number = new_phone_number(:phoneable =&gt; @person, :content =&gt; '7234567890 ex. 12')
+    @valid = @phone_number.valid?
+  end
+  
+  def test_should_be_valid
+    assert @valid
+  end
+  
+  def test_should_use_default_country_code
+    assert_equal '1', @phone_number.country_code
+  end
+  
+  def test_should_parse_number
+    assert_equal '7234567890', @phone_number.number
+  end
+  
+  def test_should_parse_extension
+    assert_equal '12', @phone_number.extension
+  end
+  
+  def teardown
+    PhoneNumber.use_default_country_code_on_parse = false
+  end
+end</diff>
      <filename>test/unit/phone_number_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>cbfef0cf4b59b2c0a70650101c26c3bdd614de8a</id>
    </parent>
  </parents>
  <author>
    <name>Matt Lightner</name>
    <email>mlightner@gmail.com</email>
  </author>
  <url>http://github.com/pluginaweek/has_phone_numbers/commit/38db07a382cefdbcb439f333ba1ef1c21b62dd16</url>
  <id>38db07a382cefdbcb439f333ba1ef1c21b62dd16</id>
  <committed-date>2009-04-19T11:40:30-07:00</committed-date>
  <authored-date>2009-04-19T11:40:30-07:00</authored-date>
  <message>Add the ability to parse raw values</message>
  <tree>32b19bbf6ced799649006d875777995ae274a540</tree>
  <committer>
    <name>Aaron Pfeifer</name>
    <email>aaron.pfeifer@gmail.com</email>
  </committer>
</commit>
