wake-up-neo.com

Rails, die eine Migration zum Hinzufügen von Spalten zu einer Tabelle erstellen, verursachen Fehler beim Ausführen von rake db: migrate

Ich habe ein Modell namens "Benutzer" erstellt und eine neue Migration erstellt, um der Benutzertabelle einige Spalten hinzuzufügen. Wenn ich nun rake db: migrate starte, erhalte ich die Fehlermeldung unter b/c, es versucht, die Benutzertabelle erneut zu erstellen

$ rake db:migrate
==  DeviseCreateUsers: migrating ==============================================
-- create_table(:users)
rake aborted!
An error has occurred, all later migrations canceled:

Mysql::Error: Table 'users' already exists: CREATE TABLE `users`.....

Warum versucht es die Tabelle erneut zu erstellen?

Hier ist der Befehl, mit dem ich die neue Migration erstellt habe

$ Rails generate migration AddDetailsToUsers home_phone:decimal cell_phone:decimal work_phone:decimal birthday:date home_address:text work_address:text position:string company:string

Die neue Migration sieht folgendermaßen aus:

class AddDetailsToUsers < ActiveRecord::Migration
  def change
    add_column :users, :home_phone, :decimal
    add_column :users, :cell_phone, :decimal
    add_column :users, :work_phone, :decimal
    add_column :users, :birthday, :date
    add_column :users, :home_address, :text
    add_column :users, :work_address, :text
    add_column :users, :position, :string
    add_column :users, :company, :string
  end
end

EDIT

20120511224920_devise_create_users

class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
      ## Database authenticatable
      t.string :email,              :null => false, :default => ""
      t.string :username,           :null => false, :default => ""
      t.string :encrypted_password, :null => false, :default => ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, :default => 0
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Encryptable
      # t.string :password_salt

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at

      ## Token authenticatable
      # t.string :authentication_token


      t.timestamps
    end

    add_index :users, :email,                :unique => true
    add_index :users, :reset_password_token, :unique => true
    # add_index :users, :confirmation_token,   :unique => true
    # add_index :users, :unlock_token,         :unique => true
    # add_index :users, :authentication_token, :unique => true
  end
end

20120619023856_add_name_to_users

class AddNameToUsers < ActiveRecord::Migration
  def change
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string
  end
end

20121031174720_add_details_to_users.rb

class AddDetailsToUsers < ActiveRecord::Migration
  def change
    add_column :users, :home_phone, :decimal
    add_column :users, :cell_phone, :decimal
    add_column :users, :work_phone, :decimal
    add_column :users, :birthday, :date
    add_column :users, :home_address, :text
    add_column :users, :work_address, :text
    add_column :users, :position, :string
    add_column :users, :company, :string
  end
end
22
Catfish

Rails verfolgt die Migrationen in der Tabelle "schema_migrations" Ihrer Datenbank. Wenn es keinen Eintrag für "20120511224920" gibt, also die Devise-Migration, wird es erneut versucht, es erneut auszuführen, was scheinbar bereits vorhanden ist.

In diesem Fall können Sie dies manuell zur Tabelle hinzufügen.

11
omarvelous

Der Fehler besagt, dass versucht wird, die ursprüngliche DeviseCreateUsers-Migration erneut auszuführen. Dies ist jedoch nicht möglich, da die Benutzertabelle bereits vorhanden ist.

Um dies zu beheben, können Sie die Down-Migration für DeviseCreateUsers und dann wie üblich Migrationen ausführen. Das kannst du mit:

rake db:migrate:down VERSION=20121031XXXXXXXX
rake db:migrate

Dabei ist 20121031XXXXXXXX der Datumsstempel des Migrationsnamens. Mit anderen Worten, Sie haben eine Migration mit dem Namen 20120410214815_devise_create_users.rb und kopieren den Datumsstempel aus dem Dateinamen und fügen ihn in den Befehl ein. Hier ist der Rails Guide zu Migrationen als Referenz .

Edit: Dies ist in den Kommentaren vermerkt, aber nur ein Wort der Warnung. Wenn Sie die Abwärtsmigration für eine Tabelle ausführen, gehen alle Einträge der Tabelle verloren. Ich gehe davon aus, dass Sie im Entwicklungsmodus laufen, daher sollte dies kein Problem sein. Wenn Sie in der Produktion sind, müssen Sie zusätzliche Schritte unternehmen, um die Tabellendaten zu sichern und anschließend erneut zu laden. Andernfalls haben Sie einen schlechten Tag (oder möglicherweise eine Woche).

6
GorrillaMcD

Können Sie versuchen, eine neue Datenbank zu erstellen und diese dann erneut zu migrieren:

rake db:drop:all
rake db:create:all
rake db:migrate
5
Thanh

Also aus dem, was ich daraus gezogen habe:

  • Sie hatten bereits ein Benutzermodell
  • Sie haben eine Version davon in Produktion
  • Sie haben einen Standard-Rails-Generic: install ausgeführt
  • Sie haben dann Rails Generate User ausgeführt

Ich hoffe das:

  • Sie verwenden die Quellcodeverwaltung
  • Sie checken viel Code ein

HINWEIS: Wenn dies nicht der Fall ist, erfahren Sie, warum Sie dies tun müssen.

Stelle den Code wieder her, bevor du Devise erstellt hast

Hoffentlich können Sie einfach eine neue Sandbox eines Punktes erstellen, bevor Sie Devise generieren. Wenn nicht, kopieren Sie Ihr Projektverzeichnis und machen Sie es von Hand. Die einzige andere Option ist die manuelle Bearbeitung aller von Devise generierten Dateien.

