如何跳过失败的迁移? (耙数据库:迁移)

发布于 2024-12-26 07:08:03 字数 161 浏览 0 评论 0原文

我似乎找不到允许我跳过迁移的选项或任何内容。

我知道您在想什么:“您永远不必这样做......”

我需要跳过对我的开发数据库中不存在的特定用户记录进行更改的迁移。我不想更改迁移,因为它不是我应该使用的源的一部分。有没有办法跳过迁移或跳过失败的迁移?

提前致谢!

I can't seem to find an option or anything that allows me to skip migrations.

I know what you're thinking: "you should never have to do that..."

I need to skip a migration that makes changes to specific user records that don't exist in my development database. I don't want to change the migration because it is not part of the source I am supposed to be working with. Is there a way to skip a migration or skip failed migrations?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

将军与妓 2025-01-02 07:08:03

我认为您应该修复有问题的迁移,使其不那么脆弱,我猜几个 if 语句和也许 rescue 就足够了。

但是,如果确实无法修复迁移,您可以通过各种方式来伪造它。首先,您可以注释掉迁移方法,运行 rake db:migrate,然后取消注释(或恢复)有问题的迁移。

您也可以在数据库中伪造它,但不建议这样做,除非您知道自己在做什么并且不介意在(不可避免地)犯错误时手动修补。您的数据库中有一个名为 schema_migrations 的表,其中有一个名为 versionvarchar(255) 列; db:migrate 使用此表来跟踪已应用的迁移。您需要做的就是 INSERT 适当的 version 值,rake db:migrate 就会认为迁移已完成。找到有问题的迁移文件:

db/migrate/99999999999999_XXXX.rb

然后进入数据库并输入:

insert into schema_migrations (version) values ('99999999999999');

其中 99999999999999 当然是迁移文件名中的数字。然后运行 ​​rake db:migrate 应该跳过该迁移。

我会在第三个选项之前选择第二个选项,为了完整性,我只包含“hack schema_versions”选项。

I think you should fix the offending migrations to be less fragile, I'd guess that a couple of if statements and perhaps a rescue would be sufficient.

But, if fixing the migrations really isn't an option, you can fake it in various ways. First of all, you could just comment out the migration methods, run rake db:migrate, and then uncomment (or revert) the offending migration.

You can also fake it inside the database but this sort of chicanery is not recommended unless you know what you're doing and you don't mind manually patching things up when you (inevitably) make a mistake. There is a table in your database called schema_migrations that has a single varchar(255) column called version; this table is used by db:migrate to keep track of which migrations have been applied. All you need to do is INSERT the appropriate version value and rake db:migrate will think that the migration has been done. Find the offending migration file:

db/migrate/99999999999999_XXXX.rb

then go into your database and say:

insert into schema_migrations (version) values ('99999999999999');

where 99999999999999 is, of course, the number from the migration's file name. Then running rake db:migrate should skip that migration.

I'd go with the second option before the third, I'm only including the "hack schema_versions" option for completeness.

云淡风轻 2025-01-02 07:08:03

我遇到了一个问题,我需要进行迁移来添加已经存在的表,因此在我的情况下,我也必须跳过此迁移,因为我收到错误,

SQLite3::SQLException: table "posts" already exists: CREATE TABLE "posts"

我只是注释掉了创建表方法的内容,运行了迁移,然后取消注释。这是一种手动绕过它的方法,但它确实有效。见下文:

class CreatePosts < ActiveRecord::Migration
  def change
    # create_table :posts do |t|
    #   t.string :title
    #   t.text :message
    #   t.string :attachment
    #   t.integer :user_id
    #   t.boolean :comment
    #   t.integer :phase_id

    #   t.timestamps
    # end
  end
end

I had an issue where I had a migration to add a table that already existed, so in my case I had to skip this migration as well, because I was getting the error

SQLite3::SQLException: table "posts" already exists: CREATE TABLE "posts"

I simply commented out the content of the create table method, ran the migration, and then uncommented it out. It's kind of a manual way to get around it, but it worked. See below:

class CreatePosts < ActiveRecord::Migration
  def change
    # create_table :posts do |t|
    #   t.string :title
    #   t.text :message
    #   t.string :attachment
    #   t.integer :user_id
    #   t.boolean :comment
    #   t.integer :phase_id

    #   t.timestamps
    # end
  end
end
从来不烧饼 2025-01-02 07:08:03

这是解决一次性错误的好方法。

db:migrate:up VERSION=my_version

这将运行一个特定迁移的“up”操作。 (如果需要,也有相反的方法,只需将“向上”替换为“向下”即可。)因此,您可以运行未来的迁移,使旧的迁移(您需要跳过)工作,或者只运行每个迁移有选择地提前迁移。

我还相信您可以通过以下方式重做迁移:

rake db:migrate:redo VERSION=my_version

