ruby-on-rails - 我如何回滚这个 Rails 迁移?

标签 ruby-on-rails sqlite ruby-on-rails-5 rails-migrations

我运行了以下迁移,但忘记包含我想要的默认值。我正在尝试将其回滚,以便我可以添加默认值并再次向前滚动。

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? ):

  1. 创建一个新表,其中不包含要删除的列。
  2. 将数据复制到新表。
  3. 删除原件。
  4. 重命名副本。

ActiveRecord 在幕后为您完成此操作。步骤 (3) 是出现问题的地方,因为您无法删除由外键约束引用的表。我认为您将手动处理外键:首先使用单独的 updown 方法,然后将 down 方法修改为:

  1. 删除引用您的表的所有外键,您可以使用 remove_foreign_key一旦你知道你正在面对的是什么 FK,就可以做到这一点。
  2. 然后像现在一样remove_column :skill_levels, :cooldown
  3. 最后把所有的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/

相关文章:

ruby-on-rails-5 - AWS EBS - Rails5/nginx - robots.txt 未找到错误 (404)

ruby-on-rails - 测试配方 : How to test a ruby gem with rails dependencies

ruby-on-rails - Rails 4、ImageMagick 和 PaperClip

ruby-on-rails - ActiveAdmin 如何使用关联对列进行排序

ruby-on-rails - 尝试扩展 ActionView::Helpers::FormBuilder

ruby-on-rails - 将 Rails 应用程序部署到 heroku 错误(sqlite3->Postgresql)?

ruby-on-rails-4 - PG::ConnectionBad:将 rails 从 4.2 升级到 5.2 后连接关闭

Ruby-on-rails Postgres 查询

sqlite - 在 phonegap 存储中创建 2 个或更多表

iphone - 我怎样才能用翻译实现字典