Rails 3-Migrationen: Referenzspalte hinzufügen?

161

Wenn ich eine neue Rails 3-Migration mit (zum Beispiel) erstelle

rails g migration tester title:tester user:references

, alles funktioniert gut ... aber wenn ich eine Spalte mit etwas in der Art von:

rails g migration add_user_to_tester user:references

Das Referenzfeld wird nicht erkannt. Kurz gesagt lautet die Frage: Wie füge ich einer Rails-Migration über die Befehlszeile eine Referenzierungsspalte hinzu?

Plankton
quelle

Antworten:

205

Wenn Sie Rails 4.x verwenden , können Sie jetzt Migrationen mit folgenden Referenzen generieren:

rails generate migration AddUserRefToProducts user:references

wie Sie auf Schienen Führungen sehen können

Paulo Fidalgo
quelle
1
Siehe beispielsweise Abschnitt 2.1 von edgeguides.rubyonrails.org/active_record_migrations.html .
B Sieben
2
Wie geben Sie einen Spaltennamen für den Fremdschlüssel anstelle des automatisch generierten Namens an?
J wird
@jwill können Sie polymorph verwenden: user: references {polymorphic}.
Paulo Fidalgo
@PauloFidalgo Kannst du ein bisschen erklären, wie das geht? kann eine Anleitung von Links sein? (spricht über polymorph)
Anwar
@Anwar: hier sind die Dokumente api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/…
Paulo Fidalgo
186

EDIT : Dies ist eine veraltete Antwort und sollte nicht beantragt werden Rails 4.x +

Sie müssen keine Referenzen hinzufügen, wenn Sie Ihrer referenzierten Klasse eine Ganzzahl-ID verwenden können.

Ich würde sagen, der Vorteil der Verwendung von Referenzen anstelle einer einfachen Ganzzahl besteht darin, dass das Modell mit Gehör zu vordefiniert wird. Da das Modell bereits erstellt wurde und bei der Migration eines vorhandenen Modells nicht betroffen ist, geht der Zweck verloren.

Also würde ich stattdessen folgendes tun:

rails g migration add_user_id_to_tester user_id:integer

Fügen Sie dann im System Tester manuell Gehör zu: Benutzer hinzu

DanneManne
quelle
9
Dies führt jedoch nicht zu den entsprechenden Fremdschlüsseleinschränkungen für Datenbanken, die dies unterstützen, oder?
Abahgat
19
Nein, afaik Rails erstellt niemals Fremdschlüsseleinschränkungen in der Datenbank, es sei denn, Sie fügen Plugins hinzu, um dies für Sie zu tun.
DanneManne
Ich studiere gerade diesen Beitrag und bitte, wie füge ich die Referenz hinzu
El Nino
13
Denken Sie
3
Die Antwort ist veraltet, siehe @ Paulos Antwort für moderne Schienen.
OneHoopyFrood
102

Bitte beachten Sie, dass Sie höchstwahrscheinlich auch einen Index für diese Spalte benötigen.

class AddUserReferenceToTester < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
    add_index  :testers, :user_id
  end
end
Eugene
quelle
1
Warum? Gilt das für die meisten zugehörigen Beziehungen?
Ahnbizcad
Es ist in der Tat aus Leistungsgründen und praktisch, wenn Sie ein has_many / has_one auf der anderen Seite dieser Beziehung haben. Wenn Sie absolut sicher sind, dass Sie nicht durchlaufen werden user.testers, können Sie den Index weglassen.
Eugene
1
Das rails g migration ...Generierte, add_reference :installs, :device, index: truedas auch den Index erstellt.
B Sieben
49

Mit den beiden oben genannten vorherigen Schritten fehlt Ihnen immer noch die Fremdschlüsseleinschränkung. Das sollte funktionieren:

  class AddUserReferenceToTester < ActiveRecord::Migration
      def change
          add_column :testers, :user_id, :integer, references: :users
      end
  end
