我有一个简单的电话表格<%= f.text_field:phone%>马上. :手机是一个整数类型,所以这要求用户输入表格必须是5551234,而不是更标准的方式555-1234我如何允许用户输入像他们习惯的美国电话号码?我知道我可以使用validates_format_of来验证它,但是一旦我验证它,我如何格式化数字并将电话号码作为整数插入数据库?
解决方法
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就好像它是一个普通的(非动态的)方法(在docs中没有显示但是有效):
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 ) – 获得的形式:迁移中的整数. MysqL中的BigInt是通过将limit限制为8获得的,如此迁移行中所示:
change_column :model_name,:phone,:integer,:limit => 8
这将给你一个bigint(20)在你的表中,可以处理多达9,223,372,036,854,775,807的数字,这应该足够任何电话号码.