Aggiunta di una colonna a una tabella esistente in una migrazione Rails


340

Ho un modello Users che ha bisogno di una :emailcolonna (ho dimenticato di aggiungere quella colonna durante lo scaffold iniziale).

Ho aperto il file di migrazione e aggiunto t.string :email, fatto rake db:migratee ottenuto un NoMethodError. Quindi ho aggiunto la linea

add_column :users, :email, :string

ancora rake db:migrate, ancora NoMethodError. Mi sto perdendo un passo qui?

Modifica: ecco il file di migrazione.

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

Risposte:


574

Se hai già eseguito la migrazione originale (prima di modificarla), devi generare una nuova migrazione ( rails generate migration add_email_to_users email:stringfarà il trucco). Creerà un file di migrazione contenente la riga: add_column :users, email, string Quindi rake db:migrateesegui una e eseguirà la nuova migrazione, creando la nuova colonna.

Se non hai ancora eseguito la migrazione originale, puoi semplicemente modificarla, come stai cercando di fare. Il tuo codice di migrazione è quasi perfetto: devi solo rimuovere add_columncompletamente la riga (quel codice sta provando ad aggiungere una colonna a una tabella, prima che la tabella sia stata creata e il tuo codice di creazione della tabella sia già stato aggiornato per includervi t.string :emailcomunque).


6
Giusto per essere chiari, usiamo il plurale? Quindi è add_email_to_userse NON add_email_to_user?
Purplejacket,

9
Corretta. I nomi delle tabelle in Rails sono sempre plurali (per abbinare le convenzioni DB).
Camdez,

2
È inoltre possibile utilizzare rails db:migrateper il passaggio finale.
Dylan Vander Berg,

È possibile creare una nuova colonna su una posizione particolare in una tabella? Ad esempio, se voglio creare un nuovo campo "status" subito dopo il campo "email" esistente?
Neeraj,

2
@neeraj probabilmente hai già la risposta, ma per gli altri cercatori, sì, puoi, come ad es. t.string :column_x, limit: 10, after: :column_y(almeno per Rails 4)
244an

124

Utilizzare questo comando nella console di rotaie

rails generate migration add_fieldname_to_tablename fieldname:string

e

rake db:migrate

per eseguire questa migrazione


57

A volte rails generate migration add_email_to_users email:stringproduce una migrazione come questa

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

In tal caso devi manualmente un add_columna change:

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

E poi corri rake db:migrate


1) rails generate migration add_email_to_users email:stringQuesto dovrebbe essere eseguito dopo bundle exec rails co semplicemente all'interno del terminale? 2) Dove si trova il file generato una volta eseguita la query?
sofs1

28

Puoi anche fare

rake db:rollback

se non sono stati aggiunti dati alle tabelle, quindi modificare il file di migrazione aggiungendo la colonna e-mail e quindi chiamare

rake db:migrate

Questo funzionerà se nel sistema sono installate le rotaie da 3.1 in poi.

Il modo molto più semplice di farlo è cambiare, lasciare che la modifica nel file di migrazione sia così com'è. uso

$rake db:migrate:redo

In questo modo verrà ripristinata l'ultima migrazione e migrata di nuovo.


21

Per aggiungere una colonna ho dovuto solo seguire questi passaggi:

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    Alternativa

    rails generate migration addFieldnameToTablename

    Una volta generata la migrazione, modifica la migrazione e definisci tutti gli attributi che desideri aggiungere alla colonna.

    Nota : i nomi delle tabelle in Rails sono sempre plurali (per abbinare le convenzioni DB). Esempio usando uno dei passaggi menzionati in precedenza-

    rails generate migration addEmailToUsers

  2. rake db:migrate

O

  1. È possibile modificare lo schema da db/schema.rb, Aggiungi le colonne desiderate nella query SQL.
  2. Esegui questo comando: rake db:schema:load

    Attenzione / Nota

    Tieni presente che, l'esecuzione rake db:schema:loadcancella automaticamente tutti i dati nelle tue tabelle.


L'ho fatto, ma non ha rifatto il "ponteggio" e aggiunto la nuova colonna. Come posso farlo "automagicamente"?
John Wooten,

@ John Wooten, potresti voler eliminare l'impalcatura e ripassarlo. Elimina anche le migrazioni corrispondenti.
Afolabi Olaoluwa Akinwumi,

per aggiungere una nota: la modifica dello schema senza modificare la migrazione può creare problemi con altri sviluppatori che gestiscono l'app.
BKSpurgeon,

3

Quando ho fatto questo, invece di giocherellare con la migrazione originale, ne creo una nuova con solo la colonna aggiungi nella sezione in alto e una colonna in discesa nella sezione in basso.

Puoi cambiare l'originale e rieseguirlo se esegui la migrazione verso il basso, ma in questo caso penso che sia stata creata una migrazione che non funzionerà correttamente.

Come attualmente pubblicato, stai aggiungendo la colonna e quindi creando la tabella.

Se cambi l'ordine, potrebbe funzionare. Oppure, mentre stai modificando una migrazione esistente, aggiungila alla tabella di creazione invece di eseguire una colonna di aggiunta separata.


1

È inoltre possibile forzare la tabella delle colonne nella tabella utilizzando force: true, se la tabella è già esistente.

esempio :

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

È inoltre possibile utilizzare il metodo change_table speciale nella migrazione per aggiungere nuove colonne:

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

0

È possibile ripristinare l'ultima migrazione di

rake db:rollback STEP=1

o ripristinare questa specifica migrazione di

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

e modifica il file, quindi esegui di rake db:mirgatenuovo.



0

Puoi anche aggiungere una colonna a una posizione specifica usando prima della colonna o dopo la colonna come:

rails generate migration add_dob_to_customer dob:date

Il file di migrazione genererà il seguente codice, tranne dopo:: email. devi aggiungere dopo:: email o prima:: email

class AddDobToCustomer < ActiveRecord::Migration[5.2]
  def change
    add_column :customers, :dob, :date, after: :email
  end
end
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.