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

时间:2009-08-25 17:36:17

标签: mysql ruby-on-rails database rake capistrano

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

4 个答案:

答案 0 :(得分:32)

为什么要使用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

答案 1 :(得分:10)

爬上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,这样如果数据库尚不存在,则会在加载架构之前创建它。

答案 2 :(得分:6)

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

首先,这是Andres'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

我已提交a feature request to have deploy:load_schema implemented in Capistrano。在该请求中,我注意到the 'db:schema:load vs. db:migrate' debate has already been covered in the Capistrano discussion group,并且有些人不愿意将deploy:cold任务切换为使用db:schema:load而不是db:migrate,因为如果无意中运行,前者会将整个数据库,而后者可能会无害地抱怨和保释。然而db:schema:load在技术上是更好的方法,因此如果可以减轻意外数据丢失的风险,那么值得转换。

答案 3 :(得分:3)

在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任务中手动调用标准部署任务(因为它们可能会在即将发布的版本中更改,或者您有自定义部署任务),您也可以简单地调用{{ 1}}在运行deploy:db_setup之前。

要执行deploy而不是db:schema:load,您只需更改佣金任务,就像这样:

db:setup