Як я можу перейменувати стовпчик бази даних під час міграції 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.