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


327

У нас є script/generate migration add_fieldname_to_tablename fieldname:datatypeсинтаксис для додавання нових стовпців до моделі.

У цьому ж рядку, чи маємо сценарій / генерацію для зміни типу даних стовпця? Або я повинен записати SQL безпосередньо під час міграції ванілі?

Я хочу змінити стовпець datetimeна на date.

Відповіді:


548

Я думаю, що це має спрацювати.

change_column :table_name, :column_name, :date

13
@b_ayan: наскільки я знаю, єдині магічні слова в назвах міграції - "додати" та "видалити".
Олексій Корбан

1
Сортування рейок тут noob, але… Я розумію відповідь, але не коментарі до цієї відповіді. Роз'яснення оцінено :)
Алан Х.

7
Коли ви створюєте міграцію, ви даєте їй ім’я (наприклад, ім'я add_fieldname_to_table у вказаному вище питанні). Якщо він починається з "додати" або "видалити", тоді міграція автоматично заповнюється кодом для додавання або видалення стовпців, що заощаджує ви самі писати цей код.
Олексій Корбан

6
Також варто пам’ятати, що вам слід замінити звичайні changeдії на окремі upта downдії, оскільки change_columnце незворотна міграція та призведе до помилки, якщо вам потрібно відкотитись.
DaveStephens

1
@QPaysTaxes вгору повинен містити те, що ви хочете змінити стовпець з і на, а вниз має містити спосіб змінити цю зміну.
DaveStephens

98

Ви також можете використовувати блок, якщо у вас є кілька стовпців для зміни в межах таблиці.

Приклад:

change_table :table_name do |t|
  t.change :column_name, :column_type, {options}
end

Докладніші відомості див. У документації API класу Table .


88

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

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

Ви можете створити нову міграцію за допомогою:

rails g migration change_data_type_for_fieldname

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

class ChangeDataTypeForFieldname < ActiveRecord::Migration
  def self.up
    change_table :tablename do |t|
      t.change :fieldname, :date
    end
  end
  def self.down
    change_table :tablename do |t|
      t.change :fieldname, :datetime
    end
  end
end

Потім запустіть міграцію:

rake db:migrate

32

Як я виявив попередні відповіді, для зміни типу стовпця потрібно три кроки:

Крок 1:

Створіть новий файл міграції за допомогою цього коду:

rails g migration sample_name_change_column_type

Крок 2:

Перейдіть у /db/migrateпапку та відредагуйте створений вами міграційний файл. Є два різних рішення.

  1. def change
        change_column(:table_name, :column_name, :new_type)
    end

2.

    def up
        change_column :table_name, :column_name, :new_type
    end

    def down
        change_column :table_name, :column_name, :old_type
    end

Крок 3:

Не забудьте виконати цю команду:

rake db:migrate

Я перевірив це рішення для Rails 4, і воно добре працює.


1
На кроці 2 перший не вдасться після запуску граблі db: відкат, рекомендую перевірити другий
Feuda

Чи існує домовленість про рейкові системи, яка дозволяє зробити все більш-менш під час створення файлу міграції, не переходячи до нього, а потім редагувати його?
BKSpurgeon

@BKSpurgeon Так, перегляньте документацію тут: edgeguides.rubyonrails.org/active_record_migrations.html
Aboozar Rajabi

12

З рейки 5

З посібників по рейках :

Якщо ви хочете, щоб міграція зробила щось, що Active Record не вміє повернути, ви можете скористатися reversible:

class ChangeTablenameFieldname < ActiveRecord::Migration[5.1]
  def change
    reversible do |dir|
      change_table :tablename do |t|
        dir.up   { t.change :fieldname, :date }
        dir.down { t.change :fieldname, :datetime }
      end
    end
  end
end

8

Просто створіть міграцію:

rails g migration change_column_to_new_from_table_name

Оновіть міграцію так:

class ClassName < ActiveRecord::Migration
  change_table :table_name do |table|
    table.change :column_name, :data_type
  end
end

і, нарешті

rake db:migrate

2

Ще один спосіб змінити тип даних за допомогою міграції

крок1: Вам потрібно видалити несправне ім’я поля даних за допомогою міграції

колишній:

rails g migration RemoveFieldNameFromTableName field_name:data_type

Тут не забудьте вказати тип даних для свого поля

Крок 2: Тепер ви можете додати поле з правильним типом даних

колишній:

rails g migration AddFieldNameToTableName field_name:data_type

Це все, тепер ваша таблиця додасть правильне поле типу даних, Happy ruby ​​кодування !!


2

Це все припускаючи, що тип даних стовпця має неявне перетворення для будь-яких існуючих даних. Я зіткнувся з декількома ситуаціями, коли існуючі дані, скажімо, a Stringможна неявно перетворити у новий тип даних, скажімо Date.

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

/app/models/table.rb
  ...
  def string_to_date
    update(new_date_field: date_field.to_date)
  end

  def date_to_string
    update(old_date_field: date_field.to_s)
  end
  ...
    def up
        # Add column to store converted data
        add_column :table_name, :new_date_field, :date
        # Update the all resources
        Table.all.each(&:string_to_date)
        # Remove old column
        remove_column :table_name, :date_field
        # Rename new column
        rename_column :table_name, :new_date_field, :date_field
    end

    # Reversed steps does allow for migration rollback
    def down
        add_column :table_name, :old_date_field, :string
        Table.all.each(&:date_to_string)
        remove_column :table_name, :date_field
        rename_column :table_name, :old_date_field, :date_field
    end

0

Щоб заповнити відповіді у випадку редагування значення за замовчуванням :

На консолі рейки:

rails g migration MigrationName

Під час міграції:

  def change
    change_column :tables, :field_name, :field_type, default: value
  end

Буде виглядати так:

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