I have a simple phone form <%= f.text_field :phone %>
right now. :phone
is an integer type, so this requires that whatever the user enters into the form must be something like 5551234
instead of the more standard way of 555-1234
How can I allow the user to enter in a USA phone number like their accustomed to? I understand that I can use validates_format_of
to validate it, but once I validate it, how can I format the number and insert the phone number into the DB as an integer?
ActiveRecord automatically typecasts input based on the databases column type. When Ruby casts a string to an integer it drops everything after the first non-numeric character, 123-456-7890
will become 123
. This is done before the field is available in the model so the solutions given so far will not work. You need to overwrite the default write accessor!
The ActiveRecord::Base docs mentions two ways to overwrite the default write accessor (field_name)=
in the model so you can process the input removing the non-digits before it needs to be typecast. There are at least three variations:
(1) Overwrite the accessor and use write_attribute to store the result in the database:
def phone=(value)
value.gsub!(/\D/, '') if value.is_a?(String)
write_attribute(:phone, value.to_i)
end
(2) Or use the hash notation:
def phone=(num)
num.gsub!(/\D/, '') if num.is_a?(String)
self[:phone] = num.to_i
end
(3) Or (in the latest versions of ActiveRecord) just call super as if it were a normal (non-dynamic) method (not shown in docs but works):
def phone=(num)
num.gsub!(/\D/, '') if num.is_a?(String)
super(num)
end
This is useful in a number of situations such as numbers with commas and works great with forms that supply a formatted version of the previous field value such as in an edit form or after an error in a new/create form:
<%= f.text_field :phone, number_to_phone(@model_data.phone) %>
This way you can show the user formatted data (i.e. as String) but still store an integer in the database.
One last tip on MySQL: You need to use a BigInt
to store a phone number otherwise you will see a lot of (214) 748-3647
phone numbers in your database as 2,147,483,647
is the max value of a normal MySQL integer - int(11)
- obtained form :integer
in a migration. A BigInt
in MySQL is obtained by setting :limit
to 8
as in this migration line:
change_column :model_name, :phone, :integer, :limit => 8
This will give you a bigint(20)
in your table which can handle numbers up to 9,223,372,036,854,775,807
which should be sufficient for any phone number.
phone.gsub(/\D/, '')
should do the trick. It removes non-digit chars.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With