Як написати міграцію для перейменування моделі ActiveRecord та її таблиці в Rails?


408

Я жахливо називаю і розумію, що в додатку Rails є кращий набір моїх моделей.
Чи є можливість використовувати міграцію для перейменування моделі та відповідної таблиці?


11
Я запропонував до цього питання додати "ActiveRecord", щоб покращити відповідність пошукових систем. Я шукав це за допомогою таблиці «Перейменування ActiveRecord».
Ландон Кун

6
Якщо ви використовуєте міграцію, ця проблема є складнішою, ніж здається. Вибране рішення говорить про просто повернення та перейменування вручну моделі, контролера тощо після зміни назви таблиці. Якщо ви зробите це, всі старі міграції, які посилаються на вашу модель за старішою назвою, не зможуть. Тож коли хтось клонує ваше репо і намагається запустити rake db:migrate, він вийде з ладу. Ви можете повернутися і змінити ці імена під час міграції, але це стане безладним. Вам може бути краще просто створити абсолютно нову модель, а не перейменувати її.
andrew

4
@andrewhannigan: Чи не ваш суперечка, якщо хтось клонує ваш репо і просто біжить rake db:schema:load?
istrasci

3
@istrasci: абсолютно. Насправді, робота rake db:migrateнад створенням бази даних з нуля активно відлякує, саме через занепокоєння, на які вказує andrew.
Джузеппе

Відповіді:


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знає, як повернути перейменування перейменування_міграцій, тому ви можете зробити це:

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

(Вам потрібно ще пройти і перейменувати файли вручну.)


6
@mathee: так, ви повинні змінити це вручну або за допомогою IDE, який може виконати рефакторинг Ruby і зафіксувати його у вашій системі управління версіями.
pupeno

13
git grep - твій друг. Я зараз перейменую діяльність на звичку: git grep -i activitдуже показово.
Фелікс Рабе

1
ви також повинні змінити вміст свого контролера, правда?
алемур

5
І не забудьте свої маршрути.rb!
Ден Герман

26
Крім того, просто піднімаючи голову, ви хочете використовувати множину версії імені вашої таблиці у виклику rename_table.
Хань

66

У Rails 4 все, що я повинен був зробити, - це змінити def

def change
  rename_table :old_table_name, :new_table_name
end

І всі мої індекси подбали про мене. Мені не потрібно було вручну оновлювати індекси, видаляючи старі та додаючи нові.

І це працює, використовуючи зміни для підйому вгору або вниз стосовно по відношенню до індексів.


47

Інші відповіді та коментарі охоплювали перейменування таблиці, перейменування файлів та прив'язку до вашого коду.

Я хотів би додати ще кілька застережень:

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

  • Не забудьте змінити назви залежних таблиць та моделей за допомогою однієї міграції. Я змінив свої моделі Merchant і MerchantStat на Business і BusinessStat одночасно. Інакше мені довелося б зробити занадто багато вибору та вибору при виконанні пошуку та заміни.
  • Для будь-яких інших моделей, які залежать від вашої моделі за допомогою зовнішніх ключів, імена стовпців інших таблиць інших таблиць будуть похідні від вашої оригінальної назви моделі. Таким чином, ви також хочете зробити кілька перейменованих викликів колон у цих залежних моделях. Наприклад, мені довелося перейменувати стовпець "merchant_id" на "business_id" у різних таблицях приєднання (для відносин has_and_belongs_to_many) та інших залежних таблицях (для нормальних відносин has_one та has_many). Інакше я закінчив би стовпчики типу "business_stat.merchant_id", які вказують на "business.id". Ось хороша відповідь про те, як робити перейменування стовпців.
  • Під час привітання пам’ятайте, що шукаєте для однини, множини, великої літери, малих і навіть ПОВЕРХНЕНИХ (що може траплятися в коментарях) версій ваших рядків.
  • Найкраще спочатку шукати множинні версії, а потім однини. Таким чином, якщо ви маєте неправильну множину - наприклад, у прикладі моїх торговців :: підприємств - ви можете виправити всі неправильні множини. Інакше ви можете, наприклад, "businesss" (3 s) як проміжний стан, що призводить до ще більшого пошуку та заміни.
  • Не сліпо замінюйте кожну подію. Якщо назви вашої моделі стикаються з загальними термінами програмування, зі значеннями в інших моделях або з текстовим вмістом у ваших переглядах, ви можете виявитись занадто нетерплячими. У своєму прикладі я хотів змінити назву своєї моделі на "Бізнес", але все ще називав їх "торговцями" у вмісті мого інтерфейсу користувача. Я також мав роль «продавця» для своїх користувачів у CanCan - саме плутанина між роллю продавця та моделлю Merchant викликала перейменування моделі в першу чергу.

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_, pripada_to чи щось. Можливо, вам також буде потрібно редагувати їх.

І нарешті, зробити це без набору тестів на регресію було б гарно.


11
Що стосується міграцій рейкових систем 4.0.0.beta1, то індекси не потрібно оновлювати вручну. AR оновлює його сам.
фреманоїд

1

Ви можете виконати цю команду: rails g migration rename_ {old_table_name} to {new_table_name}

після редагування файлу та додавання цього коду до зміни методу

rename_table: {old_table_name},: {new_table_name}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.