大整数和自定义验证

时间:2013-06-10 23:22:12

标签: ruby-on-rails ruby-on-rails-3 postgresql rails-models

我对Rails有点新鲜,我正在尝试了解自定义验证。

巴西的一个常见要求是CPF / CNPJ / RG字段。它们是一种识别号码,并遵循特定的格式。

例如:

CPF是11位数字。他们遵循以下模式:xxx.xxx.xxx-xx

我正在尝试将它们存储在Integer字段中,但我得到了(使用Postgres):

  

PG ::错误:错误:值“xxxxxxxxxxx”超出类型范围   整数

存储这个的正确方法是什么? Bigint(如何?)?字符串?

我的第二个问题是:

如何为此字段指定自定义验证(方法),可以像这样调用:

class User < AR::Base

   validates :cpf, presence: true, unique: true, cpf: true

3 个答案:

答案 0 :(得分:2)

假设性能不重要,字符串就可以了。这样你可以保持点和破折号。正如本主题中其他人所提到的,如果这是一个问题,bigintnumeric可能会更高效。

如果您将字段保留为字符串,则可以使用regex轻松验证它:

validates_format_of :cpf, with: /^[0-9]{3}\.[0-9]{3}\.[0-9]{3}\-[0-9]{2}$/

答案 1 :(得分:1)

对于小型表,只需存储为text以保留格式。

对于大表,性能和存储大小可能是个问题。如果您的模式有保证,您可以将该数字存储为bigint,并在使用to_char()检索时对其进行格式化:

写:

SELECT translate('111.222.333-55', '.-', '')::bigint

这也可以作为部分验证。您的字符串中只允许使用数字.-。该模式可能仍然被违反,您必须使用@Michael provided等明确检查。

读:

SELECT to_char(11122233355, 'FM000"."000"."000"-"00')

返回:

111.222.333-55

不要忘记模式中的前导FM以删除前导空格(负号可能用于数字)。

bigint在磁盘上占用 8个字节,可以轻松存储11位数字。
text(或varchar)需要1个字节加上实际字符串,在您的情况下需要 15个字节
另外,处理bigint通常比处理等长的text快一点。

答案 2 :(得分:0)

我个人总是将这些值存储为bigint并在输入/输出(如Erwin建议)或应用程序中应用格式。

主要原因是存储效率(如Erwin所述)和比较效率。将1111111111211111111113比较为text时,PostgreSQL将使用对文本正确的特定于语言的归类规则,但可能不是您想要的数字。他们也;最近关于SO的问题报告说,通过使用COLLATE "C"选项强制进行简单的POSIX排序,文本比较的速度提高了五倍;数字校对再次更快。

这些标准数字中的大多数都有自己的内部校验和,通常是Luhn algorithm的变体。在CHECK约束中验证这些可能是一个好主意。您可以在PL / PgSQL或纯SQL中轻松实现对整数的Luhn算法检查; I wrote some samples on the PostgreSQL wiki

无论您做什么,请确保在列上验证存储号码的CHECK约束,这样您就不会存储无效和无意义的值。