Иногда возникает ситуация, когда необходимо получить production базу к себе, для разработки и тестирования.
Я написал, как часть гема этот рецепт, сейчас работает только если база на production и development одна и та же (в нашем случае postgresql). При желании можно добавить и другие базы.
Для этой цели (как и для других) нам отлично подойдет Capistrano.
Для того, чтобы использовать рецепт необходимо установить 7zip на сервере и локальной машине:
sudo apt-get --assume-yes install p7zip-full
Добавить этот код в Capfile:
…
mac_os = `uname -a`.include?("Darwin")
run_local_sudo_psql = mac_os ? "psql -h localhost -U postgres" : "#{sudo} -u postgres psql"
run_local_psql = mac_os ? "psql -h localhost" : "psql"
config = YAML::load(File.open("config/database.yml"))
adapter = config[rails_env]["adapter"]
database = config[rails_env]["database"]
db_username = config[rails_env]["username"]
db_password = config[rails_env]["password"]
local_rails_env = 'development'
local_adapter = config[local_rails_env]["adapter"]
local_database = config[local_rails_env]["database"]
local_db_username = config[local_rails_env]["username"]
local_db_password = config[local_rails_env]["password"]
set :local_folder_path, "tmp/backup" # you can set where to store *.sql.7z files on dev machine
set :timestamp, Time.now.to_i # timestamp in seconds
set :db_file_name, "#{database}-#{timestamp}.sql" # etc. app_production-1332404980.sql
set :db_archive_ext, "7z"
namespace :db do
task :backup do
file_name = fetch(:db_file_name)
archive_ext = fetch(:db_archive_ext)
dump_file_path = "#{shared_path}/backup/#{file_name}"
output_file = "#{dump_file_path}.#{archive_ext}"
run "mkdir -p #{shared_path}/backup"
if adapter == "postgresql"
run %{export PGPASSWORD="#{db_password}" && pg_dump -U #{db_username} #{database} > #{dump_file_path}}
run "cd #{shared_path} && 7z a #{output_file} #{dump_file_path} && rm #{dump_file_path}"
else
puts "Cannot backup, adapter #{adapter} is not implemented for backup yet"
end
system "mkdir -p #{local_folder_path}"
download(output_file, "#{local_folder_path}/#{file_name}.#{archive_ext}")
end
task :import do
file_name = "#{db_file_name}.#{db_archive_ext}"
file_path = "#{local_folder_path}/#{file_name}"
if local_adapter == "postgresql"
system "cd #{local_folder_path} && 7z x #{file_name}"
system %{echo "drop database #{local_database}" | #{run_local_sudo_psql}}
system %{echo "create database #{local_database} owner #{local_db_username};" | #{run_local_sudo_psql}}
puts "ENTER your development password: #{local_db_password}"
system "#{run_local_psql} -U#{local_db_username} #{local_database} < #{local_folder_path}/#{db_file_name}"
system "rm #{local_folder_path}/#{db_file_name}"
else
puts "Cannot import, adapter #{local_adapter} is not implemented for backup yet"
end
end
task :pg_import do
if adapter == local_adapter
db.backup
db.import
else
puts "Sorry, but development and production adapters must be equals"
end
end
end
Как это работает:
cap db:pg_import
- создает на сервере папку "#{project_name}/shared/backup"
- делает дамп production базы в эту папку, архивирует ее 7zip
- передает по ssh на локальную машину в папку проекта 'tmp/backup'
- разархивирует и импортирует в девелоперскую базу ВАЖНО: перед этим делая DROP текущей локальной базы
Автор: qwlk