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.