Как я могу переименовать столбец базы данных в миграции Ruby on Rails?


Ответы:


2309
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как обычно, или как вы занимаетесь своими делами.


Для Rails 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, поэтому «если вам нужно или что-то делать или ничего не делать», на самом деле не рекомендуется. Просто сделайте: rename_column: table_name,: new_column,: old_column
Люк Гриффитс

3
Хотя это нормальная практика, чтобы отменить то, что вы сделали, self.upя бы не сказал self.down« всегда должно быть наоборот». В зависимости от контекста вашей миграции. Простое противопоставление «противоположности» не может быть «правильной» миграцией.
Nowk

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
Даже в «команде из одного», если у вас запущено несколько экземпляров приложения, скажем, в разных средах, на нескольких компьютерах и т. Д., Управление отредактированными миграциями является серьезной проблемой. Я редактирую миграцию только в том случае, если я просто создал ее и понял, что это неправильно, и еще нигде не запускал ее буквально.
Yetanotherjosh

1
После этого мне пришлось перезагрузить сервер.
Мухаммед Хьюди

7
Этот метод следует использовать только в ситуации, когда ваши изменения еще не объединены с вашей производственной ветвью, а другие не зависят от постоянства данных. В большинстве случаев это НЕ предпочтительный метод.
Коллин Грейвс

4
никогда не делай такого рода вещей.
new2cpp

4
Я хотел бы сказать своей команде: «Миграции бесплатны». Стоимость редактирования миграции, выпущенной на волю, высока: однажды я потратил несколько часов на то, чтобы понять, почему мой код не работает, прежде чем я понял, что другой член команды вернулся и отредактировал миграцию, которую я уже запустил. Поэтому не редактируйте существующую миграцию, используйте новую для изменения схемы, потому что ... ... "Миграции бесплатны!" (это не совсем верно, но в этом суть)
TerryS

31

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

Сначала я создал бы миграцию базы данных, чтобы добавить столбцы с новыми именами и заполнить их значениями из старого имени столбца.

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 для обновления именованных столбцов. Например, в первом сценарии переноса БД после добавления повторяющихся имен столбцов 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 поддерживают метод up / down для миграции, и если у вас есть метод up / down в вашей миграции, то:

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 - Миграции или Active Record Migrations .


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

Примечание. Чтобы предотвратить конфликты, вам нужно использовать nub 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

Это добавит вашу миграцию с обновленным изменением.


это не будет безопасно, так как вы можете потерять данные - если столбец уже активен. но можно сделать для нового столбца и / или таблицы.
Теджас Патель

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

Давай поцелуй . Все это занимает три простых шага. Следующие работы для 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

У вас есть два способа сделать это:

  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 - change_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

Изменения в Rails 5

например:

рельсы г модель Студент студент_имя: строка возраст: целое число

если вы хотите изменить столбец student_name как имя

Примечание: - если вы не запускаете rails db: migrate

Вы можете сделать следующие шаги

рельсы d модель Студент имя_ студента: возраст строки: целое число

Это удалит сгенерированный файл миграции, теперь вы можете исправить имя столбца

рельсы g модель Имя ученика: возраст строки: целое число

Если вы мигрировали (rails db: migrate), следующие опции для изменения имени столбца

рельсы и миграция RemoveStudentNameFromStudent имя_студента: строка

рельсы г миграции AddNameToStudent имя: строка


Разве это не должно быть: rails g migration RemoveStudentNameFromStudentS student_name:string(студенты во множественном числе)?
BKSpurgeon

Также это опасно: столбец не переименовывается, а полностью удаляется и затем читается. Что будет с данными? Это может быть не то, что пользователь захочет.
BKSpurgeon
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.