![](/img/trans.png)
[英]Rails Schema changes unintentionally whenever I run rake db:migrate
[英]db:schema:load vs db:migrate with capistrano
我有一個rails應用程序,我正在移動到另一台服務器,我想我應該使用db:schema:load來創建mysql數據庫,因為它是推薦的。 我的問題是我使用capistrano進行部署,而且似乎默認為rake db:migrate。 有沒有辦法改變這個或使用db:migrate的capistrano有充分理由?
我發現我自己的遷移最終會對數據進行一些改組(例如,假設我將first_name和last_name列組合成一個full_name列)。 一旦我做了這些,我就開始使用ActiveRecord篩選數據庫記錄,你的模型最終會對某些列做出假設。 例如,我的“人員”表后來被賦予了一個“位置”列,用戶可以對其進行排序。 之前的遷移現在無法選擇數據,因為“位置”列尚不存在。
總之,我相信deploy:cold
應該使用db:schema:load
而不是db:migrate
。 我通過改變Capistrano在冷部署上執行的中間步驟解決了這個問題。 對於Capistrano v2.5.9,庫代碼中的默認任務如下所示。
namespace :deploy do
...
task :cold do
update
migrate # This step performs `rake db:migrate`.
start
end
...
end
我在deploy.rb
覆蓋了任務,如下所示。
namespace :deploy do
task :cold do # Overriding the default deploy:cold
update
load_schema # My own step, replacing migrations.
start
end
task :load_schema, :roles => :app do
run "cd #{current_path}; rake db:schema:load"
end
end
爬上Andres Jaan Tack,Adam Spiers和Kamiel Wanrooij的肩膀,我已經建立了以下任務來覆蓋部署:冷。
task :cold do
transaction do
update
setup_db #replacing migrate in original
start
end
end
task :setup_db, :roles => :app do
raise RuntimeError.new('db:setup aborted!') unless Capistrano::CLI.ui.ask("About to `rake db:setup`. Are you sure to wipe the entire database (anything other than 'yes' aborts):") == 'yes'
run "cd #{current_path}; bundle exec rake db:setup RAILS_ENV=#{rails_env}"
end
我的改進是......
transaction do
,以便Capistrano在中止后進行適當的回滾。 db:setup
而不是db:schema:load
,這樣如果數據庫尚不存在,它將在加載模式之前創建。 這是Andres Jaan Tack的一個很好的答案。 我只是想補充幾點意見。
首先,這是Andres deploy:load_schema
的改進版本deploy:load_schema
任務,其中包含警告,更重要的是使用bundle exec
和RAILS_ENV
來確保正確設置環境:
namespace :deploy do
desc 'Load DB schema - CAUTION: rewrites database!'
task :load_schema, :roles => :app do
run "cd #{current_path}; bundle exec rake db:schema:load RAILS_ENV=#{rails_env}"
end
end
我已經提交了一個要deploy:load_schema
的功能請求deploy:load_schema
在Capistrano中實現的deploy:load_schema
。 在該請求中,我注意到Capistrano討論組已經討論了' db:schema:load
與db:migrate
'的爭論 ,並且有些人不願意將deploy:cold
任務切換為使用db:schema:load
over db:migrate
,因為如果無意中運行,前者會破壞整個數據庫,而后者可能會無害地抱怨和保釋。 然而db:schema:load
在技術上是更好的方法,因此如果可以減輕意外數據丟失的風險,那么值得切換。
在Capistrano 3 / Rails 4中,默認部署語法已更改。 你可以這樣做:
desc 'Deploy app for first time'
task :cold do
invoke 'deploy:starting'
invoke 'deploy:started'
invoke 'deploy:updating'
invoke 'bundler:install'
invoke 'deploy:db_setup' # This replaces deploy:migrations
invoke 'deploy:compile_assets'
invoke 'deploy:normalize_assets'
invoke 'deploy:publishing'
invoke 'deploy:published'
invoke 'deploy:finishing'
invoke 'deploy:finished'
end
desc 'Setup database'
task :db_setup do
on roles(:db) do
within release_path do
with rails_env: (fetch(:rails_env) || fetch(:stage)) do
execute :rake, 'db:setup' # This creates the database tables AND seeds
end
end
end
end
如果您在:cold
任務中手動調用標准部署任務(因為它們可能在即將發布的版本中更改,或者如果您有自定義部署任務),則還可以在運行deploy
之前調用deploy:db_setup
。
要執行db:schema:load
而不是db:setup
,您只需更改rake任務,如下所示:
desc 'Load DB Schema'
task :db_schema_load do
...
execute :rake, 'db:schema:load'
...
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.