ruby-on-rails - 如何回滚此 Rails 迁移?
问题描述
我运行了以下迁移并忘记包含我想要的默认值。我正在尝试回滚它,以便我可以添加默认值并再次前滚。
20190728151635_add_cooldown_to_skill_levels.rb
class AddCooldownToSkillLevels < ActiveRecord::Migration[5.1]
def change
add_column :skill_levels, :cooldown, :integer
end
end
所有 rails db:migrate 和 db:rollbacks 都失败并出现以下错误
$ rails db:回滚
== 20190728151635 AddCooldownToSkillLevels: reverting =========================
-- remove_column(:skill_levels, :cooldown, :integer)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "skill_levels"
And 100+ more lines ...
我尝试将迁移更改为具有明确的向上/向下方法无济于事
class AddCooldownToSkillLevels < ActiveRecord::Migration[5.1]
def up
add_column :skill_levels, :cooldown, :integer
end
def down
remove_column :skill_levels, :cooldown
end
end
我尝试添加一个只添加默认值的新迁移。
20190728153208_add_default_value_to_cooldown_on_skill_levels.rb
class AddDefaultValueToCooldownOnSkillLevels < ActiveRecord::Migration[5.1]
def change
change_column_default :skill_levels, :cooldown, 1
end
end
类似的错误 $ rails db:migrate
== 20190728153208 AddDefaultValueToCooldownOnSkillLevels: migrating ===========
-- change_column_default(:skill_levels, :cooldown, 1)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "skill_levels"
And 100+ more lines ...
我很乐意直接在 SQL 中修复它,但我试图保持我的迁移完好无损。
编辑:添加 $ rails db:migrate:status 的输出
...
up 20190727160901 Create skill levels
up 20190728004535 Create skill effects
up 20190728151635 Add cooldown to skill levels
down 20190728153208 Add default value to cooldown on skill levels
感谢你的帮助。
解决方案
The error:
FOREIGN KEY constraint failed: DROP TABLE "skill_levels"
is telling you that there is a foreign key constraint that references your skill_levels
table (i.e. t.references :skill_levels, foreign_key: true
in some other migration) and the remove_column :skill_levels, :cooldown
is causing a problem with that.
But why would a database constraint be a problem during an ALTER TABLE to remove a column? Well, SQLite's ALTER TABLE doesn't support removing a column, instead you have to (see the SQLite FAQ or How to delete or add column in SQLITE?):
- Create a new table without the column that you're removing.
- Copy the data to the new table.
- Drop the original.
- Rename the copy.
ActiveRecord does this behind the scenes for you. Step (3) is where things are going wrong because you can't drop a table that is being referenced by foreign key constraints. I think you'll have handle the foreign key by hand: first use separate up
and down
methods, then modify the down
method to:
- Drop all the foreign keys that reference your table, you can use
remove_foreign_key
for this once you know what FKs you're dealing with. - Then
remove_column :skill_levels, :cooldown
as you have now. - And finally put all the FKs back, you can use
add_foreign_key
for this.
Something like:
def down
remove_foreign_key :some_table, :skill_levels
remove_column :skill_levels, :cooldown
add_foreign_key :some_table, :skill_levels
end
Ideally ActiveRecord would take care of this for you but presumably AR's SQLite support is mostly from before AR supported foreign key constraints.
推荐阅读
- apache-spark - 在 PySpark 上寻找更好的性能
- typescript - 带有 Typescript 的 React-Native 自定义文本组件:“将 React.ReactNode 类型转换为文本类型......”
- ibm-cloud - 为什么我在尝试创建存储时看到“经销商渠道 2c95500b-ea86-4b13-8bb5-b2f0c2fa8200 无效”错误
- graphql - Shopify GraphQL 以获取产品的交付率
- python - 切片 Django Queryset 字段值
- python - 如何在没有额外查询的情况下过滤反向相关字段?
- express - 上传到s3后如何返回文件位置
- qlikview - 使用服务器端扩展时,Qlik(查看或感知)过滤器在图表上显示数据(X 轴)
- bash - remove multiple line from /etc/hosts using augtool
- angular - How to test if a method is called when any unHandled exception occurs in jasmine