如何将现有模型(包括插入的行)从可空列迁移到不可空列

时间:2018-10-27 04:31:09

标签: ruby-on-rails ruby ruby-on-rails-5 database-migration

我用列定义创建了一个模型

create_table :admin_authentication_tokens do |t|
    t.integer :authentication_ttl
end

现在我想使authentication_ttl不可为空。我尝试了这种迁移

change_column :admin_authentication_tokens, :authentication_ttl, :integer, null: false, default: 0

但是出现错误 PG::NotNullViolation: ERROR: column "authentication_ttl" contains null values 我了解错误的含义,但我不想手动迁移模型。因此,请给我一种使用迁移文件迁移模型的方法。

1 个答案:

答案 0 :(得分:5)

您不能向包含空值的列添加NOT NULL约束。

一种或另一种方法,在执行这种迁移之前,您需要摆脱这些值。

例如,如上所述,也许这些都应设置为0

MyModel.where(authentication_ttl: nil).update_all(authentication_ttl: 0)

...或者也许还有一些其他值可以设置为(某些)列?

也许这些行实际上没有意义,应该删除吗?

MyModel.where(authentication_ttl: nil).delete_all

(或者也许应该destroy_all来触发rails回调?)

简而言之,答案确实取决于您的具体情况。但是,无论哪种方式,您都需要先摆脱null

请注意,如果您既有生产环境又有本地环境,则在部署之前需要将其考虑在内。同样,通过一种或多种方式(例如,通过rake任务),您需要在部署此类迁移之前先“修复”生产数据。