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

1339

Я неправильно назвал столбец hased_password вместо hashed_password.

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

Теги:
migration
ruby-on-rails-3

27 ответов

2045
Лучший ответ
rename_column :table, :old_column, :new_column

Update:

Возможно, вам захочется создать отдельный перенос, чтобы сделать это. (Переименуйте имя 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

Спасибо, Luke && Turadg, для воссоздания темы.

Затем просто 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 « всегда должен быть противоположным». В зависимости от контекста вашей миграции. Простое «противоположное» не может быть «правильным» при миграции.
Показать ещё 6 комментариев
64

IMO, в этом случае лучше использовать rake db:rollback. Затем отредактируйте свою миграцию и снова введите rake db:migrate. Однако, если у вас есть данные в столбце, который вы не хотите потерять, используйте rename_column.

  • 26
    Даже в «команде из одного», если у вас запущено несколько экземпляров приложения, скажем, в разных средах, на нескольких компьютерах и т. Д., Управление отредактированными миграциями является серьезной проблемой. Я редактирую миграцию только в том случае, если я просто создал ее и понял, что это неправильно, и еще нигде не запускал ее буквально.
  • 0
    Мне пришлось перезагрузить сервер после этого.
Показать ещё 3 комментария
26

http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

В разделе Available Transformations

rename_column(table_name, column_name, new_column_name):

Переименовывает столбец, но сохраняет тип и содержимое.

25

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

Сначала я создал миграцию 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 в фоновом режиме.

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

  • 1
    Мне нравится мысль, стоящая за этим, и я хотел бы добавить +1 к вашему ответу, но это обновление данных может занять очень много времени, поскольку оно проходит через рельсы и выполняет по одной строке за раз. Миграция будет выполняться намного быстрее с необработанными инструкциями sql для обновления именованных столбцов. Например, в первом сценарии миграции execute "Update table_name set correct_name_column_one = old_name_column_one" после добавления дубликатов имен столбцов execute "Update table_name set correct_name_column_one = old_name_column_one"
  • 0
    @ mr.ruh.roh ^ Полностью согласен, должен был написать это в первую очередь. Я отредактировал, чтобы отразить один эффективный оператор SQL. Спасибо за проверку вменяемости.
Показать ещё 2 комментария
16

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

rails g migration ChangeHasedPasswordToHashedPassword

Затем в файле, сгенерированном в папке db/migrate, напишите rename_column, как показано ниже:

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

Из 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 - Миграции или Миграции активной записи.

10

Если ваш код не используется совместно с другим, лучшим вариантом является просто rake db:rollback затем измените имя столбца в процессе миграции и rake db:migrate. Thats it

И вы можете написать еще одну миграцию, чтобы переименовать столбец

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

Вот оно.

  • 0
    rake db:rollback - отличное предложение. Но, как вы сказали, только если миграция еще не продвинулась.
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
7

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

https://github.com/DAddYE/mini_record

Примечание. Чтобы предотвратить конфликты, вам нужно использовать nub db/schema.rb

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

6

Для Ruby on Rails 4:

def change
    rename_column :table_name, :column_name_old, :column_name_new
end
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

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

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

Запустите 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, чтобы узнать, действительно ли имя изменилось в базе данных!

Надеюсь, что это поможет:)

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

Откройте этот файл миграции и измените этот файл, как показано ниже (Do enter your original table_name)

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

Сгенерировать файл миграции:

rails g migration FixName

# Создает db/migrate/xxxxxxxxxx.rb

Отредактируйте миграцию, чтобы выполнить свою волю.

class FixName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end
3
 def change
    rename_column :table_name, :old_column_name, :new_column_name
  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

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

  • В этом типе он автоматически запускает обратный код, когда откатывается.

    def change
      rename_column :table_name, :old_column_name, :new_column_name
    end
    
  • Для этого типа он запускает метод 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
    
1

Я на рельсах 5.2, и пытаюсь переименовать столбец на устройстве пользователя.

бит rename_column работал для меня, но в единственном числе :table_name rename_column ошибку "Таблица пользователей не найдена". Множество работало на меня.

rails g RenameAgentinUser

Затем измените файл миграции на этот:

rename_column :users, :agent?, :agent

Где: агент? старое имя столбца

0

Пусть поцелуй. Все это занимает три простых шага. Следующие работы для Rails 5.2.

1 Создать миграцию

  • rails g migration RenameNameToFullNameInStudents

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

2. Отредактируйте миграцию

# я prefer to explicitly write the methods. вверх 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

И вы отправитесь на гонки!

0

Изменения в миграции на Rails 5

например:

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

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

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

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

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

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

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

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

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

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

  • 0
    rails g migration RemoveStudentNameFromStudentS student_name:string это не должно быть: rails g migration RemoveStudentNameFromStudentS student_name:string (студенты во множественном числе)?
  • 0
    Также это опасно: столбец не переименовывается, а полностью удаляется и затем читается. Что будет с данными? Это может быть не то, что пользователь захочет.
0

Или используйте execute для выполнения SQL, но не рекомендуется

execute "ALTER TABLE table_name change COLUMN old_column_name new_colmn_name column_data_type;"
0

Просто выполните миграцию с помощью команды

rails g migration rename_hased_password

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

rename_column :table, :hased_password, :hashed_password

Это должно сделать трюк.

-1

Обновить. Близким кузеном 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

Этот способ более эффективен, если мы делаем это с другими альтернативными методами, такими как: remove/add index/remove index/add column, например, мы можем сделать следующее:

# 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
#...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню