Skip to content

Instantly share code, notes, and snippets.

@leschenko
Created June 5, 2015 13:47
Show Gist options
  • Save leschenko/5a9130000fd0df879d1b to your computer and use it in GitHub Desktop.
Save leschenko/5a9130000fd0df879d1b to your computer and use it in GitHub Desktop.
Deep record dump
# Deep record dump
#
# Usage:
# dump = DeepRecordDump.new(order)
#
# 1) build sql dump file
# dump.write('/var/www/your_app/tmp/order_nnn.sql')
# 2) build shell commands to restore assets
# puts dump.shell_dump
# 3) restore `mysql db_name -e 'source /var/www/your_app/tmp/order_nnn.sql'` !!! NOT mysql db_name < dump.sql !!!
# 4) run shell commands
#
class DeepRecordDump
attr_accessor :dump_records
def initialize(record, dump_records={}, options={})
@options = options
@options.reverse_merge!(dependent: false)
@record = record
@dump_records = dump_records
end
def dump
@dump ||= build_dump_records.values
end
def build_dump_records
dump_records[key_for(@record)] ||= dump_for(@record)
dump_associations.each do |assoc|
Array(@record.send(assoc.name)).each do |record|
dump_records[key_for(record)] or DeepRecordDump.new(record, dump_records, @options).build_dump_records
end
end
dump_records
end
def dump_associations
@record.class.reflect_on_all_associations.reject { |assoc| !@options[:dependent] && !assoc.options[:dependent] }
end
def dump_for(record)
data = {sql: insert_for(record)}
data[:shell] = shell_for(record) if record.class.table_name == 'assets'
data
end
def insert_for(record)
arel = record.class.arel_table.create_insert
arel.insert(record.send(:arel_attributes_with_values_for_create, record.attribute_names))
arel.to_sql
end
def shell_for(record)
store_relative_dir = record.data.store_dir
target_dir = "/var/www/your_app/public/#{store_relative_dir}"
backup_dir = "/var/backups/content/#{store_relative_dir}/"
"mkdir -p #{target_dir} && rsync -a backup:#{backup_dir} #{target_dir}"
end
def key_for(record)
"#{record.class.table_name}##{record.id}"
end
def sql_dump
dump.map { |d| d[:sql] }.join(";\n")
end
def shell_dump
dump.map { |d| d[:shell] }.compact.join("\n")
end
def write(path)
File.write(path, sql_dump)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment