J'ai les trois modèles suivants (massivement simplifié): Il semble que A.CS soit mis en cache la première fois qu'il est utilisé (par objet) quand je préférerais pas. p> Voici une session de console qui met en évidence le problème (le fluff a été édité) p> C'est bien comme vous l'attendez. L'A.CS va bien par la relation A.BS. P> donc le premier appel à A2.cs (résultant dans une requête de DB) assez correctement renvoyée n ° CS. Le deuxième appel, cependant, montre un manque distinct de CS, même si elles soient bien que celles-ci (aucune requête de DB n'a eu lieu). P> d'abord, la façon dont il devrait fonctionner h2>
et maintenant pour les infiliations de mise en cache h2>
et juste pour tester ma santé mentale n'est pas à blâmer h2>
012 > A.find(a2.id).cs
=> [#<C id: 1, b_id: 1>]
6 Réponses :
(éditer: voir la réponse de Daniel Waltrip, c'est bien mieux que le mien)
Donc, après avoir tapé tout cela et juste vérifier quelque chose de sans rapport, mes yeux sont arrivés à la section "3.1 Contrôle de la mise en cache" de l'association Guide de base. < / P>
Je serai un bon garçon et je partagerai la réponse, car je viens de passer environ huit heures de googling infructueux frustrant. P>
Mais si vous voulez recharger le cache, car les données auraient pu être changé par une autre partie de la demande? Juste passer fidèle à la Appel d'association: p> blockQuote>
xxx pré> donc la morale de l'histoire: RTFM; Tout cela. p>
EDIT: Donc, avoir à mettre
vrai code> partout dans la place n'est probablement pas une si bonne chose car le cache serait contourné même quand il n'a pas besoin d'être. La solution présentée dans les commentaires de Daniel Waltrip est bien meilleure: utilisez
Clear_association_cache code> p>
xxx pré> Alors, non seulement nous devrions nous rechercher. Le code pour
: nodoc: code> s! p> p>
Ok, maintenant je suis de retour à mon code pour le réparer et je n'ai soudainement pas l'aimer. Y a-t-il un moyen de marquer le cache comme étalé? En utilisant le code ci-dessus, je ne veux pas avoir à la classe de litière A avec C (vrai) .blahblahblah partout à la place. Je préférerais avoir une seule fonction pour ajouter B's's et que cela marque n'importe quel CS Cached CS comme étant rassis.
clear_associiation_cache code> faire le tour? Je devais mettre cela dans quelques-uns de mes méthodes de modèle pour éviter d'avoir des données stables dans le cache de requête. Bien que je me sens comme même ce n'est pas la solution la plus élégante.
C'est beaucoup mieux que ma solution. En nettoyant le cache, je n'ai pas à faire en sorte que le cache soit contourné partout. Je fais, cependant encore une légère frustration avec elle: si A avait deux associations (dire has_many: DS code>),
a2.clear_association_cache code> soufflerait également le CS et ds. Maintenant, si seulement Clear_associiation_Cache devait prendre un paramètre pour invalider le cache spécifié, la vie serait merveilleuse.
J'ai trouvé une manière encore meilleure! Je l'ai posté comme solution: Stackoverflow.com/a/21320872/111635 =)
J'ai fait plus de recherches sur cette question. Tout en utilisant J'utiliserai vos modèles d'exemple: A (a beaucoup B, nombre de C à B), B (appartient à A, a plusieurs c) et C (appartient à B). Nous devrons utiliser le première modification du ajoutez un clear_association_cache code> était suffisamment pratique, l'ajoutant après chaque opération annulée le cache ne s'est pas sentie au sec. Je pensais que les rails devraient pouvoir garder une trace de cela. Heureusement, il y a un moyen!
Touch: TRUE CODE> Option pour le
appartient à la méthode code>. Cette méthode met à jour l'attribut
mis à jour code> sur le modèle parent, mais plus important encore, il déclenche également un
après_touch code> rappel. Ce rappel nous permet d'effacer automatiquement le cache de l'association pour toute instance d'un lorsque une instance associée de B ou C est modifiée, créée ou détruite. P>
appartient à code> Appel de méthode pour B et C, ajout
toucher: true code> p>
After_touch code> rappel sur un p >
class A < ActiveRecord::Base
has_many :bs
has_many :cs, through: :bs
after_touch :clear_association_cache
end
Fantastique! Merci de votre aide.
parfait, il suffit d'avoir ce problème exact sur mon application, au revoir la solution JavaScript laidée
@MattramireZ Solution JavaScript B> !? Wat? Que faisiez-vous?
Clear_association_Cache Code> a été rendu privé dans Rails 5 Github.com/Rails/Rails/ COMMIT / 9D56958 alternatives possibles Inclure
recharger code> et appeler
réinitialiser code> sur l'association
Toutes les méthodes d'association sont construites autour de la mise en cache, ce qui permet de conserver la requête la plus récente disponible pour d'autres opérations. Le cache est même partagé entre les méthodes. Par exemple: Mais si vous souhaitez recharger le cache, car des données auraient pu être modifiées par une autre partie de l'application? Il suffit de passer fidèle à l'appel de l'association: p> source http://guides.rubyonRails.org/association_basics.html p> p>
J'ai trouvé une autre façon de désactiver la cache de requête. Dans votre modèle, ajoutez simplement un vérifié le fonctionnement localement. J'ai trouvé cela en regardant Active_Record Strong> code source dans actif_record / associations / association.rb em>: p> par défaut_scope code>
Rails 5 besoin d'avoir quelque chose dans le défaut_scope; J'ai utilisé: par défaut_scope {tout} code>
Pour effacer le cache, utilisez source: Contrôle de la cache P> P> .reload code>
Vous pouvez utiliser l'option étendre code> et fournir un module pour réinitialiser le chargement avant qu'il ne se produise comme:
# Usage:
# ---
#
# has_many :versions,
# ...
# extend: UncachedAssociation
#
module UncachedAssociation
def load_target
@association.reset
super
end
end