Як я можу перейменувати стовпчик бази даних під час міграції Ruby on Rails?


1451

Я неправильно назвав стовпчик hased_passwordзамість hashed_password.

Як оновити схему бази даних, використовуючи міграцію для перейменування цього стовпця?

Відповіді:


2308
rename_column :table, :old_column, :new_column

Ви, мабуть, захочете створити окрему міграцію для цього. (Перейменуйте FixColumnNameяк завгодно.):

script/generate migration FixColumnName
# creates  db/migrate/xxxxxxxxxx_fix_column_name.rb

Потім відредагуйте міграцію, щоб виконати свою волю:

# db/migrate/xxxxxxxxxx_fix_column_name.rb
class FixColumnName < ActiveRecord::Migration
  def self.up
    rename_column :table_name, :old_column, :new_column
  end

  def self.down
    # rename back if you need or do something else or do nothing
  end
end

Для Rails 3.1 використовуйте:

Хоча, то up і downметоди все ще застосовуються, Rails 3.1 отримує changeметод, який "знає, як перенести вашу базу даних і повернути її назад, коли міграція відкочується без необхідності записувати окремий метод вниз".

Див. " Активні міграції записів " для отримання додаткової інформації.

rails g migration FixColumnName

class FixColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

Якщо у вас є ціла купа стовпців для перейменування, або щось, що вимагало б повторювати назву таблиці знову і знову:

rename_column :table_name, :old_column1, :new_column1
rename_column :table_name, :old_column2, :new_column2
...

Ви можете використовувати, change_tableщоб зберегти речі трохи акуратніше:

class FixColumnNames < ActiveRecord::Migration
  def change
    change_table :table_name do |t|
      t.rename :old_column1, :new_column1
      t.rename :old_column2, :new_column2
      ...
    end
  end
end

Тоді просто db:migrate як зазвичай, або все-таки ви займаєтеся своїм бізнесом.


Для рейок 4:

Створюючи Migrationдля перейменування стовпця, Rails 4 генерує changeметод замість upі downяк зазначено у вищевказаному розділі. Створений changeметод:

$ > rails g migration ChangeColumnName

який створить файл міграції, подібний до:

class ChangeColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

24
self.down завжди повинен бути протилежним self.up, тому "якщо вам потрібно чи щось робити чи нічого не робити" насправді не рекомендується. Просто зробіть: перейменуйте стовпець: стіл_імені,: новий_колонка,: старий_колонник
— Люк Гріффітс

3
Хоча це нормальна практика повертати те, що ви робили, self.upя б не сказав self.down" завжди має бути протилежним". Це залежить від контексту вашої міграції. Просто встановлення "протилежного" може бути не "правильним" вниз міграцією.
— зараз

23
У Rails 3.1 ви можете замінити def self.upі def self.downна, def changeі він буде знати, як відкати.
— Турадг

2
Turadg - * він буде знати, як відкати більшу частину часу. Я вважаю, що changeметод не є повним доказом, тому, як правило, використовують upі downметоди складних міграцій.
— JellyFishBoy

6
Чи перейменування видаляє індекс?
— Сун Чо

68

На мою думку, у цьому випадку краще скористатися rake db:rollback, а потім відредагувати міграцію та знову запустити rake db:migrate.

Однак якщо у вас є дані в стовпці, які ви не хочете втрачати, тоді використовуйте rename_column.


34
Навіть у "команді одного", якщо у вас є кілька примірників запуску програми, скажімо, в різних середовищах або на декількох комп'ютерах тощо, головне болі - керування відредагованими міграціями. Я редагую міграцію лише в тому випадку, коли я лише створив її і зрозумів, що вона неправильна, і ще не працювала буквально ніде.
— Єтатернотеош

1
Після цього мені довелося перезапустити сервер.
— Muhammad Hewedy

7
Цей прийом слід застосовувати лише в тих випадках, коли ваші зміни ще не були об'єднані з виробничою галуззю, а інші не залежать від збереження даних. У більшості випадків у виробництві це НЕ кращий метод.
— Collin Graves

4
ніколи не роби подібних речей.
— new2cpp

