Еще о схеме БД, миграциях и нестандартных полях в Rails

August 31, 2010, revised January 7, 2011 PostgreSQL Ruby on Rails базы данных миграции

Совершенно случайно наткнулся на такой комментарий в db/schema.rb:

# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).

# Учтите, что schema.rb является авторитетным источником данных о
# структуре базы данных. Если вам нужно воспроизвести базу на другой
# машине, нужно выполнить db:schema:load, а не прогонять все миграции
# с нуля - это ущербный и обреченный на провал подход (чем больше миграций
# накопится в проекте, тем медленне они будут проходить и тем больше вероятность ошибок).

Он говорит о двух вещах.

Во-первых, при развертывании проекта, особенно если он уже старый и миграций поднакопилось, нужно выполнять не rake db:migrate, а rake db:schema:load. Вторая команда выполняет фактически всего одну миграцию и не выполняет всяческих отменяющих друг друга команд (знаешь, как бывает – поле добавили, потом через неделю вынормализировали и убрали).

Надо заметить, что если в базе есть какие-нибудь нестандартные поля, например, поля полнотекстового поиска Postgres, то соответствующая таблица в schema.rb попросту не попадет. В таком случае у тебя есть три выхода: либо добавить файл схемы в игнор, чтоб людей не смущать, либо патчить адаптер БД, что мне желаемого результата не дало, либо использовать схему в SQL (config.active_record.schema_format = :sql). Но не тут-то было: SQL-схема не обновляется автоматически после миграций и не используется в задачах типа db:setup. Соответствующий патч лежит в багтрекере Rails аж с первого ноября 2010 года и пока принят не был.

Во-вторых, что более важно, в миграциях не должно быть логики по наполнению базы – хотя бы потому, что это нарушает вышеупомянутое соглашение. По соглашению, наполнение базы нужно делать в db/seeds.rb.

А вот логика по изменению существующих данных в миграции вполне уместна и иногда неизбежна, например, если добавление поля и наполнение его данными нужно завернуть в одну транзакцию.

Buy Me a Coffee at ko-fi.com