Как стать автором
Обновить

Комментарии 15

Я считаю, что миграциям данных вообще не место в кодовой базе, это разовые операции. Лично я просто готовлю скрипты для миграции, которые запускаю после деплоя, но не коммичу их в код, а просто храню в тикете.
Спасибо за эту мысль! Мне с моим через чур формальным подходом такое в голову не пришло. Слишком сильно я подвержен зависимости от Test First подхода.
Подумаю, как Ваш способ органично добавить в статью!
Кстати, еще один подход, который я иногда практикую, когда изменение данных очень простое — это в обычной рельсовой миграции просто написать чистый SQL. Переделанный пример из Вашей статьи:

class AddLastSmiledAtColumnToUsers < ActiveRecord::Migration[5.1]
  def up
    add_column :users, :last_smiled_at, :datetime
    add_index :users, :last_smiled_at

    connection.execute <<~SQL
      update users u
      set u.last_smiled_at = 
          (select max(s.created_at) from smiles s where s.user_id = u.id)
    SQL
  end
  
  def down
    remove_index :users, column: :last_smiled_at
    remove_column :users, :last_smiled_at
  end
end


Главное преимущество в том, что это никогда ничего не сломает, потому что SQL работает напрямую со структурой базы, которая была создана предыдущими миграциями, и это не зависит от Ruby-кода (когда классы меняются и пр.)

UPD: пардон, этот подход в статье есть, я был невнимателен :)
Ничего страшного, спасибо за этот развернутый пример.
Действительно, я призываю отказываться от SQL в миграциях схемы для миграции данных, кроме случаев, когда без этого нельзя сделать откатываемую миграцию.
Главными причинами являются увеличение простоя при развертывании и нагрузка на читателя, даже если SQL совсем простой. Как правило, с SQL сталкиваться приходится редко в Ruby On Rails проектах.
а я в основном чистый SQL использую, когда надо добавить колонку с «not null» констрейнтом и дефолтное значение записать, т.е. логика такая:
1. создать колонку
2. SQL для заполнения значений в ней
3. добавить «not null» constraint
Это как раз тот случай, когда и я это делаю, и даже в статье этот пример привел как исключение, когда без миграции данных невозможно сделать откатываемую миграцию, и SQL в самый раз для такого, ибо код модели в миграции схемы это самое недопустимое средство.
Раздел называется: Исключения, когда допустимо делать миграции данных в миграциях схемы.
Немного поразмышляв, я осознал в чём минус этого подхода. Миграции данных дают некоторую ценную информацию о развитии проекта, и удобно было бы их иметь в кодовой базе, чтобы при grep-е по названию модели, в том числе находились и миграции данных этой модели. А по ссылке на историю гита, можно было добраться до Pull Request-ов и задач, по которым это делалось. Меня всегда это выручало.
А уж, если мы затаскиваем это в кодовую базу, то тут не далеко до желания покрыть эту логику тестом и даже, в процессе обнаружить ошибки, которые можно пропустить при отладке логики на стейджинге через REPL.
Extrapolator, добавил Ваш способ как одно из возможных решений в статью. Большое спасибо за этот вклад!
Благодаря этому размышлению я придумал опрос об используемых людьми решениях.
Когда проект большой, разработчиков много и схема меняется часто, список миграций данных в кодовой базе помогает сориентироваться, что произошло с нужными тебе таблицами за последнее время. Бывает, берешь задачу из знакомого контекста, и не узнаешь структуру данных: тут уже полей нет, там таблицу выпилили, зато много нового появилось и будто заново знакомиться приходится.
Так Вы говорите не про миграции данных, а про изменение структуры. Текущая структура хорошо читается из ассоциаций в моделях, а манипуляции с данными — это наоборот лишний шум, который мешает понять структуру.
Кстати, я везде пользуюсь джемом annotate_models, чтобы прямо из модели видеть структуру соответствующей таблицы.
Я про то изменение структуры, которое сопровождается переносом и изменением данных. Например, решили считать аналитический показатель и хранить его в базе. Потом данные для этого показателя решили предварительно группировать, и так 5-7 итераций. А потом возникает задача «что-то показатели не очень похожи на правду, а почему?». И чтоб было легче разобраться как мы докатились до жизни такой, удобней объединять все миграции данных куда-то в одно место, чем по репозиторию искать связанные задачи и смотреть в них миграции данных.
Совершенно согласен! В проекте такого характера нужны решения с большей дисциплиной, и облегченный сценарий с выносом в скрипты в задачах совсем не годится.
В таком проекте подошёл бы подход с гемом для миграций данных в стиле миграций схемы. Либо можно продолжать использовать миграции схемы для миграций данных, если связанные с этим проблемы не сильно актуальны в силу масштаба.
Благодарю за комментарий, yoshka! Он помог улучшить статью добавлением определений ключевых понятий статьи. Если будет не сложно, прошу сказать, стало ли понятнее от этого содержание.
И было бы здорово, если бы Вы поучаствовали в голосовании под статьёй.

Проходил через почти все. На каком-то этапе сбор тестового проекта начинает быть похожим на сборку-разборку-подпирание-перепланирование-сборку и т.д. дома. То есть очень долго, тяжело, много истории (кода, миграций), забытая логика, неотслеживаемые баги...


Одномоментные миграции запросами прямо в базу — заманчиво, очень заманчиво, но не в энтэрпрайзе.


Если приложение большое, то я выбираю подход "циклической эволюции". Миграции делаем только на мажорных версиях приложения. Минорные — без изменений в базе. Делаем микросервисы, где возможно, чтобы раздробить миграции несколькими базами. Когда история миграций доходит до критической отметки (можно научно определить, а можно субъективно), то пишем новую версию приложения/микросервиса (не допиливаем мажорную, а пишем с нуля), делаем миграцию в него и заново начинаем наращивать миграции.


Сложно? Разработчики довольны, что пишут новое, а не ковыряются в старом, архитектор пересматривает базовые решения (иначе не мог бы) в пользу оптимальных, старые языки/фреймворки и т.п. заменяются новыми, четкая и понятная бизнес-логика. Кто на поддержке наследия мамонтов работал, тот точно оценит.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации