在 Rails 上使用 Ruby 处理失败迁移的最佳策略

Best tactics to deal with failed migration using Ruby on Rails

希望你们一切都好

我将我的一个旧项目(正在生产中)从 Github 克隆到我的新 MacBook 运行 Big Sur。我想处理新功能和更新,但我总是遇到一些迁移错误。

据我所知,我们不应该删除任何迁移文件。那么修复这些错误的最佳做法是什么?

谢谢!

  % bin/rails db:migrate RAILS_ENV=development
    ** Invoke db:migrate (first_time)
    ** Invoke environment (first_time)
    ** Execute environment
    ** Invoke db:load_config (first_time)
    ** Execute db:load_config
    ** Execute db:migrate
    == 20171118122416 AddTaggingsCounterCacheToTags: migrating ====================
    -- add_column(:tags, :taggings_count, :integer, {:default=>0})
       -> 0.0521s
    rails aborted!
    StandardError: An error has occurred, this and all later migrations canceled:
    
    uninitialized constant AddTaggingsCounterCacheToTags::ActsAsTaggableOn

不,您不应该删除迁移,根据 rails 自己的建议,您最好 运行 bin/rails db:schema:load 在已经存在的旧项目上创建新数据库迁移

https://github.com/rails/rails/blob/main/actionmailbox/test/dummy/db/schema.rb#L5-L9

This file is the source Rails uses to define your schema when running bin/rails db:schema:load. When creating a new database, bin/rails db:schema:load tends to be faster and is potentially less error prone than running all of your migrations from scratch. Old migrations may fail to apply correctly if those migrations use external dependencies or application code.

注意 rails db:setupdb:create, db:schema:load, db:seed 这在设置项目时很有用

一般使用db:schema:load

即可

通常最好的解决方案是 运行 bin/rails db:schema:load,正如@Mshka 所说。

但对于一些潜在的灵感,这里有一个案例研究,其中一个旧的迁移文件已被删除(禁止)并且我恢复了它以便我可以 运行 db:migrate 一次再次...

案例研究:恢复已删除的迁移

在此示例中,一位同事无缘无故地删除了旧迁移(可能是意外),因此 db:migrate 不再在开发中的空数据库上工作。然而,在从旧提交中追踪删除的迁移文件后,简单地重新添加该迁移文件会出现一个新问题:迁移现在在生产中失败,因为迁移添加的列已经存在于生产中。在我的案例中效果很好的解决方案是从

修改旧迁移
class AddContigFileidToSubmissions < ActiveRecord::Migration[4.2]
  def change
    add_column :submissions, :contig_fileid, :string
  end
end

class AddContigFileidToSubmissions < ActiveRecord::Migration[4.2]
  def self.up
    if !column_exists?(:submissions, :contig_fileid)
      add_column :submissions, :contig_fileid, :string
    end
  end

  def self.down
    remove_column :submissions, :contig_fileid
  end
end

这允许 db:migrate 在开发中的空数据库上再次工作(现在正确添加了该列),并且迁移在部署到生产时继续工作(其中 Rails 会发现该列已经存在于数据库中,不做任何更改)。

因此,如果您发现之前的提交错误地损坏了旧迁移,修复损坏可能是一个方便的解决方案。但是请自行判断。