Вводная
С недавних пор начал в качестве СУБД использовать Postgres. Меня очень сильно привлекают в нем схемы, или как их часто называют — пространство имен(namespace), это конечно не единственное достоинство и даже не главное, а лишь приятная мелочь. Поэтому когда мы с другом начали думать о своем пилотном проекте естественно я в качесстве СУБД выбрал именно Postgres. Но вот поставить его на рельсы так, как хочется, оказалось не так просто для новичка…
Первое что я сделал это создал проект на рельсах:
rails <project name> -d postgresql
Тут все просто, создается базовая струкрура проекта и в database.yml создается уже конфигурация с подключением к postgres:
development:
adapter: postgresql
encoding: unicode
database: app_development
pool: 5
username: www
password: 123
host: localhost
port: 5432
Да, чтобы все работало нужно не забыть подключить gem — pg :-)
Проблема
Я столкнулся с тем, что я не могу создать миграцию на создание схемы, точнее я могу ссоздать, но если после этой миграции есть еще одна, которая хочет создать таблицу в этой схеме, то тут начинаются проблемы… Как я понял все миграции запускаются в одной транзакции и поэтому не получается оздать схему и сразу создать в ней таблицу.
В ручную я принципиально не хотел создавать схемы, было желание автоматизировать процесс:
rake db:migrate
и все готово.
Что я пытался сделать
Добавил в database.yml search_path: «app, public» — не помогло, т.к. на момент запуска мигрейшена, создающего схему app, ее еще нет и поэтому приложение не может подключиться к базе. Как только не подходил к search_path, но у меня так и не получилось.
Далее пришло в голову мысль кастомизировать rake-task db:migrate. Крутил ввеертел, не вышло, что-то да шло не так как хочется.
Вариант который меня устроил
Я решил зазложить все миграции по директориям, одну директорию я назвал app — туда я складываю миграции для таблиц, которые принадлежат схеме app, далее создал директорию schema — в ней расположены все миграции, создающие схемы для БД.
Дальше я начал думать, а как же мне запустить лишь те миграции которые лежат в папке schema, а потом лишь все остальные. Я начал посматривать в сторону создания своего rake-task, который выглядит следующим образом:
# -------------------------------------------------------------
# =Description:
# Rake task for creating postgres schemas
# -------------------------------------------------------------
namespace :db do
desc "Run migration for creating schemas"
task :create_schemas => :environment do
ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
ActiveRecord::Migrator.migrate("db/migrate/schema", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
end
end
Довольно простой таск, на что тут стоит обратить внимание:
- Таск создается в неймспейсе db
namespace :db
- Запускаются только миграции из определенной директории
ActiveRecord::Migrator.migrate("db/migrate/schema", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
Как это все работает
Теперь для накатывания миграций я делаю следующее:
rake db:create_schemas
rake db:migrate
Заключение
Мучить Ruby и RoR я начал совсем недавно, возможно найдется более идеальное решение данной проблемы со схемами в RoR, но текущий вариант меня пока устраивает, может кто-то знает другой, более простой и элегантный способ?
Автор: fc_arny