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
John
fonte

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

Dylan Markow
fonte
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

vinodh
fonte
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

Apoorv Agarwal
fonte
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.

Ninz
fonte
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.

Pratik Naik
fonte
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.

Don Roby
fonte
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
Aravin
fonte
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
ruslanimos
fonte
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.

fangxing
fonte
0

Você também pode fazer isso .. migração rails add_column_to_users email: string

então rake db: migrate também adicione: atributo de email no seu controlador de usuário;

para obter mais detalhes, consulte http://guides.rubyonrails.org/active_record_migrations.html

aaquib
fonte
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
Khabir
fonte