4
Я хотів би сказати своїй команді: «Міграція безкоштовна» Вартість редагування міграції, що вийшла в дику природу, висока: я один раз витратив кілька годин на розробку, чому мій код не працював, перш ніж я зрозумів іншого члена команди повернувся назад і відредагував міграцію, яку я вже запускав. Тому не редагуйте існуючу міграцію, використовуйте нову для зміни схеми, тому що ... ... "Міграція безкоштовна!" (це не зовсім вірно, але це має сенс)
— TerryS

31

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

Спочатку я б створив db міграцію, щоб додати стовпці з новими іменами та заповнити їх значеннями зі старої назви стовпців.

class AddCorrectColumnNames < ActiveRecord::Migration
  def up
    add_column :table, :correct_name_column_one, :string
    add_column :table, :correct_name_column_two, :string

    puts 'Updating correctly named columns'
    execute "UPDATE table_name SET correct_name_column_one = old_name_column_one, correct_name_column_two = old_name_column_two"
    end
  end

  def down
    remove_column :table, :correct_name_column_one
    remove_column :table, :correct_name_column_two
  end
end

Тоді я б вчинив саме цю зміну і підштовхнув би зміни до виробництва.

git commit -m 'adding columns with correct name'

Потім, коли комітет буде висунутий у виробництво, я б побіг.

Production $ bundle exec rake db:migrate

Тоді я б оновив усі перегляди / контролери, які посилаються на стару назву стовпця на нову назву стовпця. Перегляньте мій тестовий набір і вчиняйте саме ці зміни. (Після того, як переконайтеся, що він працює локально, і спочатку пройшов усі тести!)

git commit -m 'using correct column name instead of old stinky bad column name'

Тоді я підштовхнув би це зобов'язання до виробництва.

На даний момент ви можете видалити початковий стовпець, не турбуючись про якісь простої, пов’язані з самою міграцією.

class RemoveBadColumnNames < ActiveRecord::Migration
  def up
    remove_column :table, :old_name_column_one
    remove_column :table, :old_name_column_two
  end

  def down
    add_column :table, :old_name_column_one, :string
    add_column :table, :old_name_column_two, :string
  end
end

Потім натисніть на цю останню міграцію до виробництва та запустіть bundle exec rake db:migrateу фоновому режимі.

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


2
Мені подобається думка, що стоїть за цим, і я поставив би +1 вашому репссексу, але для оновлення даних знадобиться дуже багато часу, оскільки він проходить через рейки та робить один ряд за один раз. Міграція буде виконуватись набагато швидше з необробленими операторами sql для оновлення правильно названих стовпців. Наприклад, у першому сценарії міграції db, після додавання дублікатів імен стовпців, execute "Update table_name set correct_name_column_one = old_name_column_one"
— Gui Weinmann

1
@ mr.ruh.roh ^ Повністю згоден, мав би це написати в першу чергу. Я відредагований, щоб відобразити єдиний ефективний оператор sql. Дякуємо за перевірку здорового стану
— Пол Петтенгілл

2
Що відбувається з записами між переходом до нової таблиці та оновленням коду для використання нової таблиці? Чи не могли б у вас залишилися потенційно непереселені дані?
— Стефан Дорунга

1
хоча це "безпечна" відповідь, я вважаю, що вона неповна. Багато людей тут кажуть, що не роблять цього - чому? збереження даних. І це справедливо. Мабуть, найменш болючим способом досягнення мети є створення нових полів, заповнення їх даними зі старих стовпців, налаштування контролерів. Якщо ви хочете видалити старі стовпці, вам неодмінно доведеться редагувати представлення даних. Витрати на їх утримання - це додатковий провідний простір і певні копії зусиль у контролері. Таким чином, компроміси ясні.
— Єронім


18

Запустіть команду нижче, щоб створити файл міграції:

rails g migration ChangeHasedPasswordToHashedPassword

Потім у файл, згенерований у db/migrateпапці, запишіть rename_columnтак:

class ChangeOldCoulmnToNewColumn < ActiveRecord::Migration
  def change
     rename_column :table_name, :hased_password, :hashed_password
  end
end

14

Від API:

rename_column(table_name, column_name, new_column_name)

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


12

Деякі версії Ruby on Rails підтримують спосіб переходу вгору / вниз, і якщо у вас є метод вгору / вниз для міграції, то:

