Thursday, May 24, 2007

Экспорт данных ввиде SQL Dump с сайта на Ruby

Наконец-то совершилось! Это юбилейный, сотый пост в моем блоге. не прошло и пол года с момента создания, как наступил этот юбилей. Т.е. в среднем я пишу 0.75 поста в день.. не очень много, но если вычесть выходные, то получиться ровно 1 (выходных у нас много), так что почти приближаюсь к общеинтернетовскому стандарту: 1 день - 1 пост (или больше). Ладно не буду писать оффтоп. перейду к теме поста.

Иногда, в целях быстрого бекапа и переноса данных требуется сгенерить полный дамп базы, при этом дамп должен быть в формате SQL - запустил и работает. Обычно для таких целей используют phpMyAdmin (для MySql, разумеется. Все сказанное ниже применимо только к нему). Но вот если требуется сделать это в адинистративной части? и на Ruby? тут уже copy-paste не прокатит.

Решение

В поставку стандартного MySql входит утилита mysqldump - умеет генетить то что нам надо, но вот только ей еще и параметры нужно дать правильные, да и еще и вызвать , и пот ом результ работы с диска снести...
итого имеем (работает везьде, под любой проект и ос - с этим больше всего гемморился):

require 'yaml' #Для чтения database.yaml
require 'pathname' #Для определения абсолютных путей (требуется для Unixов)

class DumpManagerController <>
def index
response.headers['Content-type'] = 'text/sql' #правильный MIME тип
response.headers['Content-Disposition'] = "attachment; filename=dump.sql" #Чтобы сразу можно было качать
rebuild_dump_file()
dump_sql_file = File.open(output_file)
dump_content = ""
dump_sql_file.each { |line|
dump_content +=line
}
dump_sql_file.close #Чистим мусор
File.delete(output_file)
render :text=>dump_content #Пишем в поток
end

protected
def rebuild_dump_file
command = build_mysqldump_command()
system command #Вызываем комманду
end

def output_file
rails_directory+"/dump.sql"
end

def rails_directory
Pathname.new(__FILE__).realpath.dirname.dirname.dirname.to_s #Главная директория рельсов
end

def build_mysqldump_command
env = ENV['RAILS_ENV'] || 'development'
database = YAML::load_file( rails_directory+'/config/database.yml')
password = ""
password = "--password=#{database[env]['password']}" if (database[env]['password'])
"mysqldump -u #{database[env]['username']} #{password} #{database[env]['database']} > #{output_file()}"
end
end


В последнем методе генерим комманду, для этого нам нужен логин, пароль и имя базы (можно еще и хост, ну ладно его пропустим, но можно было бы и настроить)
Данные читаем из конфига (благо ЯМЛ поддерживается)

Вот вообщем и все. Надеюсь будет полезно.
П.С.
Сделать в Sql Server подбную штуку штатными средствами нельзя.. потому что Microsoft думает что это никому не нужно. Приходиться мучаться и делать генераторы SQL на основе мапперов.

MySql - респект

2 comments:

Eugene Smirnov said...

Гм, это, батенька, гемор. Слабо напрямую файл отправить? Для использования mysqldump, во-первых, нужны соответствующие права на сервере. Во-вторых, слабо просто выполнить запрос? php, например, предоставляет такую возможность. Не верю, чтобы в равви такого не было.

alex said...

Пользователь береться из фаила конфигурации, от туда берет настройки и rake migrate - так что проблем с доступом быть в принципе не может - доступ к объектам дается в любом случае.

В смысле - как запрос - не понял.