db:schema:load vs db:使用capistrano迁移

我有一个rails应用程序,我正在移动到另一台服务器,我想我应该使用db:schema:load来创建mysql数据库,因为它是推荐的。 我的问题是我正在使用capistrano进行部署,而似乎默认为rake db:migrate。 有没有办法改变这个或使用db:migrate的capistrano有充分理由?

为什么要使用db:schema:load

我发现我自己的迁移最终会对数据进行一些改组(例如,假设我将first_name和last_name列组合成一个full_name列)。 一旦我做了这些,我就开始使用ActiveRecord筛选数据库记录,你的模型最终会对某些列做出假设。 例如,我的“人员”表后来被赋予了一个“位置”列,用于对人员进行排序。 之前的迁移现在无法选择数据,因为“位置”列尚不存在。

如何更改Capistrano中的默认行为

总之,我相信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 

我的增强function是……

  • 将它包装在transaction do ,以便Capistrano在中止后进行适当的回滚。
  • 执行db:setup而不是db:schema:load ,这样如果数据库尚不存在,它将在加载模式之前创建。

这是Andres Jaan Tack的一个很好的答案。 我只是想补充几点意见。

首先,这是Andres deploy:load_schema的改进版本deploy:load_schema任务,其中包含警告,更重要的是使用bundle execRAILS_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的function请求deploy:load_schema在Capistrano中实现的deploy:load_schema 。 在该请求中,我注意到Capistrano讨论组已经讨论了’ db:schema:loaddb: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