def up
    rename_column :table_name, :column_old_name, :column_new_name
end

def down
    rename_column :table_name, :column_new_name, :column_old_name
end

Якщо у вас є changeметод міграції, виконайте вказані нижче дії .

def change
    rename_column :table_name, :column_old_name, :column_new_name
end

Для отримання додаткової інформації ви можете переміститись: Ruby on Rails - міграція або активна міграція записів .


11

Якщо ваш код не надано спільним іншим, найкращим варіантом є лише rake db:rollback після цього змінити ім'я стовпця під час міграції та rake db:migrate. Це воно

Ви можете написати ще одну міграцію для перейменування стовпця

 def change
    rename_column :table_name, :old_name, :new_name
  end

Це воно.


rake db:rollbackє чудовою пропозицією. Але, як ви сказали, лише якщо міграція ще не була натиснута.
— danielricecodes

9

Як альтернативний варіант, якщо ви не одружені з ідеєю міграцій, є переконливий дорогоцінний камінь для ActiveRecord, який автоматично обробляє зміни імені для вас, стиль Datamapper. Все, що вам потрібно зробити - це змінити назву стовпця у вашій моделі (і переконайтеся, що ви поставили Model.auto_upgrade! Внизу вашого model.rb) та віолу! База даних оновлюється на льоту.

https://github.com/DAddYE/mini_record

Примітка. Щоб запобігти конфліктам, вам потрібно буде запустити db / schema.rb

Все ще в бета-фазах і, очевидно, не для всіх, але все ж переконливий вибір (я зараз використовую його в двох нетривіальних виробничих додатках без проблем)


8

Якщо вам потрібно переключити назви стовпців, вам потрібно створити заповнювач, щоб уникнути помилки дублювання імені стовпця . Ось приклад:

class SwitchColumns < ActiveRecord::Migration
  def change
    rename_column :column_name, :x, :holder
    rename_column :column_name, :y, :x
    rename_column :column_name, :holder, :y
  end
end

7

Якщо наявні дані для вас не важливі, ви можете просто зняти оригінальну міграцію, використовуючи:

rake db:migrate:down VERSION='YOUR MIGRATION FILE VERSION HERE'

Без лапок, потім внесіть зміни в початкову міграцію та знову запустіть перехідну версію за допомогою:

rake db:migrate

6

Просто створіть нову міграцію та в блоці використовуйте, rename_columnяк показано нижче.

rename_column :your_table_name, :hased_password, :hashed_password


5

Вручну ми можемо використовувати наступний метод:

Ми можемо редагувати міграцію вручну так:

  • відчинено app/db/migrate/xxxxxxxxx_migration_file.rb

  • Оновити hased_passwordдоhashed_password

  • Виконайте команду нижче

    $> rake db:migrate:down VERSION=xxxxxxxxx

Тоді вона видалить вашу міграцію:

$> rake db:migrate:up VERSION=xxxxxxxxx

Це додасть вашу міграцію оновленими змінами.


це не буде безпечно, оскільки ви можете втратити дані - якщо стовпець вже активний. але можна зробити для нового стовпця та / або таблиці.
— Tejas Patel

5

Створіть файл міграції:

rails g migration FixName

# Створює db / migrate / xxxxxxxxxx.rb

Відредагуйте міграцію, щоб виконати свою волю.

class FixName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

5

Виконати rails g migration ChangesNameInUsers(або як би ви хотіли його назвати)

Відкрийте щойно створений файл міграції та додайте цей рядок у спосіб (між def changeта end):

rename_column :table_name, :the_name_you_want_to_change, :the_new_name

Збережіть файл та запустіть rake db:migrateу консолі

Перевірте свою schema.db, щоб побачити, чи дійсно ім’я змінилося в базі даних!

Сподіваюся, це допомагає :)


5

Давайте KISS . Все, що потрібно, - це три простих кроки. Наступні роботи для Rails 5.2 .

1. Створіть міграцію

  • rails g migration RenameNameToFullNameInStudents

  • rails g RenameOldFieldToNewFieldInTableName- таким чином, цілком зрозуміло, що надалі підтримуватимуть кодову базу. (використовуйте множину для назви таблиці).

