【发布时间】:2015-12-04 10:00:51
【问题描述】:
我们的旧版 Rails 应用有一些损坏的迁移(因此我们滚动迁移)到一个大型迁移中,为它编写了一个 rake 任务,一切都很好。
desc "Removes all schema migrations and inserts the migration reconstruction"
task reconstruct_migrations: :environment do
reconstruction_migration = Dir["db/migrate/*.rb"].find { |migration| migration =~ /reconstruct_database/ }
file_name = reconstruction_migration.split("/").last
timestamp = file_name.split("_").first
puts ">> Resetting migration version to #{timestamp}"
ActiveRecord::Base.transaction do
ActiveRecord::Base.connection.tap do |c|
c.execute("DELETE FROM schema_migrations")
c.execute("INSERT INTO schema_migrations(version) VALUES ('#{timestamp}')")
end
end
end
这有点不正统,但它是大型遗留应用程序,这就是情况。然而,即使在重建我的迁移之后,在运行新的迁移时它也会失败,因为现有的 MySQL 转储将有一个冲突的 schema_migrations 表。它的版本列包含所有先前的迁移时间戳,如下所示:
+----------------+
| version |
+----------------+
| 20081121002510 |
| 20081124055648 |
| 20081124102955 |
| 20081124103008 |
etc....
要解决我的情况,我需要用我的 rails 应用程序中的当前时间戳覆盖此版本列的值。它们是:
200507121201
20151111084520
20151117071001
桌子:
mysql> show columns from schema_migrations;
+---------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| version | varchar(255) | NO | PRI | NULL | |
+---------+--------------+------+-----+---------+-------+
1 row in set (0.00 sec)
我尝试解决这个问题:
mysql> UPDATE `schema_migrations` SET `version` = '';
ERROR 1062 (23000): Duplicate entry '' for key 'unique_schema_migrations'
mysql> alter table schema_migrations drop column version;
ERROR 1090 (42000): You can't delete all columns with ALTER TABLE; use DROP TABLE instead
所以总而言之,我该如何覆盖此列中的现有值并将它们替换为上面列出的 3 个?
【问题讨论】:
-
我不明白。为什么不直接在转储中删除迁移表并再次运行迁移?此外,如果您有很多迁移,则无需保留它们。无论如何,你永远不会回滚那么远。
-
感谢您的建议。所以你是说我可以删除
schema_migrations表,重新运行迁移,它会正确地重新填充它? -
是的,如果您将所有之前的迁移都放在一个迁移文件中。但是再次查看您的代码似乎并非如此。
标签: mysql ruby-on-rails database activerecord