DB: схема: нагрузка против DB: мигрировать с Capistrano - PullRequest
22 голосов
/ 25 августа 2009

У меня есть приложение rails, которое я перемещаю на другой сервер, и я решил использовать db: schema: load для создания базы данных mysql, потому что это рекомендуется. Моя проблема в том, что я использую capistrano для развертывания, и вместо этого по умолчанию используется rake db: migrate. Есть ли способ изменить это или capistrano использует db: migrate по уважительной причине?

Ответы [ 4 ]

32 голосов
/ 29 октября 2009

Зачем использовать db: схема: нагрузка

Я обнаружил, что мои собственные миграции в конечном итоге делают некоторую перестановку данных (например, я объединяю столбцы 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
10 голосов
/ 13 июля 2012

Взобравшись на плечи Андреса Яана Така, Адама Спирса и Камиэля Ванрооиджа, я построил следующую задачу для перезаписи развертывания: 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, поэтому, если база данных еще не существует, она будет создана перед загрузкой схемы.
6 голосов
/ 18 мая 2012

Это отличный ответ от Андреса Яана Така. Я просто хотел добавить несколько комментариев.

Во-первых, вот улучшенная версия задачи Андреса 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 в Capistrano . В этой просьбе я отметил, что дискуссия db:schema:load против db:migrate уже обсуждалась в дискуссионной группе Capistrano , и было некоторое нежелание переключить задачу deploy:cold на использование db:schema:load сверх db:migrate, поскольку при непреднамеренном запуске первый уничтожает всю базу данных, а второй, вероятно, будет жаловаться и безнаказанно освобождать под залог. Тем не менее, с технической точки зрения db:schema:load является лучшим подходом, поэтому, если риск случайной потери данных может быть уменьшен, его стоит заменить.

3 голосов
/ 03 августа 2014

В 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 перед запуском deploy.

Чтобы выполнить db:schema:load вместо db:setup, вы можете просто изменить задачу rake, например:

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