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?

caarlos0
quelle

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
mschultz
quelle
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.

Sheharyar
quelle
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"
ökoologisch
quelle
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.

Nathanvda
quelle
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
jes5199
quelle
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)
sekmo
quelle
1
Dies funktioniert nicht, wenn Sie mehrere Verweise auf ein anderes Modell definieren müssen, z. B. Post (Autor, Herausgeber)
Ultrajohn