我运行了以下迁移,但忘记包含我想要的默认值。我正在尝试将其回滚,以便我可以添加默认值并再次向前滚动。
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:rollback
== 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 数据库:迁移
== 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
感谢您的帮助。
最佳答案
错误:
FOREIGN KEY constraint failed: DROP TABLE "skill_levels"
告诉您有一个外键约束引用您的 skill_levels
表(即其他迁移中的 t.references :skill_levels,foreign_key: true
),并且remove_column :skill_levels, :cooldown
导致了这个问题。
但是为什么在 ALTER TABLE 删除列期间数据库约束会成为问题呢?好吧,SQLite 的 ALTER TABLE doesn't support removing a column ,相反,您必须(请参阅 SQLite 常见问题解答或 How to delete or add column in SQLITE? ):
- 创建一个新表,其中不包含要删除的列。
- 将数据复制到新表。
- 删除原件。
- 重命名副本。
ActiveRecord 在幕后为您完成此操作。步骤 (3) 是出现问题的地方,因为您无法删除由外键约束引用的表。我认为您将手动处理外键:首先使用单独的 up
和 down
方法,然后将 down
方法修改为:
- 删除引用您的表的所有外键,您可以使用
remove_foreign_key
一旦你知道你正在面对的是什么 FK,就可以做到这一点。 - 然后像现在一样
remove_column :skill_levels, :cooldown
。 - 最后把所有的FK都放回去,可以用
add_foreign_key
为此。
类似于:
def down
remove_foreign_key :some_table, :skill_levels
remove_column :skill_levels, :cooldown
add_foreign_key :some_table, :skill_levels
end
理想情况下,ActiveRecord 会为您处理这个问题,但大概 AR 的 SQLite 支持主要来自 AR 支持外键约束之前。
关于ruby-on-rails - 我如何回滚这个 Rails 迁移?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57242929/