Angeben des Spaltennamens in einer "Referenz" -Migration


124

Ich möchte ein migrationin Rails erstellen und auf eine andere Tabelle verweisen. Normalerweise würde ich so etwas machen wie:

add_column :post, :user, :references

Dadurch wird eine Spalte mit dem Namen user_idin der postsTabelle erstellt. Aber was ist, wenn user_idich stattdessen so etwas möchte author_id? Wie kann ich das machen?

Antworten:


59

Mach es manuell:

add_column :post, :author_id, :integer

Aber jetzt, wenn Sie die Gehörs_to-Anweisung erstellen, müssen Sie sie ändern, also müssen Sie jetzt aufrufen

def post
    belongs_to :user, :foreign_key => 'author_id'
end

1
Muss ich keinen Index hinzufügen?
Caarlos0

1
Ja, Sie müssen bei der Migration einen Index erstellen.
Tom Harrison

1
Rails-Cheats - standardmäßig werden keine Indizes verwendet. Wenn Sie nun Indizes möchten (was eine großartige Idee ist - trotz der Tatsache, dass Rails sie vollständig ignorieren), können Sie sie sicherlich hinzufügen. Weitere Informationen zu Migrationen im Allgemeinen finden Sie in der Anleitung, die ich verlinke. Möglicherweise wird sogar der Aufruf von SQL-Code direkt in Ihre Migration eingefügt. Ich würde sagen, ignorieren Sie es, da es kein normaler Teil von Rails ist, erhalten Sie 0 Leistung, da die standardmäßig generierten SQL-Abfragen von Rails keinen Vorteil daraus ziehen. link
mschultz

hmm verstanden. Vielen Dank!
Caarlos0

mit schema_plusgem, t.references :category, index: true, foreign_key: true, references: :match_categoriesarbeitete auch für mich in der Migrationsdatei.
Elquimista

251

Für Schienen 5+

Anfangsdefinition:

Wenn Sie Ihre definieren PostModelltabelle, können Sie festlegen references, indexund foreign_keyin einer Zeile:

t.references :author, index: true, foreign_key: { to_table: :users }

Update verfügbar:

Wenn Sie Verweise auf eine vorhandene Tabelle hinzufügen, können Sie dies tun:

add_reference :posts, :author, foreign_key: { to_table: :users }

Hinweis: Der Standardwert für indexist true.


Erlaubt die ursprüngliche Definition Nullen? Wenn nicht, kennen Sie die nullbare Alternative?
Vorpulus Lyphane

5
Diese Definition erlaubt nulls. Fügen Sie die übliche Option hinzu, um sie nicht zuzulassen null: false.
Ashitaka

Vielen Dank. Für die "Initial Definition" denke ich, dass der "Index: true" nicht notwendig ist. Ich bekomme die gleiche Schemaänderung mit oder ohne. Keine Ursache; Ich habe gerade deine Notiz am Ende gesehen.
Joey

Danke, das habe ich gesucht!
Philippe B.

250

In Rails 4.2+ können Sie auch Fremdschlüssel in der Datenbank festlegen , was eine gute Idee ist .

Für einfache Zuordnungen kann dies auch beim t.referencesHinzufügen erfolgen foreign_key: true. In diesem Fall benötigen Sie jedoch zwei Zeilen.

# The migration
add_reference :posts, :author, index: true
add_foreign_key :posts, :users, column: :author_id

# The model
belongs_to :author, class_name: "User"

2
Danke, aber die Frage ist mit Rails3 markiert. Ich helfe
Ihnen

2
Oh, das habe ich nicht bemerkt. Nun, es war sehr hilfreich für mich. :)
Bonh

2
Ich hatte die Hoffnung fast aufgegeben, als ich das sah! Vielen Dank an @ecoologic!
Dan Williams

2
@ecoologic, nur eine Sache, die Sie vielleicht hinzufügen möchten, add_foreign_key ist nur Rails 4.2+. ;)
Dan Williams

4
Ich bin nicht sicher, ob Sie die references: :usersOption im add_referenceAnruf benötigen . Ich sehe es nicht in den Dokumenten dokumentiert und es scheint an meinem Ende ohne es zu funktionieren.
Jakecraige

87

In Rails 4 können Sie bei Verwendung von postgresql und dem Juwel schema_plus einfach schreiben

add_reference :posts, :author, references: :users

Dadurch wird eine Spalte erstellt author_id, auf die korrekt verwiesen wird users(id).

Und in Ihrem Modell schreiben Sie

belongs_to :author, class_name: "User"

Beachten Sie, dass Sie beim Erstellen einer neuen Tabelle Folgendes schreiben können:

create_table :things do |t| 
  t.belongs_to :author, references: :users 
end 

Hinweis: Der schema_plusEdelstein in seiner Gesamtheit ist nicht mit Schienen 5+ kompatibel. Diese Funktionalität wird jedoch von dem Edelstein schema_auto_foreign_keys (Teil von schema_plus) angeboten, der mit Schienen 5 kompatibel ist.


28
und wenn Sie verwenden create_table:t.references :author, references: :users
Michael Radionov

2
Das Hinzufügen des Kommentars von @ MichaelRadionov zu Ihrer Antwort würde es perfekt machen.
Toxaq

2
Ich habe mir die Rails 4.1-Quelle angesehen und kann keine Beweise finden, die :referencestatsächlich etwas bewirken.
jes5199

1
Ja, Sie haben Recht, ich benutze das schema_plusJuwel seit Ewigkeiten und es fügt tatsächlich diese Funktionalität hinzu. Ich habe meine Antwort entsprechend bearbeitet.
Nathanvda

2
In Rails 6 scheint die Syntax t.references :col_name, references: other_table_nameohne zusätzliche Edelsteine ​​zu funktionieren.
Qqwy

51

Wenn Sie keinen Fremdschlüssel verwenden, spielt es keine Rolle, wie der tatsächliche Tabellenname der anderen Tabelle lautet.

add_reference :posts, :author

Ab Rails 5 können Sie bei Verwendung eines Fremdschlüssels den Namen der anderen Tabelle in den Fremdschlüsseloptionen angeben. (Weitere Informationen finden Sie unter https://github.com/rails/rails/issues/21563. )

add_reference :posts, :author, foreign_key: {to_table: :users}

Vor Rails 5 sollten Sie den Fremdschlüssel als separaten Schritt hinzufügen:

add_foreign_key :posts, :users, column: :author_id

12
to_table ist die pluralisierte Form:{to_table: :users}
hoffmanc

-3

alias_attribute (neuer_name, alter_name) ist sehr praktisch. Erstellen Sie einfach Ihr Modell und die Beziehung:

rails g model Post title user:references

Bearbeiten Sie dann das Modell und fügen Sie einen Attributalias mit hinzu

alias_attribute :author, :user

Danach können Sie Dinge wie ausführen

Post.new(title: 'My beautiful story', author: User.first)

1
Dies funktioniert nicht, wenn Sie mehrere Verweise auf ein anderes Modell definieren müssen, z. B. Post (Autor, Herausgeber)
Ultrajohn
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.