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
, что должно быть достаточно для любого телефонного номера.