Ruby on Rails:验证和更改电话号码

Ret*_*eti 7 validation ruby-on-rails

我现在有一个简单的电话表格<%= f.text_field :phone %>.:phone是一个整数类型,所以这要求用户输入表单的内容必须是类似的5551234而不是更标准的方式555-1234如何允许用户输入他们习惯的美国电话号码?我知道我可以使用validates_format_of它来验证它,但是一旦我验证它,我如何格式化数字并将电话号码作为整数插入数据库?

小智 17

ActiveRecord根据数据库列类型自动进行类型转换.当红宝石投下了一个字符串,它将使第一个非数字字符后的所有整数,123-456-7890将成为123.这是在模型中的字段可用之前完成的,因此到目前为止给出的解决方案将不起作用.您需要覆盖默认的写访问器!

的ActiveRecord :: Base的文档提到了两种方式来覆盖默认的写访问(field_name)=的模式,使您可以处理输入除去非数字需要进行类型转换之前.至少有三种变化:

(1)覆盖访问器并使用write_attribute将结果存储在数据库中:

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

(2)或使用哈希表示法:

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

(3)或者(在最新版本的ActiveRecord中)只需调用super就好像它是一个普通的(非动态的)方法(在docs中没有显示但是有效):

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

这在许多情况下非常有用,例如带逗号的数字,并且对于提供前一字段值的格式化版本的表单非常有用,例如在编辑表单中或在新/创建表单中出错之后:

<%= f.text_field :phone, number_to_phone(@model_data.phone) %>
Run Code Online (Sandbox Code Playgroud)

这样,您可以显示用户格式化的数据(即String),但仍然在数据库中存储整数.

关于MySQL的最后一个提示:您需要使用a BigInt来存储电话号码,否则您将(214) 748-3647在数据库中看到许多电话号码,这2,147,483,647是正常MySQL整数的最大值int(11)- 从:integer迁移中获得的形式.甲BigInt在MySQL通过设定得到:limit8如在此迁移行:

change_column :model_name, :phone, :integer, :limit => 8
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个bigint(20)表格,可以处理9,223,372,036,854,775,807任何电话号码应该足够的号码.


Mar*_*mas 12

phone.gsub(/\D/, '')
Run Code Online (Sandbox Code Playgroud)

应该做的伎俩.它删除了非数字字符.

  • 有许多方法可以将整数格式化为显示为电话号码.请参阅NumberHelper(http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html)或'phone'gem(https://github.com/carr/phone) (3认同)

Kar*_*arl 0

"1-2-3-4".gsub('-','').to_i
# => 1234
Run Code Online (Sandbox Code Playgroud)

如果您想变得更奇特,您也可以使用正则表达式,但您应该能够摆脱这一点。

您可能想要验证将其存储在数据库中的内容,因为 Rails 在保存之前会检查验证。但是,您可以before_validation先修改数字。像这样的东西:

before_validation do
  phone = phone.to_s.gsub('-','').to_i
end
Run Code Online (Sandbox Code Playgroud)

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