Rails 3 + postgresql
我想为列的默认值添加一个随机字符串的阴影。
所以,在我的迁移中,我有:
t.string :uniqueid, default: md5(random()::text)
但是我无法得到它来实际产生任何东西,我使用了反引号,引号等。从我看到的示例中,似乎pg函数仅在SELECT
语句中有效。
准确吗?关于如何实现此目标的任何想法?
谢谢
Rails将尝试解释这一点:
t.string :uniqueid, default: md5(random()::text)
作为Ruby代码和:default => md5(...)
在Ruby中没有任何意义。如果您引用它,那么Rails会认为它是一个字符串,并将uniqueid
的默认值设置为字符串'md5(random()::text)'
,但这无济于事。
您的问题是,Rails无法理解诸如使用函数作为列默认值之类的复杂事物,Rails具有一种奇怪而被误导的观念,即您应该在Rails中而不是在数据库中进行所有操作。如果要在默认列中使用函数调用,则可以手动执行alter table
:
alter table
这将为您提供数据库中所需的默认值,但您可能会注意到connection.execute(%q{
alter table your_table alter column uniqueid set default md5(random()::text)
})
中没有提及新的默认值。如果您想要一个可用的模式,那么您就必须将Rails推开,并使用schema.rb
:
SQL schema instead by putting this in your application.rb
请注意,SQL模式转储在3.2之前一直被破坏,并且在各种Rails版本中都有模式加载问题(但是您可以始终以application.rb
的方式来解决)。然后删除config.active_record.schema_format = :sql
,而改用psql < structure.sql
。从好的方面来看,SQL模式转储将跟踪真正的外键,检查约束,触发器等花哨的事物。
顺便说一句,如果您真的想要SHA,那么您将需要查看schema.rb
。
当然,所有这些都不起作用,因为ActiveRecord太笨了,无法将它无法理解的东西丢掉。 ActiveRecord在解析从数据库获取的表定义时将看到默认值,但是它不理解它,因此它将忽略它。然后,在INSERT期间,ActiveRecord似乎坚持为所有列提供值,即使您没有为其分配值的列也是如此。结果是,即使您已在数据库中附加了明智的默认值,您也将在structure.sql
中以NULL结尾。
所以,您如何解决?与ActiveRecord一样,您假装数据库是一个愚蠢的电子表格,并可能使用digest
function from pgcrypto
钩子在Ruby中进行所有操作。或者,您可以找到比ActiveRecord更少的数据库恶意ORM;我不确定其他ORM能否很好地处理非恒定列默认值。
或者,您可以尝试编写一个BEFORE INSERT触发器,如果digest
,它将为该列分配默认值。
您也可以这样做