2012-01-10 86 views
31

我似乎无法找到一个选项或任何允许我跳过迁移。如何跳过失败的迁移? (耙分贝:迁移)

我知道你在想什么:“你永远不应该这样做......”

我需要跳过迁移,使那些没有在我的开发数据库中更改为特定用户记录。我不想更改迁移,因为它不属于我应该与之合作的来源。有没有办法跳过迁移或跳过失败的迁移?

在此先感谢!

回答

53

我认为你应该修复有问题的迁移,以减少脆弱性,我猜想几个if声明,也许rescue就足够了。

但是,如果修改迁移确实不是一个选项,那么可以用各种方法来伪造它。首先,您可以评论迁移方法,运行rake db:migrate,然后取消(或恢复)违规迁移。

您也可以伪造它的数据库,但这种欺骗的内部不推荐,除非你知道自己在做什么,你不介意手动修补的东西,当你(难免)犯了一个错误。数据库中有一个名为schema_migrations的表,其中有一个varchar(255)列,名为version;此表由db:migrate用于跟踪已应用哪些迁移。您所需要做的就是插入适当的version值,并且rake db:migrate会认为迁移已完成。找到问题的迁移文件:

db/migrate/99999999999999_XXXX.rb 

然后进入你的数据库,并说:

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

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

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

+0

雅,我只是说干就干,暂时切断了违规迁移。我个人会创建适当的If语句或只是检查生产环境,但显然,处理迁移的人不相信使用db:migrate while developing = P谢谢 – hmind 2012-01-10 23:11:25

+0

@hmind:“处理迁移不相信在开发时使用db:migrate“。天啊。发布到您的生产系统必须是一个超级开心的乐趣! – 2012-01-10 23:30:28

+2

幸运的是,我不处理这个要么是haha – hmind 2012-01-11 00:20:59

1

而不是跳过,你可以让你的智能迁移的迁移,增加了一些IF它,所以你可以检查“特定用户”

+0

是的,如果我已经写了迁移,我会这样做。但是我没有,我也不想真的想把我不应该碰到的部分源头搞砸,所以我最终只是暂时将它们剪掉。 – hmind 2012-01-10 23:12:34

14

这是做了一个关闭错误的好办法。

db:migrate:up VERSION=my_version

这将运行一个特定迁移的 “向上” 的行动。 (如果您需要它,也可以相反,只需将“up”替换为“down”)。因此,您可以通过这种方式运行将来的迁移,使旧的迁移(需要跳过)工作,或者运行每个迁移有选择地在它之前进行迁移

我也相信你可以重做迁移这种方式:

rake db:migrate:redo VERSION=my_version

我没有尝试过这种方法个人,所以因人而异。

1

有时,有必要重新填写schema_migrations绝对正确迁移 ... ONLY FOR为此我创造了这个方法

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") 

(或者以某种方式)

其中"xxxxxxxxxxxxxx" - 是您要停止插入其迁移前的时间戳(你可以让它空)

!只有当你完全理解你会得到什么结果时才使用它!

10

我有一个问题,我有一个迁移添加已经存在了,所以在我的情况,我不得不跳过此迁移以及表,因为我得到的错误

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

我只是注释掉create table方法的内容,运行迁移,然后取消注释。这是一种手动的方式来解决它,但它的工作。见下:

​​
+0

这真是太好了!不敢相信我没有想到这一点。完全合作。 – helpse 2017-11-16 15:25:43

7

如果你必须这样做,你的应用程序的迁移是搞砸了!

插入所有丢失的迁移:

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) } 
+1

不一定。例如,如果您将生产数据库pg_restore复制到开发计算机,以解决生产数据的问题。当你没有所有的信息时,不要那么快地告诉别人他们做错了。 – 2016-09-08 18:21:19

+0

@MikeBethany:在我的情况下,当我不得不使用它时,一切都变得非常混乱,我没有时间去理解它为什么会这样。关于pg_restore,它也应该恢复'schema_migrations'表,我猜对吧? – Dorian 2016-09-09 11:21:20

+0

是的,当然,'schema_migrations'表只是数据库中的一个表。重新阅读你的标题我可以看到另一种解释。我原本是这样读的,“你没有正确写出你的迁移。”我认为你的意思是,“迁移有问题。”但这是显而易见的,因此这个问题,所以我认为“你搞砸了”的含义。我的错。 – 2016-09-11 15:20:52