Adicionando uma coluna a uma tabela existente em uma migração do Rails


340

Eu tenho um modelo de usuários que precisa de uma :emailcoluna (eu esqueci de adicionar essa coluna durante o andaime inicial).

Abri o arquivo de migração e adicionei t.string :email, fiz rake db:migratee obtive um NoMethodError. Então eu adicionei a linha

add_column :users, :email, :string

de novo rake db:migrate, de novo NoMethodError. Estou perdendo um passo aqui?

Editar: aqui está o arquivo de migração.

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

Respostas:


573

Se você já executou sua migração original (antes de editá-la), precisará gerar uma nova migração (o que rails generate migration add_email_to_users email:stringserá feito). Ele criará um arquivo de migração contendo a linha: add_column :users, email, string Em seguida, faça rake db:migrateae executará a nova migração, criando a nova coluna.

Se você ainda não executou a migração original, basta editá-la, como está tentando fazer. Seu código de migração é quase perfeito: você só precisa remover a add_columnlinha completamente (esse código está tentando adicionar uma coluna a uma tabela, antes da criação da tabela e seu código de criação de tabela já foi atualizado para incluir uma t.string :emailmaneira).


6
Só para esclarecer, usamos o plural? Então é add_email_to_userse NÃO add_email_to_user?
Purplejacket

9
Corrigir. Os nomes de tabela no Rails são sempre plurais (para corresponder às convenções do banco de dados).
Camdez

2
Você também pode usar rails db:migratepara a etapa final.
Dylan Vander Berg

É possível criar uma nova coluna em uma posição específica em uma tabela. Por exemplo, se eu quiser criar um novo campo "status" logo após o campo "email" existente?
21318 neeraj #

2
@neeraj você provavelmente tem a resposta até agora, mas para outros candidatos, você pode sim como no exemplo t.string :column_x, limit: 10, after: :column_y(para Rails 4 pelo menos)
244an

123

Use este comando no console do Rails

rails generate migration add_fieldname_to_tablename fieldname:string

e

rake db:migrate

para executar esta migração


57

Às vezes rails generate migration add_email_to_users email:stringproduz uma migração como esta

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

Nesse caso, você precisa manualmente um add_columnpara change:

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

E então corra rake db:migrate


1) rails generate migration add_email_to_users email:stringIsso deve ser executado após bundle exec rails cou dentro do terminal? 2) Onde o arquivo gerado é colocado quando executamos a consulta?
sofs1

28

Você também pode fazer

rake db:rollback

se você não adicionou nenhum dado às tabelas. Em seguida, edite o arquivo de migração adicionando a coluna de email a ele e depois chame

rake db:migrate

Isso funcionará se você tiver os trilhos 3.1 em diante instalados no seu sistema.

Uma maneira muito mais simples de fazer isso é mudar, deixar que a mudança no arquivo de migração seja como é. usar

$rake db:migrate:redo

Isso reverterá a última migração e a migrará novamente.


21

Para adicionar uma coluna, basta seguir estas etapas:

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    Alternativa

    rails generate migration addFieldnameToTablename

    Depois que a migração for gerada, edite a migração e defina todos os atributos que você deseja que a coluna inclua.

    Nota : Os nomes de tabela no Rails são sempre plurais (para corresponder às convenções do banco de dados). Exemplo usando uma das etapas mencionadas anteriormente -

    rails generate migration addEmailToUsers

  2. rake db:migrate

Ou

  1. Você pode alterar o esquema de db/schema.rb, Adicione as colunas desejadas na consulta SQL.
  2. Execute este comando: rake db:schema:load

    Aviso / Nota

    Lembre-se de que a execução rake db:schema:loadlimpa automaticamente todos os dados em suas tabelas.


Fiz isso, mas ele não refez os "andaimes" e adicionou a nova coluna. Como posso fazer isso "automagicamente"?
31416 John Wooten

@ John Wooten, você pode excluir o andaime e passar por ele novamente. Solte as migrações correspondentes também.
Afolabi Olaoluwa Akinwumi

para adicionar uma observação: alterar o esquema sem alterar a migração pode criar problemas com outros desenvolvedores que mantêm o aplicativo.
precisa saber é o seguinte

3

Quando eu faço isso, em vez de mexer na migração original, crio uma nova com apenas a coluna add na seção up e uma coluna drop na seção down.

Você pode alterar o original e executá-lo novamente se fizer a migração para baixo, mas, neste caso, acho que foi feita uma migração que não funcionará corretamente.

Como postado atualmente, você está adicionando a coluna e, em seguida, criando a tabela.

Se você alterar a ordem, pode funcionar. Ou, ao modificar uma migração existente, adicione-a à tabela de criação em vez de fazer uma coluna de adição separada.


1

Você também pode forçar a tabela de colunas na tabela usando force: true, se a tabela já existir.

exemplo :

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

Você também pode usar o método change_table especial na migração para adicionar novas colunas:

change_table(:users) do |t|
  t.column :email, :string
end

0

Você pode reverter a última migração,

rake db:rollback STEP=1

ou reverter essa migração específica por

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

edite o arquivo e execute rake db:mirgatenovamente.



0

Você também pode adicionar uma coluna a uma posição específica usando a coluna anterior ou posterior, como:

rails generate migration add_dob_to_customer dob:date

O arquivo de migração irá gerar o seguinte código, exceto após:: email. você precisa adicionar depois:: email ou antes:: email

class AddDobToCustomer < ActiveRecord::Migration[5.2]
  def change
    add_column :customers, :dob, :date, after: :email
  end
end
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.