Phone number conversions

I'm trying to figure out a good way to store phone numbers as an integer in a rails app without having to have separate columns in the table for each part of the phone number. I want people to enter the phone number in a single entry field, but to be able to store it as an integer rather than as a string.

My idea was to allow free-form text entry in the form, but to add something into create() to turn the string into an integer. From the console, though:

    >> @foo=User.new     >> @foo.build_contact     >> @foo.contact.phone='123-456-7890'     >> p @foo.contact.phone     => 123

Obviously, rails is converting the string to an integer before saving it to the database, but this doesn't get me where I need to go. My idea was to simply add some evaluation in create like:

    @foo.contact.phone.gsub([^\d]+, '')

but this obviously isn't going to work. So, if my model defines contact.phone as an integer, how can I coerce numbers entered from the new/edit views into the appropriate data type?

What about storing things like 123-123-1234 ext 123 ?

A phone number isn't a number.

Also UK phone numbers generally start with 0 so 0123456789 would be indistinguishable from 123456789

What is wrong with storing it as a string anyway?

Colin

What is wrong with storing it as a string anyway?

Strings are less efficient than integers, from a database point of view. More importantly, though, if you store a number as varchar or text, you have a much harder time regularizing the output. For example, you couldn't do this:

   >> foo = ActionView::Base.new    >> foo.number_to_phone 1234567890, :area_code => true    => "(123) 456-7890"

with a random string. If you try, you just get back the original string, like so:

    >> foo.number_to_phone "123/456.7890x55", :area_code => true     => "123/456.7890x55"

The whole idea here is to regularize the data IN THE DATABASE, so that the output can be customized (and perhaps even changed later) without having to change the schema. Isn't there some way to strip out the characters and extra digits *after* form submission but *before* the assignment to the model object?

which you can only do with US phone numbers, without extensions. That seems pretty limited.[*]

And if you're going to try to not parse the data on the way into the database, how are you going to store your "123/456.7890x55" example?

Stored strictly as an integer, foo.number_to_phone will return 12(345) 678-9055 -- is that what you want?

[*] BTW, it's not that long ago that my wife ran a small island resort in the Kingdom of Tonga, and the resort phone # was '5' :slight_smile:

FWIW,

Todd A. Jacobs wrote:

What is wrong with storing it as a string anyway?

Strings are less efficient than integers, from a database point of view.

Premature optimization. -- and phone numbers really aren't numbers anyway.

More importantly, though, if you store a number as varchar or text, you have a much harder time regularizing the output. For example, you couldn't do this:

   >> foo = ActionView::Base.new    >> foo.number_to_phone 1234567890, :area_code => true    => "(123) 456-7890"

Of course you can. It's trivial to do that with a phone number stored as a string. In fact, doing it with an integer would involve converting the integer to a string first.

with a random string. If you try, you just get back the original string, like so:

    >> foo.number_to_phone "123/456.7890x55", :area_code => true     => "123/456.7890x55"

Then use to_i or write your own helper. Better yet, create a PhoneNumber class and give it a meaningful to_s method.

The whole idea here is to regularize the data IN THE DATABASE, so that the output can be customized (and perhaps even changed later) without having to change the schema. Isn't there some way to strip out the characters and extra digits *after* form submission but *before* the assignment to the model object?

Yup. You can use an ActiveRecord callback, or (if you create a PhoneNumber class) use composed_of and put this logic in the constructor.

-- "Oh, look: rocks!"   -- Doctor Who, "Destiny of the Daleks"

Best,