2010-10-01 3 views
1

pourEst-ce que has_many: à travers les associations, travaille pour des modèles qui n'existent qu'en mémoire?

class A < ActiveRecord::Base 
    has_many :bs 
    has_many :cs, :through => :bs 
end 

class B < ActiveRecord::Base 
    belongs_to :a 
    belongs_to :c 
end 

class C < ActiveRecord::Base 
    has_many :bs 
end 

Si je mettre en place une console de rails et faire

a = A.new 
b = a.bs.build 
b.c = C.new 

Puis-je obtenir

a.cs => [] 

mais

a.bs[0].c => c 

Si un est enregistré, alors tout fonctionne . Est-ce prévu? pourquoi l'association à travers ne fonctionne-t-elle pas quand les modèles existent seulement en mémoire? merci

+1

Peut-être, l'association est 'établie' lorsque l'objet est enregistré (ou chargé), pas créé. Est-il obligatoire que vous opériez avec des instances non enregistrées? –

+0

Ce n'est pas, mais je préfère avoir un encombrement aussi faible que possible lors de mes tests, s'ils peuvent être exécutés en mémoire, je vais gagner beaucoup de temps. – pingu

Répondre

1

Je suppose que l'objet a n'a aucune référence à l'objet c créé. Normalement, il lancerait une requête, mais ce ne sera pas le cas car il n'est pas sauvegardé dans db. Je pense qu'il est créé pour les relations db et il ne vérifie simplement pas les références aux objets en mémoire.

Vous pouvez aussi essayer ceci:

a = A.new 
a.cs.build 
a.bs 
=> [] 

mais

a.cs 
=> [created c object] 
+0

Un autre effet secondaire triste de l'entwinement de modèle et de persistance d'ActiveRecord. Rails et AR me rendent heureux la plupart du temps, mais maintenant je suis triste. :( –

0

Voilà comment je travaillais autour:

class A < ActiveRecord::Base 
    has_many :bs 

    def cs 
    bs.map &:c 
    end 

end 

Vous risquez de perdre quelque chose. Par exemple, cs est maintenant en lecture seule, donc vous ne pouvez pas lui attribuer ou build ou create dessus. C'est bien dans mon cas particulier parce que je vais toujours muter bs seulement, ce qui est peut-être une meilleure pratique. De même, les objets plusieurs-à-plusieurs comme B auront normalement certains attributs que vous voulez définir.

Par ailleurs, si C est reliée à B par has_many au lieu de belongs_to changer le code ci-dessus pour utiliser flat_map au lieu de map.

Questions connexes