【问题标题】:db:schema:load vs db:migrate with capistranodb:schema:load vs db:migrate with capistrano
【发布时间】:2009-08-25 17:36:17
【问题描述】:

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

【问题讨论】:

  • 您用于部署到新服务器的上限任务是什么?

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


【解决方案1】:

为什么要使用 db:schema:load

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

如何更改 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

【讨论】:

  • 这很棒。我按照这种格式更改了我的冷部署。但是,我使用了 Multistage-Extension,所以我在 rake 之后添加了一个“RAILS_ENV=${rails_env}”。同样对于我的暂存环境,我想重新加载架构,所以我在其中添加了一个 rake db:drop 和一个 rake db:create。
  • @Howler,我也是这么做的。 :)
  • 警告:这是旧的。请参阅 Cap 3.x 或更高版本的答案。
【解决方案2】:

爬上 Andres Jaan Tack、Adam Spiers 和 Kamiel Wanrooij 的肩膀,我构建了以下任务来覆盖 deploy:cold。

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

【讨论】:

  • 警告:这是旧的。请参阅 Cap 3.x 或更高版本的答案。
【解决方案3】:

Andres Jaan Tack 给出了很好的回答。我只是想添加一些 cmets。

首先,这是 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 在技术上是更好的方法,因此如果可以降低意外数据丢失的风险,那么值得转换。

【讨论】:

  • 在任务开头添加raise RuntimeError.new('load_schema aborted!') unless Capistrano::CLI.ui.ask("Are you sure to wipe the entire database (anything other than 'yes' aborts):") == 'yes' 就像一个魅力!这感觉足够安全,也可以修补 deploy:cold。
  • 好主意,卡米尔!我刚刚added your suggestion to the github issue
  • 警告:这是旧的。请参阅 Cap 3.x 或更高版本的答案。
【解决方案4】:

在 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:db_setup 987654324@.

要执行 db:schema:load 而不是 db:setup,您可以简单地更改 rake 任务,如下所示:

desc 'Load DB Schema'
task :db_schema_load do
  ...
        execute :rake, 'db:schema:load'
  ...
end

【讨论】:

  • 谢谢。这工作得很好。虽然我不可能简单地运行deploy:db_setup,因为服务器上还没有我的应用程序的副本(据我所知,第一次部署将为此做好准备)。我很奇怪 Cap​​istrano 没有满足这个要求的默认任务......
猜你喜欢
  • 2012-05-05
  • 2013-09-30
  • 2016-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-08
相关资源
最近更新 更多