Wiederhole deine Devise Generation

  • gelesener Edelstein 'erfasse' zu deinem Gemfile
  • Schienen erzeugen Gerät: Installieren
  • Schienen erzeugen Gerät MODEL

Stellen Sie sicher, dass das Modell nicht existiert! Wenn Sie nicht in das Problem geraten, das Sie gerade haben.

Aktuelle Benutzer von einem Modell zum anderen migrieren

Wenn Sie ein Skript generieren können, um die Authentifizierungsinformationen vollständig von Ihrem alten Benutzermodell in das neue zu verschieben, ist dies für Sie gut. Wenn Sie für Ihre aktuelle Authentifizierung einen anderen Hash-Algorithmus als Devise verwenden, müssen Sie entweder alle ihre Passwörter ungültig machen und die Benutzer müssen ein neues Passwort mit einem Bestätigungscode in ihrer E-Mail OR erstellen, den Sie migrieren könnten Benutzer beim Anmelden. Die erste Methode ist sauber, vollständig und unhöflich. Die zweite Methode ist hässlich, unvollständig und stumm. Wählen Sie Ihre Methode, wie Sie möchten. 

Bearbeiten: Möglicherweise finden Sie eine Möglichkeit, Devise an Ihre Algorithmen anzupassen. Das wäre wahrscheinlich noch besser, aber ein bisschen mehr Arbeit und ziemlich spröde.

Eine andere Sache ist, dass Ihr Authentifizierungsmodell nicht mit Kontodaten überladen werden sollte. Sie sollten über ein Modell verfügen, das nur die Authentifizierung ausführt, bei dem has_a ein Kontendatenmodell gespeichert ist, in dem gespeichert ist, was Sie möglicherweise über Konten nachverfolgen möchten.

2
Michael McGuire

verwenden Sie auf und ab Methoden. Dies ist hilfreich für das Rollback und das Ausführen bestimmter Migrationsdateien.

Bitte folgen Sie der Syntax ..

  class AddDetailsToUsers < ActiveRecord::Migration
    def self.up
      add_column :users, :home_phone, :decimal
      add_column :users, :cell_phone, :decimal
      add_column :users, :work_phone, :decimal
      add_column :users, :birthday, :date
      add_column :users, :home_address, :text
      add_column :users, :work_address, :text
      add_column :users, :position, :string
      add_column :users, :company, :string
   end

   def self.down
      remove_column :users, :home_phone
      remove_column :users, :cell_phone
      remove_column :users, :work_phone
      remove_column :users, :birthday
      remove_column :users, :home_address
      remove_column :users, :work_address
      remove_column :users, :position
      remove_column :users, :company
   end
  end


    In this case please try to migrate using version number.

Wie rake db: migrate: down VERSION = Versionsnummer #Versionsnummer gibt an, welche Version Sie migrieren möchten.

2
vijikumar

Suchen Sie nach Umgebungsvariablen, die möglicherweise einen unerwarteten Wert für die Version Ihrer Migration liefern. Ich fand eine alte Frage bei Stack Overflow (und vergib mir, wenn es nicht mehr aktuell ist), wo db:migrate die Tabelle zerstörte, anstatt eine bestehende neue Migration anzuwenden. 

Sie stellten schließlich fest, dass eine Umgebungsvariable dazu führte, dass db:migrate mit einem Versionsparameter "0" ausgeführt wurde, der funktional äquivalent zu rake db:migrate:down ist.

Ist es möglich, dass Ihre Situation dadurch verursacht wurde, dass die Version unerwartet geändert wurde, um die vorherige Migration DeviseCreateUsers aufzunehmen oder abzugleichen?

1
lutze

Ich nehme an, Sie haben irgendwann Rails generate devise user ausgeführt, wodurch DeviseCreateUsers generiert wurde. Wenn Sie bereits ein Benutzermodell und eine Benutzertabelle erstellt haben, können Sie die generierte Migrationsdatei aus db/migrate löschen.

1
Yanhao

Und wenn Sie einige schmutzige Migrationen manuell durchführen müssen:

class A < ActiveRecord::Migration
  def up
    add_column :images, :name
  end
end

A.new.migrate(:up)
0
Dorian

versuch's einfach 

in der ersten Datei 

create_table(:users), :force => true do |t|

dadurch wird jede andere Tabelle überschrieben

0

Wie Sie sagten, haben Sie diesen Befehl zum Erstellen einer neuen Migration verwendet

$ Rails erzeugen Migration AddDetailsToUsers home_phone: decimal cell_phone: decimal work_phone: decimal geburtstag: date home_address: text work_address: text position: string firma: string

Ich bin nicht sicher, ob es sich nur um einen Tippfehler handelt, es sollte jedoch "AddDetailsToUser" und nicht "Users" sein. Einfach nochmal nachschauen und wir können Ihnen helfen. Dies ist für das erzeugte Modell. Wenn Sie Benutzer erwähnen, wird in db nach Benutzern gesucht.

Ruby on Rails folgt der linguistischen Konvention.Tabellenname ist Plural, aber Modellname ist Singular. In dem von Ihnen verwendeten Befehl müssen Sie Modellname verwenden.

Wenn Sie tabellenname verwenden möchten, verwenden Sie diese Option 

Rails g Migration add_details_to_users home_phone: dezimal ...... etc

0
Nikhil Nanjappa