【问题标题】:I can't rollback migrations, because the migration file does not exist我无法回滚迁移,因为迁移文件不存在
【发布时间】:2022-12-30 02:10:42
【问题描述】:
我在分支“add_dogs”中添加了迁移db/migrate/20221220155010_create_dogs.rb,并运行了db:migrate。
后来,我改变了分支(没有合并),最终放弃了“new_dogs”分支。
稍后,我用 db/migrate/20221101010101_create_cats.rb 查看了“add_cats” 分支,并运行了 db:migrate。到目前为止,一切都很好。
但后来我调整了“add_cats”迁移(在提交任何内容之前),并运行db:rollback,这样我就可以再次运行它。我收到此错误:
ActiveRecord::UnknownMigrationVersionError:
No migration with version number 20221220155010.
我仍然可以在新迁移上运行 db:migrate,但不能运行 db:rollback 或 db:migrate:redo。
这是有道理的,因为数据库有申请20221220155010的记录,但是那个迁移文件已经不存在了,所以没有办法回滚。
我怎样才能克服这个问题?
【问题讨论】:
标签:
ruby-on-rails
ruby
migration
rollback
【解决方案1】:
以下是处理丢失的迁移文件的三种方法,具体取决于您的需要和访问权限:
- 要进行快速临时修复,您可以只回滚当前正在编辑的迁移,以便再次运行它。如果另一个迁移仍在另一个分支的管道中并且最终将合并,这可能很有用。
rake db:migrate:down VERSION=20230101010101
// This is the version of the migration you WANT to rollback, not the missing one.
- 如果丢失的迁移永远不会回来,您需要永久修复。最简单的方法是从数据库中删除该记录。您可以从您最喜欢的 SQL 客户端、rails 控制台等执行此操作(我想您甚至可以编写迁移来执行此操作,但这似乎强大的粗略。)
DELETE FROM schema_migrations WHERE version = '20221220155010'
-- This is the version of the migration that is MISSING, not the one you are working on.
- 如果您出于某种原因不能直接访问数据库,您可以给 Rails 一个安慰剂来回滚。确保文件名中的时间戳与丢失的迁移版本号相匹配。
创建一个名为db/migrations/20221220155010_just_kidding.rb的文件:
class JustKidding < ActiveRecord::Migration
def change
# nothing to see here.
end
end
然后,rails db:rollback 将回滚该无操作迁移并从 schema_migrations 表中删除 20221220155010。您现在可以永远删除安慰剂迁移,就运行迁移和回滚而言,您将处于良好状态。
然而……别忘了效果的旧迁移仍在您的架构中。也许你被一个新的、未使用的“狗”表或表上的额外列所困扰。也许这对您的开发箱来说是良性的,但您肯定不希望在生产环境中出现这种情况。此答案中的所有建议都假设您处于一次性环境中,并且旧迁移的影响不是问题。在这种情况下,拆除整个数据库并重建可能会成为一个更有吸引力的选择。
这里真正的收获之一是……首先不要让这种情况发生!理想情况下,您应该在离开分支之前回滚任何新的、未提交的迁移。但是……事情发生了……
附:如果有一种方法可以从命令行执行此操作,我很乐意学习它。我在想 rails db:migrate:delete VERSION=20230101010101 之类的东西可能会以一种骇人听闻的方式派上用场。