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通过设定得到:limit以8如在此迁移行:
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)
应该做的伎俩.它删除了非数字字符.
"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