Agregar una columna a una tabla existente en una migración de Rails

340

Tengo un modelo de usuarios que necesita una :emailcolumna (olvidé agregar esa columna durante el andamio inicial).

Abrí el archivo de migración y agregué t.string :email, lo hice rake db:migratey obtuve un NoMethodError. Luego agregué la línea

add_column :users, :email, :string

De nuevo rake db:migrate, de nuevo NoMethodError. ¿Me estoy perdiendo un paso aquí?

Editar: aquí está el archivo de migración.

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
Juan
fuente

Respuestas:

573

Si ya ha ejecutado su migración original (antes de editarla), entonces necesita generar una nueva migración ( rails generate migration add_email_to_users email:stringhará el truco). Creará un archivo de migración que contiene una línea: add_column :users, email, string luego haga una rake db:migratey ejecutará la nueva migración, creando la nueva columna.

Si aún no ha ejecutado la migración original, puede editarla, como está tratando de hacer. Su código de migración es casi perfecto: solo necesita eliminar la add_columnlínea por completo (ese código está tratando de agregar una columna a una tabla, antes de que se haya creado la tabla, y su código de creación de tabla ya se ha actualizado para incluir un de t.string :emailtodos modos).

Dylan Markow
fuente
66
Para ser claros, usamos el plural? ¿Entonces es add_email_to_usersy NO add_email_to_user?
Purplejacket
99
Correcto. Los nombres de tabla en Rails siempre son plurales (para que coincidan con las convenciones de DB).
camdez
2
También puedes usarlo rails db:migratepara el paso final.
Dylan Vander Berg
¿Es posible crear una nueva columna en una posición particular en una tabla? Por ejemplo, si quiero crear un nuevo "estado" de campo justo después del campo "correo electrónico" existente.
neeraj
2
@neeraj probablemente ya tenga la respuesta, pero para otros buscadores, sí, puede t.string :column_x, limit: 10, after: :column_y
hacerlo,
123

Use este comando en la consola de rails

rails generate migration add_fieldname_to_tablename fieldname:string

y

rake db:migrate

para ejecutar esta migración

vinodh
fuente
57

A veces rails generate migration add_email_to_users email:stringproduce una migración como esta

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

En ese caso, tiene que an manualmente add_columnpara change:

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

Y luego corre rake db:migrate

Apoorv Agarwal
fuente
1) ¿Debería rails generate migration add_email_to_users email:stringejecutarse después bundle exec rails co solo dentro de la terminal? 2) ¿Dónde se ubica el archivo generado una vez que ejecutamos la consulta?
sofs1
28

También puedes hacer

rake db:rollback

si no ha agregado ningún dato a las tablas. Luego edite el archivo de migración agregando la columna de correo electrónico y luego llame

rake db:migrate

Esto funcionará si tiene instalados rieles 3.1 en adelante en su sistema.

Una forma mucho más simple de hacerlo es cambiar, dejar que el cambio en el archivo de migración sea como es. utilizar

$rake db:migrate:redo

Esto revertirá la última migración y la migrará nuevamente.

Ninz
fuente
21

Para agregar una columna solo tenía que seguir estos pasos:

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    Alternativa

    rails generate migration addFieldnameToTablename

    Una vez que se genera la migración, edítela y defina todos los atributos que desea que tenga esa columna agregada.

    Nota : Los nombres de tabla en Rails siempre son plurales (para que coincidan con las convenciones de DB). Ejemplo usando uno de los pasos mencionados anteriormente

    rails generate migration addEmailToUsers

  2. rake db:migrate

O

  1. Puede cambiar el esquema desde db/schema.rb, Agregue las columnas que desee en la consulta SQL.
  2. Ejecute este comando: rake db:schema:load

    Advertencia / nota

    Tenga en cuenta que, la ejecución rake db:schema:loadborra automáticamente todos los datos en sus tablas.

Pratik Naik
fuente
Hice esto, pero no rehizo el "andamiaje" y agregó la nueva columna. ¿Cómo puedo hacer eso "automágicamente"?
John Wooten
@ John Wooten, es posible que desee eliminar el andamio y volver a revisarlo. Descarte las migraciones correspondientes también.
Afolabi Olaoluwa Akinwumi
para agregar una nota: cambiar el esquema sin cambiar la migración puede crear problemas con otros desarrolladores que mantienen la aplicación.
BKSpurgeon
3

Cuando he hecho esto, en lugar de manipular la migración original, creo una nueva con solo agregar la columna en la sección superior y una columna desplegable en la sección inferior.

Puede cambiar el original y volver a ejecutarlo si migra hacia abajo, pero en este caso creo que se realizó una migración que no funcionará correctamente.

Como está publicado actualmente, está agregando la columna y luego creando la tabla.

Si cambia el orden, podría funcionar. O bien, cuando esté modificando una migración existente, simplemente agréguela a la tabla de creación en lugar de hacer una columna de agregar por separado.

Don roby
fuente
1

También puede forzar a las columnas de la tabla en la tabla usando force: true, si su tabla ya existe.

ejemplo :

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
fuente
1

También puede usar el método especial change_table en la migración para agregar nuevas columnas:

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

Puede revertir la última migración por

rake db:rollback STEP=1

o deshacer esta migración específica por

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

y edite el archivo, luego rake db:mirgatevuelva a ejecutarlo .

fangxing
fuente
0

También puede agregar una columna a una posición específica usando antes de la columna o después de la columna como:

rails generate migration add_dob_to_customer dob:date

El archivo de migración generará el siguiente código, excepto después: correo electrónico. necesita agregar después:: correo electrónico o antes:: correo electrónico

class AddDobToCustomer < ActiveRecord::Migration[5.2]
  def change
    add_column :customers, :dob, :date, after: :email
  end
end
Khabir
fuente