在 Rails 上使用 Ruby 处理失败迁移的最佳策略
Best tactics to deal with failed migration using Ruby on Rails
希望你们一切都好
我将我的一个旧项目(正在生产中)从 Github 克隆到我的新 MacBook 运行 Big Sur。我想处理新功能和更新,但我总是遇到一些迁移错误。
据我所知,我们不应该删除任何迁移文件。那么修复这些错误的最佳做法是什么?
- 我应该删除、编辑导致问题的迁移文件吗?
- 我是否应该删除相关的 gem 以及迁移文件并重新安装?
- 还有其他建议吗?
谢谢!
% 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:setup
做 db: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 会发现该列已经存在于数据库中,不做任何更改)。
因此,如果您发现之前的提交错误地损坏了旧迁移,修复损坏可能是一个方便的解决方案。但是请自行判断。
希望你们一切都好
我将我的一个旧项目(正在生产中)从 Github 克隆到我的新 MacBook 运行 Big Sur。我想处理新功能和更新,但我总是遇到一些迁移错误。
据我所知,我们不应该删除任何迁移文件。那么修复这些错误的最佳做法是什么?
- 我应该删除、编辑导致问题的迁移文件吗?
- 我是否应该删除相关的 gem 以及迁移文件并重新安装?
- 还有其他建议吗?
谢谢!
% 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:setup
做 db: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 会发现该列已经存在于数据库中,不做任何更改)。
因此,如果您发现之前的提交错误地损坏了旧迁移,修复损坏可能是一个方便的解决方案。但是请自行判断。