2. Відредагуйте міграцію

# I prefer to explicitly write theвгору andвнизmethods.

# ./db/migrate/20190114045137_rename_name_to_full_name_in_students.rb

class RenameNameToFullNameInStudents < ActiveRecord::Migration[5.2]
  def up
    # rename_column :table_name, :old_column, :new_column
    rename_column :students, :name, :full_name
  end

  def down
            # Note that the columns are reversed
    rename_column :students, :full_name, :name
  end
end

3. Виконайте свої міграції

rake db:migrate

І ви їдете на перегони!


4
$:  rails g migration RenameHashedPasswordColumn
invoke  active_record
      create    db/migrate/20160323054656_rename_hashed_password_column.rb

Відкрийте цей файл міграції та змініть його, як показано нижче (Введіть оригінал table_name)

class  RenameHashedPasswordColumn < ActiveRecord::Migration
  def change
    rename_column :table_name, :hased_password, :hashed_password
  end
end


3

Створіть міграцію Ruby on Rails :

$:> rails g migration Fixcolumnname

Вставте код у файл міграції (XXXXXfixcolumnname.rb) :

class Fixcolumnname < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

2

Відкрийте консоль Ruby on Rails і введіть:

ActiveRecord::Migration.rename_column :tablename, :old_column, :new_column

2

У вас є два способи зробити це:

  1. У цьому типі він автоматично запускає зворотний код при відкаті.

    def change
      rename_column :table_name, :old_column_name, :new_column_name
    end
  2. Для цього типу він запускає метод up коли rake db:migrateі запускає метод down, коли rake db:rollback:

    def self.up
      rename_column :table_name, :old_column_name, :new_column_name
    end
    
    def self.down
      rename_column :table_name,:new_column_name,:old_column_name
    end

2

Я перебуваю на рейках 5.2 і намагаюся перейменувати стовпчик на призначеного користувача.

rename_columnтрохи працював для мене, але в однині :table_nameкинув «таблиці користувача не знайдений» помилка. Множина працювала на мене.

rails g RenameAgentinUser

Потім змініть файл міграції на це:

rename_column :users, :agent?, :agent

Де: агент? - стара назва стовпця.


0

Оновлення - Близький родич create_table є змінним_кабелем, який використовується для зміни існуючих таблиць. Він використовується аналогічно для create_table, але об'єкт, поступлений блоку, знає більше хитрощів. Наприклад:

class ChangeBadColumnNames < ActiveRecord::Migration
  def change
    change_table :your_table_name do |t|
      t.rename :old_column_name, :new_column_name
    end
  end
end

Цей спосіб є більш ефективним, якщо ми застосовуємо інші методи зміни, такі як: видалити / додати індекс / видалити індекс / додати стовпчик, наприклад, ми можемо робити далі:

# Rename
t.rename :old_column_name, :new_column_name
# Add column
t.string :new_column
# Remove column
t.remove :removing_column
# Index column
t.index :indexing_column
#...

0

Просто генеруйте міграцію за допомогою команди

rails g migration rename_hased_password

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

rename_column :table, :hased_password, :hashed_password

Це повинно зробити трюк.


0

Рейки 5 міграційних змін

наприклад:

rails g модель Студентське ім'я студента: вік рядка: ціле число

якщо ви хочете змінити стовпець імені студента як ім'я

Примітка: - якщо ви не запустите рейки db: migrate

Ви можете виконати наступні дії

rails d модель Студентське ім'я студента: строковий вік: ціле число

Це видалить створений файл міграції, тепер ви можете виправити ім'я стовпця

rails g модель Ім'я студента: string string: integer

Якщо ви мігрували (rails db: migrate), дотримуйтесь параметрів, щоб змінити назву стовпця

rails g міграція RemoveStudentNameFromStudent_імен__код: строка

rails g міграція AddNameToStudent ім'я: string


Чи не повинно бути: rails g migration RemoveStudentNameFromStudentS student_name:string(учні множини)?
— BKSpurgeon

Також це небезпечно: стовпець не перейменовується, а повністю видаляється та перечитується. Що буде з даними? Користувач може це не те, чого захоче.
— BKSpurgeon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.