Как вы пишете миграцию для переименования модели ActiveRecord и ее таблицы в Rails?

408

Я ужасно разбираюсь в названиях и понимаю, что в моем приложении Rails есть лучший набор имен для моих моделей.
Есть ли способ использовать миграцию для переименования модели и соответствующей ей таблицы?

Readonly
источник
11
Я предложил добавить «ActiveRecord» к этому вопросу, чтобы улучшить поиск в поисковых системах. Я искал это с помощью "таблицы переименования ActiveRecord".
Лэндон Кун
6
Если вы используете миграцию, эта проблема сложнее, чем кажется. Выбранное решение говорит просто вернуться и вручную переименовать модель, контроллер и т. Д. После изменения имени таблицы. Если вы сделаете это, все старые миграции, которые ссылаются на вашу модель по старому имени, завершатся неудачно. Поэтому, когда кто-то клонирует ваш репозиторий и пытается его запустить rake db:migrate, он потерпит неудачу. Вы могли бы вернуться и изменить эти имена в процессе миграции, но это может стать грязным. Возможно, вам лучше просто создать совершенно новую модель, чем переименовывать ее.
Андрей
4
@andrewhannigan: Тебе не важно, если кто-то клонирует твой репо и просто бежит rake db:schema:load?
Истраши
3
@istrasci: абсолютно. На самом деле, запускать rake db:migrateсоздание базы данных с нуля активно не рекомендуется, именно из-за проблем, на которые указал Эндрю.
Джузеппе

Ответы:

584

Вот пример:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def self.up
    rename_table :old_table_name, :new_table_name
  end

  def self.down
    rename_table :new_table_name, :old_table_name
  end
end

Мне пришлось пойти и переименовать файл объявления модели вручную.

Редактировать:

В Rails 3.1 и 4 ActiveRecord::Migration::CommandRecorderзнает, как отменить миграцию rename_table, поэтому вы можете сделать это:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def change
    rename_table :old_table_name, :new_table_name
  end 
end

(Вам все еще нужно пройти и вручную переименовать ваши файлы.)

Readonly
источник
6
@mathee: да, вы должны изменить это вручную или использовать IDE, которая может выполнить рефакторинг Ruby и зафиксировать его в вашей системе контроля версий.
Пупено
13
мерзавец grep твой друг. Я переименовываю активность в привычку прямо сейчас: git grep -i activitэто очень показательно.
Феликс Рабе
1
Вы также должны изменить содержимое вашего контроллера, верно?
alemur
5
И не забывайте свои маршруты.
Дэн Герман,
26
Также, в качестве заголовка, вы хотите использовать множественную версию имени вашей таблицы в вызове rename_table.
Хан
66

В Rails 4 все, что мне нужно было сделать, это изменить определение

def change
  rename_table :old_table_name, :new_table_name
end

И обо всех моих показателях позаботились обо мне. Мне не нужно было вручную обновлять индексы, удаляя старые и добавляя новые.

И это работает, используя изменения для повышения или понижения в отношении индексов.

bfcoder
источник
47

Другие ответы и комментарии касались переименования таблиц, переименования файлов и просмотра вашего кода.

Я хотел бы добавить еще несколько предостережений:

Давайте используем реальный пример, с которым я столкнулся сегодня: переименование модели из «Торговца» в «Бизнес».

  • Не забудьте изменить имена зависимых таблиц и моделей в одной и той же миграции. Я изменил свои модели Merchant и MerchantStat на Business и BusinessStat одновременно. В противном случае мне пришлось бы делать слишком много выбора и выбора при выполнении поиска и замены.
  • Для любых других моделей, которые зависят от вашей модели через внешние ключи, имена столбцов внешних ключей других таблиц будут получены из вашего исходного имени модели. Поэтому вы также захотите сделать несколько вызовов rename_column для этих зависимых моделей. Например, мне пришлось переименовать столбец 'merchant_id' в 'business_id' в различных таблицах соединения (для отношений has_and_belongs_to_many) и других зависимых таблицах (для нормальных отношений has_one и has_many). В противном случае я бы получил столбцы типа business_stat.merchant_id, указывающие на business.id. Вот хороший ответ по поводу переименования столбцов.
  • При подборе текста не забывайте искать версии строк в единственном, множественном числе, в верхнем регистре и даже в верхнем регистре (что может встречаться в комментариях).
  • Лучше всего сначала поискать варианты во множественном числе, а затем в единственном числе. Таким образом, если у вас неправильное множественное число - как, например, в моем примере с торговцами :: бизнесом - вы можете получить все неправильные множественные числа правильными. В противном случае вы можете получить, например, «businesss» (3 с) в качестве промежуточного состояния, что приведет к еще большему поиску и замене.
  • Не заменяйте вслепую каждый случай. Если названия вашей модели вступают в противоречие с общими терминами программирования, со значениями в других моделях или с текстовым содержимым в ваших представлениях, вы, возможно, будете слишком перегружены. В моем примере я хотел изменить название своей модели на «Бизнес», но по-прежнему называю их «продавцами» в контенте в моем пользовательском интерфейсе. У меня также была роль «продавца» для моих пользователей в CanCan - именно путаница между ролью продавца и моделью Merchant заставила меня переименовать модель в первую очередь.
armchairdj
источник
26

Вам также необходимо заменить ваши индексы:

class RenameOldTableToNewTable< ActiveRecord:Migration
  def self.up
    remove_index :old_table_name, :column_name
    rename_table :old_table_name, :new_table_name
    add_index :new_table_name, :column_name
  end 

  def self.down
    remove_index :new_table_name, :column_name
    rename_table :new_table_name, :old_table_name
    add_index :old_table_name, :column_name
  end
end

И переименуйте свои файлы и т. Д. Вручную, как описано в других ответах.

Смотрите: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

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

Кроме того: проверьте schema_db для любых соответствующих имен столбцов в других таблицах, определенных has_ ​​или own_to или чем-то. Вам, вероятно, придется редактировать их тоже.

И, наконец, делать это без набора регрессионных тестов было бы чокнутым.

Rimian
источник
11
Что касается миграций rails 4.0.0.beta1, нет необходимости обновлять индексы вручную. AR обновляет его самостоятельно.
Фриманоид
1

Вы можете выполнить эту команду: rails gigration rename_ {old_table_name} to {new_table_name}

после того, как вы отредактируете файл и добавите этот код в метод изменения

rename_table: {old_table_name},: {new_table_name}

Мухамаду Бамба Мбуп
источник