我似乎无法找到允许我跳过迁移的选项或任何内容。
我知道你在想什么:“你永远不应该这样做......”
我需要跳过迁移,该迁移会更改我的开发数据库中不存在的特定用户记录。我不想更改迁移,因为它不是我应该使用的源代码的一部分。有没有办法跳过迁移或跳过失败的迁移?
提前致谢!
答案 0 :(得分:58)
我认为您应该将违规迁移修复为不那么脆弱,我猜这几个if
语句和rescue
就足够了。
但是,如果修复迁移确实不是一种选择,你可以用各种方式伪造它。首先,您可以注释掉迁移方法,运行rake db:migrate
,然后取消注释(或还原)违规迁移。
你也可以在数据库中伪造它,但是除非你知道你正在做什么,否则你不介意在你(不可避免地)犯错误的时候手动修补它时,不建议使用这种类型的chicanry。您的数据库中有一个名为schema_migrations
的表,其中有一个名为varchar(255)
的{{1}}列; version
使用此表来跟踪已应用的迁移。您需要做的就是插入适当的db:migrate
值,version
将认为迁移已完成。找到有问题的迁移文件:
rake db:migrate
然后进入你的数据库说:
db/migrate/99999999999999_XXXX.rb
其中insert into schema_migrations (version) values ('99999999999999');
当然是迁移文件名中的数字。然后运行99999999999999
应该跳过该迁移。
我会在第三个选项之前使用第二个选项,我只包括“hack rake db:migrate
”选项以获得完整性。
答案 1 :(得分:16)
我有一个问题,我有一个迁移来添加已经存在的表,所以在我的情况下我也不得不跳过这个迁移,因为我收到了错误
SQLite3::SQLException: table "posts" already exists: CREATE TABLE "posts"
我只是注释掉了create table方法的内容,运行了迁移,然后取消注释掉了。这是一种解决它的手动方式,但它有效。见下文:
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
答案 2 :(得分:15)
这是一次性错误的好方法。
db:migrate:up VERSION=my_version
这将运行一个特定迁移的“向上”操作。 (如果需要,也可以反过来,只需将“up”替换为“down”。)这样,您可以运行将来迁移,使旧版(需要跳过)工作,或者只运行每个有选择地进行迁移。
我也相信您可以通过这种方式重做迁移:
rake db:migrate:redo VERSION=my_version
我个人没有尝试过这种方法,所以YMMV。
答案 3 :(得分: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) }
答案 4 :(得分:1)
而不是跳过迁移,您可以使迁移变得智能,添加一些IF,这样您就可以检查“特定用户”
答案 5 :(得分:1)
有时,有必要使用绝对正确的迁移重新填充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")
(或其他方式)
其中"xxxxxxxxxxxxxx"
- 是您希望停止插入的迁移时间戳(您可以将其留空)
<强> !!!只有在你完全理解你会得到什么结果时才使用它!
答案 6 :(得分:0)
要跳过所有未完成的迁移,请在您的终端中运行此操作:
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 中删除它们来更改要跳过的迁移列表。