Hinzufügen einer Spalte zu einer vorhandenen Tabelle in einer Rails-Migration

340

Ich habe ein Benutzermodell, das eine :emailSpalte benötigt (ich habe vergessen, diese Spalte während des anfänglichen Gerüsts hinzuzufügen).

Ich öffnete die Migrationsdatei und fügte hinzu t.string :email, tat rake db:migrateund bekam eine NoMethodError. Dann habe ich die Zeile hinzugefügt

add_column :users, :email, :string

wieder rake db:migratewieder NoMethodError. Vermisse ich hier einen Schritt?

Bearbeiten: Hier ist die Migrationsdatei.

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
quelle

Antworten:

573

Wenn Sie Ihre ursprüngliche Migration bereits ausgeführt haben (bevor Sie sie bearbeiten), müssen Sie eine neue Migration generieren (reicht aus rails generate migration add_email_to_users email:string). Es wird eine Migrationsdatei mit der folgenden Zeile erstellt: add_column :users, email, string Führen Sie dann a ausrake db:migrate Führen und führen Sie die neue Migration aus, wobei Sie die neue Spalte erstellen.

Wenn Sie die ursprüngliche Migration noch nicht ausgeführt haben, können Sie sie einfach bearbeiten, wie Sie es versuchen. Ihr Migrationscode ist fast perfekt: Sie müssen nur die add_columnZeile vollständig entfernen (dieser Code versucht, einer Tabelle eine Spalte hinzuzufügen, bevor die Tabelle erstellt wurde, und Ihr Tabellenerstellungscode wurde bereits so aktualisiert, dass er t.string :emailohnehin eine enthält).

Dylan Markow
quelle
6
Um klar zu sein, verwenden wir den Plural? Also ist es add_email_to_usersund NICHT add_email_to_user?
Purplejacket
9
Richtig. Tabellennamen in Rails sind immer plural (entsprechend den DB-Konventionen).
Camdez
2
Sie können auch rails db:migratefür den letzten Schritt verwenden.
Dylan Vander Berg
Ist es möglich, eine neue Spalte an einer bestimmten Position in einer Tabelle zu erstellen? Zum Beispiel, wenn ich ein neues Feld "Status" direkt nach dem vorhandenen "E-Mail" -Feld erstellen möchte?
Neeraj
2
@neeraj Sie haben wahrscheinlich die Antwort jetzt, aber für andere Suchende, ja Sie können wie in zB t.string :column_x, limit: 10, after: :column_y(mindestens für Rails 4)
244an
123

Verwenden Sie diesen Befehl an der Rails-Konsole

rails generate migration add_fieldname_to_tablename fieldname:string

und

rake db:migrate

um diese Migration auszuführen

vinodh
quelle
57

rails generate migration add_email_to_users email:stringErzeugt manchmal eine solche Migration

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

In diesem Fall müssen Sie manuell ein add_columnan change:

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

Und dann renn rake db:migrate

Apoorv Agarwal
quelle
1) Sollte rails generate migration add_email_to_users email:stringdies nach bundle exec rails coder nur innerhalb des Terminals ausgeführt werden? 2) Wo wird die generierte Datei abgelegt, nachdem wir die Abfrage ausgeführt haben?
sofs1
28

Sie können auch tun

rake db:rollback

Wenn Sie den Tabellen keine Daten hinzugefügt haben. Bearbeiten Sie anschließend die Migrationsdatei, indem Sie die E-Mail-Spalte hinzufügen und dann aufrufen

rake db:migrate

Dies funktioniert, wenn in Ihrem System Schienen ab Version 3.1 installiert sind.

Eine viel einfachere Methode ist die Änderung. Lassen Sie die Änderung in der Migrationsdatei so sein, wie sie ist. verwenden

$rake db:migrate:redo

Dadurch wird die letzte Migration zurückgesetzt und erneut migriert.

Ninz
quelle
21

Um eine Spalte hinzuzufügen, musste ich nur die folgenden Schritte ausführen:

  1. rails generate migration add_fieldname_to_tablename fieldname:string

    Alternative

    rails generate migration addFieldnameToTablename

    Bearbeiten Sie nach der Generierung der Migration die Migration und definieren Sie alle Attribute, die dieser Spalte hinzugefügt werden sollen.

    Hinweis : Tabellennamen in Rails sind immer plural (entsprechend den DB-Konventionen). Beispiel mit einem der zuvor genannten Schritte

    rails generate migration addEmailToUsers

  2. rake db:migrate

Oder

  1. Sie können das Schema ändern unter db/schema.rb: Fügen Sie die gewünschten Spalten in die SQL-Abfrage ein.
  2. Führen Sie diesen Befehl aus: rake db:schema:load

    Warnung / Hinweis

    Beachten Sie, dass beim rake db:schema:loadautomatischen Ausführen alle Daten in Ihren Tabellen gelöscht werden.

Pratik Naik
quelle
Ich habe dies getan, aber das "Gerüst" wurde nicht wiederholt und die neue Spalte hinzugefügt. Wie kann ich das "automatisch" machen?
John Wooten
@ John Wooten, vielleicht möchten Sie das Gerüst löschen und es noch einmal durchgehen. Löschen Sie auch entsprechende Migrationen.
Afolabi Olaoluwa Akinwumi
So fügen Sie einen Hinweis hinzu: Das Ändern des Schemas ohne Änderung der Migration kann zu Problemen mit anderen Entwicklern führen, die die App warten.
BKSpurgeon
3

Wenn ich dies getan habe, anstatt die ursprüngliche Migration zu fummeln, erstelle ich eine neue mit nur der Add-Spalte im oberen Bereich und einer Drop-Spalte im unteren Bereich.

Sie können das Original ändern und erneut ausführen, wenn Sie zwischenzeitlich migrieren. In diesem Fall ist dies jedoch eine Migration, die nicht ordnungsgemäß funktioniert.

Wie aktuell veröffentlicht, fügen Sie die Spalte hinzu und erstellen dann die Tabelle.

Wenn Sie die Reihenfolge ändern, funktioniert es möglicherweise. Wenn Sie eine vorhandene Migration ändern, fügen Sie sie einfach der Erstelltabelle hinzu, anstatt eine separate Spalte zum Hinzufügen hinzuzufügen.

Don Roby
quelle
1

Sie können das Erzwingen von Tabellenspalten in Tabellen auch mit erzwingen force: true, wenn Ihre Tabelle bereits vorhanden ist.

Beispiel :

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

Sie können bei der Migration auch eine spezielle Methode change_table verwenden, um neue Spalten hinzuzufügen:

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

Sie können die letzte Migration um zurücksetzen

rake db:rollback STEP=1

oder setzen Sie diese spezifische Migration um zurück

rake db:migrate:down VERSION=<YYYYMMDDHHMMSS>

Bearbeiten Sie die Datei und führen Sie sie rake db:mirgateerneut aus.

Fangxing
quelle
0

Sie können einer bestimmten Position auch eine Spalte hinzufügen, indem Sie vor oder nach der Spalte Folgendes verwenden:

rails generate migration add_dob_to_customer dob:date

Die Migrationsdatei generiert den folgenden Code, außer nach :: email. Sie müssen nach :: E-Mail oder vor :: E-Mail hinzufügen

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