Modell mit user: reference vs user_id: integer generieren


176

Ich bin verwirrt darüber, wie man ein Modell generiert, das zu einem anderen Modell gehört. Mein Buch verwendet diese Syntax, um Micropost dem Benutzer zuzuordnen:

rails generate model Micropost user_id:integer

aber http://guides.rubyonrails.org/ sagt, es so zu machen:

rails generate model Micropost user:references

Die von diesen beiden generierten Migrationen sind unterschiedlich. Woher wissen Rails bei ersteren, dass user_ides sich um eine Fremdschlüsselreferenzierung handelt user? Vielen Dank!

Antworten:


190

Beide generieren dieselben Spalten, wenn Sie die Migration ausführen. In der Rails-Konsole können Sie sehen, dass dies der Fall ist:

:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)

Der zweite Befehl fügt eine belongs_to :userBeziehung in Ihr Micropost-Modell ein, der erste nicht. Wenn diese Beziehung angegeben wird, geht ActiveRecord davon aus, dass der Fremdschlüssel in der user_idSpalte verbleibt, und verwendet ein Modell mit dem Namen User, um den bestimmten Benutzer zu instanziieren.

Der zweite Befehl fügt auch einen Index für die neue user_idSpalte hinzu.


1
Ist es möglich, ein Modell mit Referenzen von zwei Tabellen zu generieren
Praveenkumar

Beachten Sie, dass dem anderen Modell (Benutzer) keine has_many-Zuordnung hinzugefügt wird, die Sie möglicherweise ebenfalls hinzufügen möchten.
Sv1

45

Woher weiß Rails, dass user_ides sich um eine Fremdschlüsselreferenzierung handelt user?

Rails selbst weiß nicht, dass user_ides sich um eine Fremdschlüsselreferenzierung handelt user. Im ersten Befehl rails generate model Micropost user_id:integerwird nur eine Spalte user_idhinzugefügt, Rails kennt jedoch die Verwendung der Spalte nicht. Sie müssen die Linie manuell in das MicropostModell einfügen

class Micropost < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :microposts
end

die Schlüsselwörter belongs_tound has_manybestimmen die Beziehung zwischen diesen Modellen und deklarieren user_idals Fremdschlüssel zum UserModell.

Der spätere Befehl rails generate model Micropost user:referencesfügt die Zeile belongs_to :userin das MicropostModell ein und deklariert hiermit als Fremdschlüssel.

Zu Ihrer
Information Wenn Sie die Fremdschlüssel mit der vorherigen Methode deklarieren, werden die Rails nur über die Beziehung der Modelle / Tabellen informiert. Die Datenbank ist über die Beziehung unbekannt. Wenn Sie die EER-Diagramme mit einer Software wie der folgenden erstellen, stellen MySql WorkbenchSie daher fest, dass zwischen den Modellen keine Beziehungsthreads gezogen werden. Wie im folgenden Bild Geben Sie hier die Bildbeschreibung ein

Wenn Sie jedoch die spätere Methode verwenden, sieht Ihre Migrationsdatei folgendermaßen aus:

def change
    create_table :microposts do |t|
      t.references :user, index: true

      t.timestamps null: false
    end
    add_foreign_key :microposts, :users

Jetzt wird der Fremdschlüssel auf Datenbankebene festgelegt. und Sie können geeignete EERDiagramme erstellen. Geben Sie hier die Bildbeschreibung ein


1
Es scheint, dass der neueste Rails-Generator die add_foreign_keyAktion durch eine Option foreign_key: truefür die t.referencesLinie ersetzt hat, was impliziert index: true. So ist es jetzt t.references :user, foreign_key: true. Derzeit ist keine Dokumentation für die foreign_keyOption verfügbar, daher ist dies nur meine Annahme.
Franklin Yu

Oh, die add_referenceAktion hat eine :foreign_keyOption, die eine entsprechende Fremdschlüsseleinschränkung hinzufügt . Ich denke, diese Option würde das gleiche tun, wenn eine Tabelle erstellt wird.
Franklin Yu

Wie exportieren Sie Ihre Ruby-Datenbank in die Workbench? Könnten
Krawalla

Macht es add_foreign_key :microposts, :users für Rails einen Unterschied?
Linus

17

Für erstere Konvention über Konfiguration. Schienen standardmäßig, wenn Sie auf eine andere Tabelle verweisen

 belongs_to :something

ist zu suchen something_id.

references, oder belongs_toist eigentlich eine neuere Art, die erstere mit wenigen Macken zu schreiben.

Es ist wichtig zu beachten, dass keine Fremdschlüssel für Sie erstellt werden. Dazu müssen Sie es explizit einrichten, indem Sie entweder Folgendes verwenden:

t.references :something, foreign_key: true
t.belongs_to :something_else, foreign_key: true

oder (beachten Sie den Plural):

add_foreign_key :table_name, :somethings
add_foreign_key :table_name, :something_elses`

1
Können Sie erklären, was Sie damit meinen, dass Referenzen keine Fremdschlüssel für Sie erstellen? Wie unterscheidet es sich vom ersten Befehl, bei dem user_id: integer direkt verwendet wird?
Shailesh

Dies ist nicht der Fall, es sei denn, Sie verwenden eine :polymorphicOption (was meiner Meinung nach in den meisten Fällen keine gute Idee ist). Wenn Sie Fremdschlüssel in ActiveRecord verwenden möchten, verwenden Sie Foreigner .
Krule

1
@Krule Now add_foreign_keyhat es in ActiveRecord geschafft.
Franklin Yu
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.