Capistrano Copying your Production data to your Staging environment

Posted by dave
on Friday, November 06

Here’s a quick bit of capistrano to copy your production data into your staging environment if you’re running a multi-stage setup:

desc "Loads the production database and assets into the staging environment" 
task :load_production_data, :roles => :app do
  require 'yaml'
  # get the database.yml file from the server
  production_yml = "config/database.production#{Time.now.strftime '%Y-%m-%d_%H:%M:%S'}.yml" 
  staging_yml = "config/database.staging#{Time.now.strftime '%Y-%m-%d_%H:%M:%S'}.yml" 

  begin
    get "/path/to/your/production/current/config/database.yml", production_yml
    get "#{current_path}/config/database.yml", staging_yml

    # load the values
    p_config = YAML::load_file(production_yml)
    username = p_config['production']['username']
    password = p_config['production']['password']
    database = p_config['production']['database']
    s_config = YAML::load_file(staging_yml)
    s_username = s_config['staging']['username']
    s_password = s_config['staging']['password']
    s_database = s_config['staging']['database']
  rescue
    raise
  ensure
    `rm -f #{production_yml};rm -f #{staging_yml}`
  end

  # copy the SQL data
  filename = "/tmp/dump.#{Time.now.strftime '%Y-%m-%d_%H:%M:%S'}.sql.gz" 
  run "mysqldump -u #{username} --password='#{password}' #{database} | gzip > #{filename}" 
  run "gunzip -c #{filename} | mysql -u #{s_username} --password='#{s_password}' #{s_database} && rm -f gunzip #{filename}" 

  # Copy media files under system  
  run "cp -Rf /path/to/your/production/current/public/system/* #{current_path}/public/system/" 
end

Seems to work alright for us – remember that you may need to re-apply database migrations using cap deploy:migrate in case your staging database is ahead of your production database.

Re-saving ActiveRecord Objects Rake Task

Posted by dave
on Thursday, October 29

A quick rake task to allow you to quickly re-save all objects in a model class (maybe you’ve added some new code in an ActiveRecord filter and need to run the code on existing persisted objects).

namespace :db do
  desc "Resave all objects in a model class." 
  task :resave_objects => :environment do
    raise 'USAGE: rake db:resave_objects MODEL=MyModelName' if ENV["MODEL"].nil?
    unsaved = []
    model_class.find(:all).each do |o|
      if o.save
        puts "#{model_class.to_s}(#{o.id}) re-saved\"" 
      else
        unsaved << o
      end
    end
    if unsaved.length > 0
      puts "Some objects failed to save.  Here are their IDs:" 
      unsaved.each do |o|
        puts "#{o.id} : #{o.errors.full_messages}" 
      end
    end
  end
end

def model_class
  if (ENV["MODEL"].split('::').size > 1)
    ENV["MODEL"].split('::').inject(Kernel) {|scope, const_name| scope.const_get(const_name)}
  else
    Object.const_get(ENV["MODEL"])
  end
end