[英]How to know that a rake task has been run in rails?
我在Rails應用程序中進行了遷移,僅當運行了特定的rake任務時,我才想運行它,否則會丟失大量數據。 以下是我想做的事情:
if has_rake_task_been_run?
remove_column :transactions, :paid_by
end
目前,無論如何我都找不到,只能手動確保這一點。 有什么解決辦法嗎?
使用rake任務進行數據遷移是一個極具風險的想法。 不這樣做的幾個原因:
即使您設法找出您的rake任務是否已經完成,您的遷移仍將標記為已完成,並且您將無法重播它。 唯一的辦法就是在遷移中引發異常。
不,您也將無法回滾該遷移。 如果運行遷移后rake任務完成,則回滾將嘗試添加已經存在的列。
新開發人員從頭開始建立數據庫將變得很痛苦,因為他們將需要知道什么時間運行哪些rake任務。 rake db:migrate
執行所有遷移。
您正在用不可重復使用的任務污染耙任務列表
看來您正在做的只是定期的數據遷移,因此rake任務完成的所有工作實際上應該是遷移的一部分。 這甚至可以使您進行可逆的數據遷移(大多數情況下)。
但是請注意,數據遷移並不像常規的僅方案遷移那樣簡單。 因為您的遷移應該完全獨立於代碼(即使將來完全使用遷移模型,即使將來從代碼庫中完全刪除它們),所以重新定義要在遷移中使用的模型是一種慣例。 (只有遷移所需的位)。 聽起來很簡單,不幸的是,老實說,我仍在尋找完美的解決方案。 到目前為止,我所見過的最好的方法很簡單(我假設paid_by
以前是字符串,而您將其更改為paid_by_id
,它引用了用戶):
class YOURMIGRATIONNAME < ActiveRecord::Migration
class Transaction < ActiveRecord::Base
belongs_to :paid_by, class_name: "User"
end
class User < ActiveRecord::Base
end
def up
add_column :transaction, :paid_by_id, :integer
Transaction.transaction do # for speed
Transaction.find_each do |t|
t.paid_by_id = User.find_by(username: t[:paid_by])
t.save! # Always banged save in migration!
end
end
remove_column :paid_by
end
def down
add_column :transaction, :paid_by, :string
Transactions.transaction do
Transaction.find_each do |t|
t[:paid_by] = t.paid_by && t.paid_by.username
t.save!
end
end
remove_column :transactions, :paid_by_id
end
使用上面的代碼的唯一缺點是,如果其中任何一個模型正在使用STI,它都將無法正常工作(我曾經犯過一次錯誤,花了一段時間才能找出問題所在)。 解決方法是在遷移類之外定義它,但是這些類在所有遷移中都可用,並且可能會受到實際模型代碼的影響(尤其是在預加載所有模型的情況下,在生產中)。 簡而言之,我目前仍在研究使用STI進行數據遷移。
萬一有人來了,我們成功地使用了after_party rails庫。 通過簡單的機制,該庫可以維護已執行的rake任務,並且可以輕松執行遷移任務。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.