Rails-Migration: t.Referenzen mit alternativem Namen?


120

Ich habe also eine solche create_table für Kurse an einer Schule:

create_table :courses do |t|
  t.string :name
  t.references :course
  t.timestamps
end

aber ich möchte, dass es sich auf zwei andere Kurse bezieht , wie:

has_many :transferrable_as # A Course
has_many :same_as          # Another Course

Kann ich folgendes sagen?

t.references :transferrable_as, :as=> :course

Antworten:


161

Sie können dies alles in der anfänglichen Migrations- / Spaltendefinition tun (zumindest derzeit in Rails 5):

t.references :transferable_as, index: true, foreign_key: {to_table: :courses}
t.references :same_as, index: true, foreign_key: {to_table: :courses}

10
Dies funktioniert auf Rails 5.1 und keiner der anderen Vorschläge tut dies. Es ist viel sauberer und fühlt sich richtig an.
— Stephenmurdoch

2
Ich benutze Rails 5.1.4, aber es funktioniert nicht. Wenn ich eine foreign_keyOption in der Tabellenerstellung auf diese Weise spezifiziere , wird ein Fehler ausgegeben, der besagt, dass die von mir erstellte Tabelle nicht vorhanden ist. Ich vermute also, dass sie von der offiziellen API nicht wirklich unterstützt wird.
— Quv

3
Ich habe auch gelesen, dass indexFremdschlüssel bereits ab Rails stackoverflow.com/questions/39769981/…
— Jonathan Reyes

98

Sie können es so machen:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as
  t.references :same_as
  t.timestamps
end

oder t.belongs_toals Alias ​​für verwendent.references

Sie können foreign_key: truediesen beiden Referenzzeilen keine hinzufügen . Wenn Sie sie auf Datenbankebene als Fremdschlüssel markieren möchten, müssen Sie Folgendes migrieren:

add_foreign_key :courses, :courses, column: :transferrable_as_id
add_foreign_key :courses, :courses, column: :same_as_id

Aktualisieren

In Rails 5.1 und höher können Sie den Fremdschlüssel in der Migration im create_tableBlock wie folgt hinzufügen :

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as, foreign_key: { to_table: 'courses' }
  t.references :same_as, foreign_key: { to_table: 'courses' }
  t.timestamps
end

5
Der Teil darüber, dass foreign_key: trueich nicht in der Lage war, zu den Referenzzeilen hinzuzufügen , war das, was mich auslöste. Das Hinzufügen add_foreign_keyund Angeben des Spaltennamens für diese hat den Trick getan.
— Matthew Clark

Funktioniert dies sofort in Rails? Laut stackoverflow.com/a/22384289/239657 ist hierfür der schema_plusEdelstein erforderlich . In den add_reference- Dokumenten von Rails werden die Optionen a: reference nicht erwähnt.
— Beni Cherniavsky-Paskin

1
Ich verfolge nicht, wofür die references:Option ist (im Gegensatz dazu, t.referenceswäre das nicht nur auf Modellebene relevant, da die Überlegungen zu Foreign_key von add_foreign_key?
— MCB,

1
@MCB t.referencessagt "füge dieser Tabelle ein Feld hinzu, das der Primärschlüssel einer anderen Tabelle ist." Die references:Option gibt an, für welche Tabelle es sich um einen Primärschlüssel handelt (erforderlich, wenn der Name des Felds nicht klar ist). Die add_foreign_keyFunktion weist die Datenbank an, hier die referenzielle Integrität zu erzwingen.
— Toby 1 Kenobi

2
@MCB nach all dieser Zeit merke ich, dass du die ganze Zeit Recht hattest. Ihr erster Kommentar oben ist genau richtig - die add_foreign_keyZeilen sorgen dafür, dass die Datenbank darüber informiert wird, was ein Fremdschlüssel von was ist. Der references:Parameter macht nichts.
— Toby 1 Kenobi

13

Ich denke, dieser Thread hat eine andere, eher Rails-artige Art: Scaffolding ActiveRecord: zwei Spalten desselben Datentyps

In der Migration:

t.belongs_to: transferrable_as

t.belongs_to: same_as


1
Aber woher weiß die Datenbank, mit welchem ​​Fremdschlüssel die Tabelle verknüpft werden soll? Ich versuche dies mit der Postgres-Datenbank und es wird mir ein Fehler PG::UndefinedTable: ERRORangezeigt, dass versucht wird, einer nicht vorhandenen Tabelle eine Fremdschlüsseleinschränkung hinzuzufügen.
— Toby 1 Kenobi

Falls sich jemand wundert, belongs_toist dies nur ein Alias für referencesund hat daher genau die gleiche Funktionalität.
— Jason Swett

11

Als zusätzliche Antwort auf diese Frage sollte das Modell die folgende Zeile enthalten, um die Zuordnung zu vervollständigen:

    belongs_to :transferrable_as, class_name: "Course"
    belongs_to :same_as, class_name: "Course"

3

Ich glaube nicht, dass referencesdie :asOption akzeptiert wird , aber Sie können Ihre Spalten manuell erstellen ...

create_table :courses do |t| 
  t.string  :name 
  t.integer :course1_id
  t.integer :course2_id 
  t.timestamps 
end 
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.