Ruby on Rails: проверка и изменение номера телефона - PullRequest
7 голосов
/ 30 июля 2010

У меня есть простая телефонная форма <%= f.text_field :phone %> прямо сейчас. :phone является целочисленным типом, поэтому для этого требуется, чтобы все, что пользователь вводит в форму, было что-то вроде 5551234 вместо более стандартного способа 555-1234 Как я могу позволить пользователю вводить номер телефона в США, например их привыкли? Я понимаю, что могу использовать validates_format_of для проверки, но как только я его проверю, как я могу отформатировать номер и вставить номер телефона в БД в виде целого числа?

Ответы [ 4 ]

17 голосов
/ 20 декабря 2011

ActiveRecord автоматически вводит ввод данных в зависимости от типа столбца базы данных. Когда Ruby преобразует строку в целое число, он удаляет все после первого нечислового символа, 123-456-7890 станет 123. Это делается до того, как поле доступно в модели, поэтому приведенные решения не будут работать. Вам необходимо перезаписать средство записи по умолчанию!

В ActiveRecord :: Base docs упоминается два способа перезаписи средства доступа по умолчанию для записи (field_name)= в модели, чтобы вы могли обработать ввод, удаляя нецифровые символы, прежде чем его нужно будет привести к типу. Существует как минимум три варианта:

(1) Перезаписать метод доступа и использовать write_attribute для сохранения результата в базе данных:

def phone=(value)
  value.gsub!(/\D/, '') if value.is_a?(String)
  write_attribute(:phone, value.to_i)
end

(2) Или используйте хэш-запись:

def phone=(num)
  num.gsub!(/\D/, '') if num.is_a?(String)
  self[:phone] = num.to_i
end

(3) Или (в последних версиях ActiveRecord) просто вызвать super, как если бы это был обычный (не динамический) метод (не показан в документации, но работает):

def phone=(num)
  num.gsub!(/\D/, '') if num.is_a?(String)
  super(num)
end

Это полезно в ряде ситуаций, таких как числа с запятыми, и прекрасно работает с формами, которые предоставляют отформатированную версию предыдущего значения поля, например, в форме редактирования или после ошибки в новой форме / форме создания:

<%= f.text_field :phone, number_to_phone(@model_data.phone) %>

Таким образом, вы можете отображать данные, отформатированные пользователем (то есть как String), но по-прежнему сохранять целое число в базе данных.

Последний совет по MySQL: вам нужно использовать BigInt для хранения номера телефона, в противном случае вы увидите много (214) 748-3647 телефонных номеров в вашей базе данных, так как 2,147,483,647 является максимальным значением обычного целого числа MySQL - int(11) - полученная форма :integer в миграции. BigInt в MySQL получается путем установки :limit в 8, как в этой строке миграции:

change_column :model_name, :phone, :integer, :limit => 8

Это даст вам bigint(20) в вашей таблице, которая может обрабатывать номера до 9,223,372,036,854,775,807, что должно быть достаточно для любого телефонного номера.

12 голосов
/ 30 июля 2010
phone.gsub(/\D/, '')

должен сделать свое дело. Удаляет нецифровые символы.

0 голосов
/ 15 декабря 2011

Не уверен, что вы все выяснили, но я столкнулся с той же проблемой, что и Рети с кодом Марка.

Кажется, что конкретный self.phone = self.phone.gsub(/\D/, '') добился цели.

Может быть, это потому, что в этот момент phone еще не инициализирован? Я не уверен, все еще новичок здесь ...

0 голосов
/ 30 июля 2010
"1-2-3-4".gsub('-','').to_i
# => 1234

Вы также можете использовать регулярные выражения, если вы хотите получить больше фантазии, но вы должны иметь возможность сойти с рук только с этим.

Возможно, вы захотите проверить, что вы храните в БД, так как Rails проверяет проверки перед сохранением. Тем не менее, вы можете сделать before_validation, который сначала изменяет число. Как то так:

before_validation do
  phone = phone.to_s.gsub('-','').to_i
end

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M001378

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...