Можете ли вы создать «временную» модель в миграции Rails? - PullRequest
5 голосов
/ 08 февраля 2012

У меня есть проект Rails 2, который имеет много-много связей через таблицу соединений.Давайте назовем таблицы A, B и ABJ, где ABJ имеет свойства a_id и b_id (вместе с не относящимися к этому вопросу id и {created,updated}_at).

Что я хочуделать

Это отношение, к сожалению, было неправильно создано с самого начала и должно было быть просто одно-много (A has_many B's, B принадлежит_to A).Таким образом, я создал миграцию up , которая заново связывает B непосредственно с A.В основном это: 1) add_column a_id для B, 2) для каждого ABJ, поместите abj.a.id в abj.b.a_id, 3) drop_table: abj.Это прекрасно работает.

Я также создал «обратную» операцию в миграции down , чтобы вернуться, если мне нужно (1) create_table abj, 2) для каждого B, сделать новыйabj такой, что abj.a_id = b.a_id и abj.b_id = b.id, 3) remove_column a_id из B).Это тоже хорошо работает.

Задача

Наряду с "повторным связыванием" этого отношения с одним-многими существует ожидание, что неиспользуемый ресурс соединения ABJ исчезнет, ​​т.е., удаление модели, контроллера, тестов и т. д. Проблема заключается в том, что если мне нужно вернуться назад, запуск миграции down не будет работать, поскольку на шаге 2 (для каждогоB, создайте новый abj) больше нет class ABJ < ActiveRecord::Base, так как я удалил модель.

Так есть ли способ создать «временную» модель в рамках миграции только для манипулирования данными вБД?Или вы просто требуете, чтобы человек, выполняющий миграцию, был уверен, что эта модель существует, прежде чем запускать ее?Потому что если на шаге 2 миграция down завершится неудачно, то на шаге 1 уже будет создана таблица abj, и вам придется вручную удалить ее или закомментировать код шага 1 в миграцииперед повторным запуском (затем раскомментируйте его позже).

Интересно, есть ли какое-нибудь хорошее решение для этого.

Ответы [ 2 ]

6 голосов
/ 09 февраля 2012

Вы можете определить модель в миграции. Просто поместите определение barebones вверху вашей миграции:

class Pancake < ActiveRecord::Base; end

В случае, когда вы отбрасываете таблицу, вам нужно быть осторожным, чтобы не вызывать методы на Pancake, когда таблица блинов не существует.

1 голос
/ 09 февраля 2012

Либо следуйте советам TomL, либо используйте ручной SQL (при условии, что вы используете MySQL):

UPDATE
  B, ABJ
SET
  B.a_id = ABJ.a_id
WHERE
  B.id = ABJ.b_id;

Другие РСУБД допускают похожий, более естественный синтаксис с использованием JOIN.

...