rails migration:postgresql for md5 of random string as default

Rails 3 + postgresql

我希望有一个随机字符串的sha用于列的默认值。

所以,在我的迁移中,我有:

t.string :uniqueid, default: md5(random()::text)

然而,我无法让它实际产生任何东西,我使用了反引号,引号等。 从我看过的例子来看,似乎pg函数只能在SELECT语句中使用。

这是准确的吗? 有关如何实现这一目标的任何想法?

谢谢

Rails会尝试解释这个:

 t.string :uniqueid, default: md5(random()::text) 

作为Ruby代码和:default => md5(...)在Ruby中没有任何意义。 如果你引用它,那么Rails会认为它是一个字符串,并将uniqueid的默认值uniqueid字符串'md5(random()::text)' ,这对你没有帮助。

你的问题是Rails不理解像使用函数作为列默认值这样复杂的事情,Rails有一个奇怪的和被误导的概念,你应该在Rails中而不是在数据库中做所有事情。 如果要在列默认值中使用函数调用,可以手动执行alter table

 connection.execute(%q{ alter table your_table alter column uniqueid set default md5(random()::text) }) 

这将使您获得数据库中所需的默认值,但您可能会注意到schema.rb没有提及新的默认值。 如果你想要一个可用的模式,那么你当然必须将Rails推开并使用SQL模式,而不是将它放在你的application.rb

 config.active_record.schema_format = :sql 

请注意,SQL架构转储在3.2之前一直被破坏,并且在各种Rails版本中存在架构加载问题(但您可以随时使用psql < structure.sql )。 然后删除schema.rb并改用structure.sql 。 从好的方面来说,SQL模式转储将跟踪真实的外键,检查约束,触发器......

顺便说一句,如果你真的想要SHA那么你会想看看pgcryptodigest函数 。


当然,这些都不会起作用,因为ActiveRecord太愚蠢了,不能单独留下它不理解的东西。 ActiveRecord在分析从数据库获取的表定义时会看到默认值,但它不会理解它,所以它会忽略它。 然后,在INSERT期间,ActiveRecord似乎坚持为所有列提供值,甚至是您没有为其赋值的列。 结果是,即使您在数据库中附加了合理的默认值,您也会在uniqueid得到NULL。

那么,你怎么解决这个问题呢? 像往常一样使用ActiveRecord,你假装数据库是一个愚蠢的电子表格,并使用可能的before_create钩子在Ruby中做所有事情。 或者你可以找到一个比ActiveRecord更少数据库恶意的ORM; 我不确定其他ORM如何处理非常量列默认值。

或者,您可以尝试编写BEFORE INSERT触发器,如果NEW.uniqueid IS NULL ,则会将默认值分配给该列。