我们所有人都在开发环境中的应用程序中添加了新的表和列。当事情出错时,我们放下桌子开始新鲜,没有伤害,没有犯规。但是,当我们在生产阶段遇到问题时会发生什么?那是挑战开始的时候。在这篇文章中,我们将解决涉及非限制的棘手迁移方案,并共享实用技巧,以避免在生产中丢失数据。所以搭扣,让我们潜入! ð
ð开发阶段幸福
当我在validateok.click应用程序上工作时,我需要将新列category
添加到现有表ideas
中。这是一个示例迁移:
class AddCategoryToIdeas < ActiveRecord::Migration[7.1]
def change
add_reference :ideas,
:category,
default: 'Tools',
null: false,
foreign_key: true,
type: :uuid
end
end
在开发环境中,运行此迁移很轻松,一切都按预期工作。但是生产呢? ð°
- 生产阶段障碍
在生产中,除非我们愿意失去所有东西,否则丢弃数据库不是一个选择 - 没人想要! ð±使用与我们在上述发展中所做的相同迁移步骤可能会导致错误,就像这样:
ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR: column "category_id" of relation "ideas" contains null values
错误之所以发生错误,是因为ideas
表中的现有记录不具有category_id
值,而不仅如此,而且我们设置了null: false
约束。我们该怎么办来解决这个问题? ðρ
ð解决方案
不用担心!我们为您提供了完美的解决方案。让我们浏览生产优雅地处理此迁移所需的步骤
步骤1:删除默认值并将迁移分为两个部分
首先,从迁移中删除默认值“工具”,因为它应该是UUID
而不是字符串。 这是我的错误,因为我没有注意我正在使用uuid。我是唯一的一个ðÖT,然后将迁移分为两个步骤:
- 在没有
null: false
约束的情况下添加category_id
列,并使用默认类别回填现有想法。 - 最后,添加
null: false
约束。
这是更新的迁移文件:
class AddCategoryToIdeas < ActiveRecord::Migration[7.1]
def up
add_reference :ideas, :category, foreign_key: true, type: :uuid #1
default_category = Category.find_or_create_by!(name: 'Tools')
Idea.update_all(category_id: default_category.id)
change_column_null :ideas, :category_id, false #2
end
def down
remove_reference :ideas, :category
end
end
步骤2:了解每个步骤的目的
- 添加无
null: false
约束的category_id
列。这使我们能够在不违反非编号约束的情况下更新现有记录。 - 查找或创建名为“工具”的默认类别,并将其ID设置为所有现有想法的默认
category_id
。这确保了所有现有想法都有有效的category_id
值。 - 将
null: false
约束添加到category_id
列。现在,所有现有的想法都使用默认的category_id
进行了更新,我们可以安全地执行非无效约束。 - 现在您可以自信地运行
rails db:migrate
ð总结
,你有它,伙计们!多亏了这些步骤,我们在生产环境中优雅地处理了潜在的棘手迁移,而不会丢失任何数据ð。通过将迁移分为两个部分,更新现有记录,然后执行非挂钩约束,我们使应用程序更加健壮和可靠。
请记住,作为Rails Developers,必须考虑我们的DB迁移在开发和生产环境中的影响。有了一点远见和一些位置良好的表情符号ð,我们可以克服这些挑战并继续构建出色的应用。
一如既往,愉快的编码,直到下一次! ð