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.