2016-06-18 1 views
4

J'utilise Rails 4.2.3 J'ai un modèle avec deux relations avec le même type d'objet,Comment construire mon modèle lorsqu'il contient deux relations avec le même type d'objet?

class MyObject < ActiveRecord::Base 
    belongs_to :user 
    has_many :my_object_times 
… 
    has_one :my_object_time, foreign_key: :linked_my_object_time_id 

Le nom de colonne dans ma base de données pour le « has_one » est « linked_my_object_time_id. » Ce que je n'arrive pas à comprendre, c'est comment écrire le modèle pour l'objet lié. Je sais que je dois mettre deux clauses "belongs_to", mais je ne sais pas comment écrire la seconde. Jusqu'à présent, j'ai

class MyObjectTime < ActiveRecord::Base 
    belongs_to :my_object 

Quand je vais sauver mon objet ...

my_object.linked_my_object_time = my_object_time 
    my_object.save 

Je reçois l'erreur « NoMethodError (méthode non définie linked_my_object_time = » pour # »

Répondre

3

Rails infère comme par magie la clé étrangère d'une association et son modèle nom basé sur le nom de l'association. Si la clé étrangère ou le nom du modèle diffère du nom de l'association, vous devez indiquer explicitement à rails le nom de la classe et la clé étrangère à utiliser. Cela vous permettra d'écrire votre modèle avec deux relations.

Il devrait ressembler à ceci:

class MyObject < ActiveRecord::Base 
    belongs_to :user 
    has_many :my_object_times 
    has_one :linked_my_object_time, class_name: 'MyObjectTime' 

Qu'est-il arrivé ici? J'ai changé le nom de l'association has_one car il doit être différencié en nom de la relation has_many que les rails déduiront. Il n'y a pas de conflit de noms dans ce fichier, mais si vous avez utilisé has_many: my_object_times et has_one: my_object_time, vous ne pourrez pas faire la différence entre les associations (ie. Belongs_to: my_object) dans le modèle MyObjectTime. Comme j'ai changé le nom de l'association, les rails ne peuvent plus déduire le nom du modèle, donc je le spécifie. Mais parce que rails ajoute généralement _id au nom de l'association, il devrait être en mesure d'inférer la colonne de clé étrangère de linked_my_object_time_id du nom de l'association.

Qu'en est-il du modèle MyObjectTime?

class MyObjectTime < ActiveRecord::Base 
    belongs_to :my_object 
    belongs_to :whatever_you_want_to_call_it, class_name: 'MyObject', foreign_key: 'linked_my_object_time_id' 

Le premier belongs_to est l'association inverse pour has_many: my_object_times et rails regarderont pour la colonne my_object_id dans le tableau de MyObjectTime comme prévu. Le second appartient_to doit avoir un nom d'association différent pour être capable de différencier les associations, et puisque le nom de l'association a changé, je dois inclure le nom de la classe et la foreign_key car il ne peut pas être déduit du nom de l'association. J'ai reçu toutes mes informations de here.

(EDIT: syntaxe fixe en association)

+0

"linked_my_object_time" est une clé étrangère de "MyObject" à "MyObjectTime". Dans la mesure où cela est vrai, le "has_one: linked_my_object_Time" ne devrait-il pas appartenir à? – Dave

+0

L'association belongs_to est toujours pour le modèle de la table qui contient la clé étrangère. Si dans votre spécification, vous voulez que MyObject ait ** ** MyObjectTime, alors la clé étrangère sera dans la table MyObjectTime et l'association belongs_to dans le modèle MyObjectTime. Si vous voulez que MyObjectTime ait ** un ** MyObject, alors vous utiliserez l'association has_one dans MyObjectTime et un belongs_to dans MyObject. La clé étrangère serait dans la table MyObject. – hypern

+2

donner ce gars sa prime :) – jaydel

0

Lors de la création d'associations vous peut créer comme ça

rails generate model MyObject => parent

rails g model MyObjectTime my_object:references => enfant

et my_object.rb

class MyObject < ActiveRecord::Base 
    has_one :my_object_time 
end 

alors vous pouvez mon_objet référence de my_object_times comme ce

my_object_time.my_object

+0

droit, mais ce que quand MyObject a deux relations, "has_one" et "has_many", qu'est-ce que le modèle ressemble pour "MyObjectTime"? Si vous pouviez inclure du code dans votre question, vous devriez résoudre mon problème. – Dave