générer un modèle à l'aide de user: references vs user_id: integer

177

Je ne sais pas comment générer un modèle qui appartient à un autre modèle. Mon livre utilise cette syntaxe pour associer Micropost à User:

rails generate model Micropost user_id:integer

mais http://guides.rubyonrails.org/ dit de le faire comme ceci:

rails generate model Micropost user:references

Les migrations générées par ces 2 sont différentes. De plus, pour le premier, comment les rails savent-ils qu'il user_ids'agit d'une clé étrangère référençant user? Merci!

stackOverlord
la source

Réponses:

190

Les deux généreront les mêmes colonnes lorsque vous exécuterez la migration. Dans la console rails, vous pouvez voir que c'est le cas:

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

La deuxième commande ajoute une belongs_to :userrelation dans votre modèle Micropost, contrairement à la première. Lorsque cette relation est spécifiée, ActiveRecord supposera que la clé étrangère est conservée dans la user_idcolonne et utilisera un modèle nommé Userpour instancier l'utilisateur spécifique.

La deuxième commande ajoute également un index sur la nouvelle user_idcolonne.

Jon M.
la source
1
Est-il possible de générer un modèle avec des références de deux tables
praveenkumar
Notez qu'il n'ajoute pas d'association has_many sur l'autre modèle (utilisateur), que vous pouvez également ajouter.
Sv1
45

Comment les rails savent-ils qu'il user_ids'agit d'un référencement de clé étrangère user?

Rails lui-même ne sait pas qu'il user_ids'agit d'un référencement de clé étrangère user. Dans la première commande, rails generate model Micropost user_id:integeril ajoute uniquement une colonne, user_idmais les rails ne connaissent pas l'utilisation du col. Vous devez mettre manuellement la ligne dans le Micropostmodèle

class Micropost < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :microposts
end

les mots-clés belongs_toet has_manydéterminer la relation entre ces modèles et déclarer user_idcomme clé étrangère au Usermodèle.

La dernière commande rails generate model Micropost user:referencesajoute la ligne belongs_to :userdans le Micropostmodèle et déclare par la présente comme clé étrangère.

FYI La
déclaration des clés étrangères en utilisant l'ancienne méthode permet uniquement aux Rails de connaître la relation entre les modèles / tables. La base de données est inconnue sur la relation. Par conséquent, lorsque vous générez les diagrammes EER à l'aide d'un logiciel comme MySql Workbenchvous constatez qu'il n'y a pas de fils de relation dessinés entre les modèles. Comme dans la photo suivante entrez la description de l'image ici

Cependant, si vous utilisez la méthode ultérieure, vous constatez que votre fichier de migration ressemble à:

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

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

La clé étrangère est désormais définie au niveau de la base de données. et vous pouvez générer des EERdiagrammes appropriés . entrez la description de l'image ici

illusionniste
la source
1
Il semble que le dernier générateur de Rails ait remplacé l' add_foreign_keyaction par une option foreign_key: trueà la t.referencesligne, ce qui implique index: true. Il en est ainsi maintenant t.references :user, foreign_key: true. Il n'y a actuellement aucune documentation pour l' foreign_keyoption disponible, donc ce n'est que mon hypothèse.
Franklin Yu
Oh, l' add_referenceaction a une :foreign_keyoption qui ajoute une contrainte de clé étrangère appropriée . Je suppose que cette option ferait la même chose lors de la création d'une table.
Franklin Yu
Comment exporter votre base de données ruby ​​vers Workbench? pourriez-vous peut-être répondre ici: stackoverflow.com/questions/42982921/…
Krawalla
Avoir add_foreign_key :microposts, :users fait-il une différence pour les rails?
Linus
17

Pour le premier, convention sur la configuration. Rails par défaut lorsque vous référencez une autre table avec

 belongs_to :something

est à rechercher something_id.

references, ou belongs_toest en fait une manière plus récente d'écrire la première avec quelques bizarreries.

Il est important de se rappeler qu'il ne créera pas de clés étrangères pour vous. Pour ce faire, vous devez le configurer explicitement en utilisant soit:

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

ou (notez le pluriel):

add_foreign_key :table_name, :somethings
add_foreign_key :table_name, :something_elses`
Krule
la source
1
pouvez-vous expliquer ce que vous entendez en disant que les références ne créeront pas de clés étrangères pour vous. En quoi est-ce différent de la première commande utilisant directement user_id: integer?
shailesh
Ce n'est pas le cas, sauf dans le cas où vous utilisez l' :polymorphicoption (ce à mon humble avis, dans la plupart des cas, n'est pas une bonne idée). Si vous souhaitez utiliser des clés étrangères dans ActiveRecord, utilisez un étranger .
Krule
1
@Krule Now add_foreign_keyest devenu ActiveRecord.
Franklin Yu