Добавление столбца в существующую таблицу в миграции Rails

340

У меня есть модель Users, которая нуждается в :emailстолбце (я забыл добавить этот столбец во время первоначального скаффолда).

Я открыл файл миграции и добавил t.string :email, сделал rake db:migrateи получил NoMethodError. Затем я добавил строку

add_column :users, :email, :string

снова rake db:migrate, снова NoMethodError. Я пропустил шаг здесь?

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

class CreateUsers < ActiveRecord::Migration  
  def self.up  
    add_column :users, :email, :string  
    create_table :users do |t|  
      t.string :username  
      t.string :email  
      t.string :crypted_password  
      t.string :password_salt  
      t.string :persistence_token  

      t.timestamps  
    end  
  end  

  def self.down  
    drop_table :users  
  end  
end
Джон
источник

Ответы:

574

Если вы уже запустили исходную миграцию (до ее редактирования), то вам нужно сгенерировать новую миграцию ( rails generate migration add_email_to_users email:stringсработает). Он создаст файл миграции, содержащий строку: add_column :users, email, string Затем выполните a, rake db:migrateи он запустит новую миграцию, создав новый столбец.

Если вы еще не запустили оригинальную миграцию, вы можете просто отредактировать ее, как вы пытаетесь это сделать. Ваш код миграции почти идеален: вам просто нужно полностью удалить add_columnстроку (этот код пытается добавить столбец в таблицу до того, как таблица была создана, а ваш код создания таблицы уже был обновлен для включения в t.string :emailлюбом случае).

Дилан Марков
источник
6
Просто чтобы прояснить, мы используем множественное число? Так это add_email_to_usersи НЕ add_email_to_user?
Purplejacket
9
Верный. Имена таблиц в Rails всегда множественные (для соответствия соглашениям БД).
Камдез
2
Вы также можете использовать rails db:migrateдля последнего шага.
Дилан Вандер Берг
Можно ли создать новый столбец на определенной позиции в таблице. Например, если я хочу создать новое поле «статус» сразу после существующего поля «адрес электронной почты»?
neeraj
2
@neeraj у вас, вероятно, уже есть ответ, но для других ищущих, да, вы можете, как, например, t.string :column_x, limit: 10, after: :column_y( например, для Rails 4)
244an
124

Используйте эту команду в консоли rails

rails generate migration add_fieldname_to_tablename fieldname:string

и

rake db:migrate

запустить эту миграцию

vinodh
источник
57

Иногда rails generate migration add_email_to_users email:stringпроизводит миграцию, как это

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
  end
end

В этом случае вам придется вручную , то add_columnдля change:

class AddEmailToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :email, :string
  end
end

А потом беги rake db:migrate

Апурв Агарвал
источник
1) Должно ли rails generate migration add_email_to_users email:stringэто выполняться после bundle exec rails cили только внутри терминала? 2) Где находится сгенерированный файл после выполнения запроса?
sofs1
28

Вы также можете сделать

rake db:rollback

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

rake db:migrate

Это будет работать, если в вашей системе установлены rails 3.1 и выше.

Гораздо более простой способ сделать это - изменить изменения, чтобы изменения в файле миграции были такими, какие они есть. использование

$rake db:migrate:redo

Это откатит последнюю миграцию и перенастроит ее снова.

Ninz
источник
21

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

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    альтернатива

    rails generate migration addFieldnameToTablename

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

    Примечание : имена таблиц в Rails всегда множественные (для соответствия соглашениям БД). Пример использования одного из шагов, упомянутых ранее

    rails generate migration addEmailToUsers

  2. rake db:migrate

Или

  1. Вы можете изменить схему из db/schema.rb, добавив нужные столбцы в запросе SQL.
  2. Запустите эту команду: rake db:schema:load

    Предупреждение / Note

    Имейте в виду, что при запуске rake db:schema:loadавтоматически стираются все данные в ваших таблицах.

Притик Наик
источник
Я сделал это, но он не переделал «леса» и не добавил новый столбец. Как я могу сделать это "автоматически"?
Джон Вутен
@ Джон Вутен, ты можешь удалить Эшафот и снова пройти через него. Отбросьте соответствующие миграции тоже.
Афолаби Олаолува Акинвуми
добавить примечание: изменение схемы без изменения миграции может создать проблемы с другими разработчиками, поддерживающими приложение.
BKSpurgeon
3

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

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

В настоящее время вы добавляете столбец, а затем создаете таблицу.

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

Дон Роби
источник
1

Вы также можете заставить столбцы таблицы в таблице, используя force: true , если ваша таблица уже существует.

пример :

ActiveRecord::Schema.define(version: 20080906171750) do
  create_table "authors", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
end
Аравин
источник
1

Вы также можете использовать специальный метод change_table в миграции для добавления новых столбцов:

change_table(:users) do |t|
  t.column :email, :string
end
ruslanimos
источник
0

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

rake db:rollback STEP=1

или откатить эту конкретную миграцию по

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

и отредактируйте файл, затем rake db:mirgateснова запустите .

Fangxing
источник
0

Вы также можете сделать это .. rails gigration add_column_to_users email: строка

затем rake db: migrate также добавьте атрибут: email в ваш пользовательский контроллер;

для более подробной информации посетите http://guides.rubyonrails.org/active_record_migrations.html

aaquib
источник
0

Вы также можете добавить столбец в определенную позицию, используя перед столбцом или после столбца, например:

rails generate migration add_dob_to_customer dob:date

Файл миграции сгенерирует следующий код, кроме как после: электронной почты. Вы должны добавить после:: электронная почта или до:: электронная почта

class AddDobToCustomer < ActiveRecord::Migration[5.2]
  def change
    add_column :customers, :dob, :date, after: :email
  end
end
Хабир
источник