Migration des rails: t. Références avec un autre nom?

121

J'ai donc un create_table comme celui-ci pour les cours dans une école:

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

mais je veux qu'il fasse référence à deux autres cours comme:

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

Puis-je dire ce qui suit?

t.references :transferrable_as, :as=> :course
le miroir
la source

Réponses:

161

Vous pouvez tout faire dans la définition initiale de migration / colonne (au moins actuellement dans Rails 5):

t.references :transferable_as, index: true, foreign_key: {to_table: :courses}
t.references :same_as, index: true, foreign_key: {to_table: :courses}
Ryan
la source
10
Cela fonctionne sur Rails 5.1 et aucune des autres suggestions ne le fait. C'est beaucoup plus propre et se sent bien.
stephenmurdoch
2
J'utilise Rails 5.1.4 mais cela ne fonctionne pas. Lorsque je spécifie une foreign_keyoption dans la création de table de cette manière, cela soulève une erreur disant que la table même que je crée n'existe pas ... Donc je soupçonne qu'elle n'est pas vraiment prise en charge par l'API officielle.
Quv
3
J'ai aussi lu que cela indexest déjà ajouté aux clés étrangères à partir de Rails stackoverflow.com/questions/39769981/...
Jonathan Reyes
99

Vous pouvez le faire de cette façon:

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

ou en utilisant t.belongs_tocomme alias pourt.references

Vous ne pouvez pas ajouter foreign_key: trueà ces deux lignes de références. Si vous souhaitez les marquer comme clés étrangères au niveau de la base de données, vous devez effectuer une migration avec ceci:

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

Mettre à jour

Dans Rails 5.1 et plus, vous pouvez ajouter la clé étrangère dans la migration dans le create_tablebloc comme ceci:

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
Toby 1 Kenobi
la source
5
Le fait de ne pas pouvoir ajouter foreign_key: trueaux lignes de références était ce qui me faisait trébucher. L'ajout add_foreign_keyet la spécification du nom de colonne pour ceux-ci ont fait l'affaire.
Matthew Clark
Cela fonctionne-t-il directement dans Rails? Selon stackoverflow.com/a/22384289/239657 , cela nécessite la schema_plusgemme. Les documents add_reference de Rails ne mentionnent pas les options a: references.
Beni Cherniavsky-Paskin
1
Je ne suis pas à quoi references:sert l' option (par opposition à t.referencescela ne serait-il pas seulement pertinent au niveau du modèle, les considérations Foreign_key étant prises en charge par add_foreign_key?
MCB
1
@MCB t.referencesdit "ajoutez un champ à cette table qui est la clé primaire d'une autre table." L' references:option lui indique de quelle table il s'agit d'une clé primaire (nécessaire si le nom du champ n'est pas clair). La add_foreign_keyfonction indique à la base de données d'appliquer l'intégrité référentielle ici.
Toby 1 Kenobi
2
@MCB après tout ce temps, je réalise que vous aviez raison depuis le début. Votre premier commentaire ci-dessus est tout à fait exact - les add_foreign_keylignes se chargent d'informer la base de données de ce qu'est une clé étrangère de quoi. Le references:paramètre ne fait rien.
Toby 1 Kenobi le
13

Je pense que ce fil a une autre manière plus Rails-ish: Scaffolding ActiveRecord: deux colonnes du même type de données

Dans la migration:

t.belongs_to: transférable_as

t.belongs_to: same_as

le miroir
la source
1
mais comment la base de données sait-elle à quelle clé étrangère lier la table? J'essaie cela avec la base de données Postgres et cela me donne une erreur PG::UndefinedTable: ERRORen essayant d'ajouter une contrainte de clé étrangère à une table qui n'existe pas.
Toby 1 Kenobi
Au cas où quelqu'un se demanderait, belongs_toest juste un alias de referenceset a donc exactement la même fonctionnalité.
Jason Swett
11

Comme réponse supplémentaire à cette question - le modèle doit avoir la ligne suivante pour compléter l'association:

    belongs_to :transferrable_as, class_name: "Course"
    belongs_to :same_as, class_name: "Course"
Diego Diaz de Berenguer
la source
3

Je ne pense pas referencesaccepter l' :asoption, mais vous pouvez créer vos colonnes manuellement ...

create_table :courses do |t| 
  t.string  :name 
  t.integer :course1_id
  t.integer :course2_id 
  t.timestamps 
end 
Ju Nogueira
la source