Подтвердить что ты не робот

Db: schema: load vs db: migrate with capistrano

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

4b9b3361

Ответ 1

Зачем использовать 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

Ответ 2

Поднявшись на плечи Андреса Яана Тэка, Адама Спирса и Камиэля Ваньюоя, я создал следующую задачу, чтобы перезаписать развертывание: холодно.

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, поэтому, если база данных еще не существует, она будет создана до загрузки схемы.

Ответ 3

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

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

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

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

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