我个人还没有尝试过该方法,所以 YMMV。

This is a good way to do it for one-off errors.

db:migrate:up VERSION=my_version

This will run one specific migration's "up" actions. (There is also the opposite if you need it, just replace "up" with "down".) So this way you can either run the future migration that makes the older one (that you need to skip) work, or just run each migration ahead of it selectively.

I also believe that you can redo migrations this way:

rake db:migrate:redo VERSION=my_version

I have not tried that method personally, so YMMV.

旧话新听 2025-01-02 07:08:03

如果您必须这样做,您的应用程序的迁移就会变得混乱!

插入所有缺失的迁移:

def insert(xxx)
  ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{xxx})") rescue nil
end

files = Dir.glob("db/migrate/*")
files.collect { |f| f.split("/").last.split("_").first }.map { |n| insert(n) }

If you have to do that, your app's migrations are messed up!

Inserts all missing migrations:

def insert(xxx)
  ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{xxx})") rescue nil
end

files = Dir.glob("db/migrate/*")
files.collect { |f| f.split("/").last.split("_").first }.map { |n| insert(n) }
ぇ气 2025-01-02 07:08:03

要跳过所有挂起的迁移,请在终端中运行以下命令:(

echo "a = [" $(rails db:migrate:status | grep "down" | grep -o '[0-9]\{1,\}' | tr '\n' ', ') "];def insert(b);ActiveRecord::Base.connection.execute(\"insert into schema_migrations (version) values (#{b})\") rescue nil;end;a.map { |b| insert(b)}" | xclip

对于 macOS,请使用 pbcopy 而不是 xclip)

然后在 Rails 控制台中按 CTRL-V 查看结果:

a = [ 20180927120600,20180927120700 ];def insert(b);ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{b})") rescue nil;end;a.map { |b| insert(b)}

并按 ENTER 键。

您可以在执行该行之前从数组 a 中删除要跳过的迁移列表。

To skip all pending migrations, run this in your terminal:

echo "a = [" $(rails db:migrate:status | grep "down" | grep -o '[0-9]\{1,\}' | tr '\n' ', ') "];def insert(b);ActiveRecord::Base.connection.execute(\"insert into schema_migrations (version) values (#{b})\") rescue nil;end;a.map { |b| insert(b)}" | xclip

(For macOS use pbcopy instead of xclip)

Then CTRL-V the result inside rails console:

a = [ 20180927120600,20180927120700 ];def insert(b);ActiveRecord::Base.connection.execute("insert into schema_migrations (version) values (#{b})") rescue nil;end;a.map { |b| insert(b)}

And hit ENTER.

You can change the list of migrations you want to skip by removing them from array a before executing the line.

牵强ㄟ 2025-01-02 07:08:03

您可以通过添加一些 IF 来使迁移变得智能,而不是跳过迁移,这样您就可以检查“特定用户”

Instead of skip the migration you could make your migration smart, adding some IF to it, so you can check "specific users"

黑白记忆 2025-01-02 07:08:03

有时,有必要使用绝对正确的迁移重新填充schema_migrations表...
仅用于此目的我创建了此方法,

def self.insert_missing_migrations(stop_migration=nil)
  files = Dir.glob("db/migrate/*")
  timestamps = files.collect{|f| f.split("/").last.split("_").first}
  only_n_first_migrations = timestamps.split(stop_migration).first

  only_n_first_migrations.each do |version|
    sql = "insert into `schema_migrations` (`version`) values (#{version})"
    ActiveRecord::Base.connection.execute(sql) rescue nil
  end
end

您可以将其复制粘贴到您想要的任何模型中,并从控制台使用它

YourModel.insert_missing_migrations("xxxxxxxxxxxxxx")

(或其他方式)

,其中“xxxxxxxxxxxxxxx " - 是您想要停止插入之前的迁移时间戳(您可以将其留空)

!!!仅当您完全了解会得到什么结果时才使用它!!!

sometimes, it is necessary to re-fill schema_migrations table with definitely correct migrations...
ONLY FOR THIS PURPOSE i have created this method

def self.insert_missing_migrations(stop_migration=nil)
  files = Dir.glob("db/migrate/*")
  timestamps = files.collect{|f| f.split("/").last.split("_").first}
  only_n_first_migrations = timestamps.split(stop_migration).first

  only_n_first_migrations.each do |version|
    sql = "insert into `schema_migrations` (`version`) values (#{version})"
    ActiveRecord::Base.connection.execute(sql) rescue nil
  end
end

you can copy-paste it into any model you want and use it from console

YourModel.insert_missing_migrations("xxxxxxxxxxxxxx")

(or somehow else)

where "xxxxxxxxxxxxxx" - is timestamp of migration before which you want to stop insertion (you can leave it empty)

!!! use it only if you absolutely understand what result will you get !!!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文