Martin Cabrera Diaubalick
quelle
Dies ist die einzige tatsächliche Antwort hier. Der Fremdschlüssel ist hier der kritischste Teil
user2490003
Dies sollte als die richtige Antwort markiert werden, da die Fragen nach Schienen 3
Carlos Roque
35

Sie können Referenzen in einer Änderungsmigration verwenden. Dies ist ein gültiger Rails 3.2.13-Code:

class AddUserToTester < ActiveRecord::Migration
  def change
    change_table :testers do |t|
      t.references :user, index: true 
    end
  end
  def down
    change_table :testers do |t|
      t.remove :user_id
    end
  end
end

Vgl.: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table

gl03
quelle
1
Methoden ändern und herunterfahren? sind nicht stattdessen Up- und Down-Methoden?
MaicolBen
@MaicolBen ja, und Sie können auch einfach die Down-Methode weglassen.
Hut8
@MaicolBen Ohne die downMethode habe ich ActiveRecord::IrreversibleMigrationbeim Rollback mit Rails 3.2 bekommen. Ich auch ändern musste changezu up.
Andrew Grimm
27

Durch Ausführen rails g migration AddUserRefToSponsors user:referenceswird die folgende Migration generiert:

def change
  add_reference :sponsors, :user, index: true
end
Wirwing
quelle
Für welche Version von Rails ist das?
Andrew Grimm
8

Wenn Sie eine Spalte hinzufügen, müssen Sie diese Spalte zu einer Ganzzahl machen und wenn möglich die Schienenkonventionen einhalten. Für Ihren Fall gehe ich also davon aus, dass Sie bereits über Tester- und Benutzermodelle sowie Tester- und Benutzertabellen verfügen.

Um den Fremdschlüssel hinzuzufügen, müssen Sie eine Ganzzahlspalte mit dem Namen user_id (Konvention) erstellen:

add_column :tester, :user_id, :integer

Fügen Sie dann dem Testermodell ein Gehorsam hinzu:

class Tester < ActiveRecord::Base
  belongs_to :user
end

Vielleicht möchten Sie auch einen Index für den Fremdschlüssel hinzufügen (dies ist etwas, was die Referenzen bereits für Sie tun):

add_index :tester, :user_id
Zamith
quelle
8

Das wird den Trick machen:

rails g migration add_user_to_tester user_id:integer:index
meisterhaft
quelle
Ich mag es, dass dies auch den Index hinzufügt, den Sie höchstwahrscheinlich wollen werden.
Bheeshmar
3

Sie können Ihrem Modell über die Befehlszeile auf folgende Weise Verweise hinzufügen:

rails g migration add_column_to_tester user_id:integer

Dadurch wird eine Migrationsdatei wie folgt generiert:

class AddColumnToTesters < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
  end
end

Dies funktioniert jedes Mal gut, wenn ich es benutze.

Neha
quelle
3

Für Schienen 4

Der Generator akzeptiert den Spaltentyp als Referenz (auch verfügbar als belongs_to).

Diese Migration erstellt eine user_idSpalte und einen entsprechenden Index:

$ rails g migration AddUserRefToProducts user:references 

erzeugt:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :products, :user, index: true
  end
end

http://guides.rubyonrails.org/active_record_migrations.html#creating-a-standalone-migration

Für Schienen 3

Der Helfer heißt Referenzen (auch verfügbar als belongs_to).

Diese Migration erstellt eine category_idSpalte des entsprechenden Typs. Beachten Sie, dass Sie den Modellnamen und nicht den Spaltennamen übergeben. Active Record fügt das _idfür Sie hinzu.

change_table :products do |t|
  t.references :category
end

Wenn Sie polymorphe belongs_toAssoziationen haben, fügen Referenzen beide erforderlichen Spalten hinzu:

change_table :products do |t|
  t.references :attachment, :polymorphic => {:default => 'Photo'}
end

Fügt eine Anhangs-ID-Spalte und eine Zeichenfolgenspalte attachment_typemit dem Standardwert von hinzu Photo.

http://guides.rubyonrails.org/v3.2.21/migrations.html#creating-a-standalone-migration

shilovk
quelle