2012-01-10 148 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